挖矿的过程:选择出块节点的过程——谁用好了用对了稀缺资源,谁稀缺资源多谁就更有可能是出块节点,并获得奖励
POW工作量证明:算力作为稀缺资源——解数学题(难于计算,易于验证,解对了你就是出块节点)
POST时间空间证明:存储空间和时间作为稀缺资源
CHIA的场景:用户将数据存储在硬盘驱动器上一段时间,而赢得区块记账权利的机会与分配的空间大小成正比。该机制通过与彩票中奖类似的方式,允许所有普通用户均可参与其中
BTC的场景:
用户通过算力解数学题,而赢得区块记账权利
用户持有的稀缺资源作为一个赢得记账权利的机会,稀缺资源越多赢的机会越大
提示:以下是本篇文章正文内容,下面案例可供参考
CHIA的空间证明——若想赢得奖励,我需要向验证者证明我有这么多稀缺资源
空间证明的总流程:
1、验证者向证明者发出一项质询(challange)
2、证明者向验证者证明在某一时刻,验证者保留了特定数量的存储空间
空间证明的实现细节:
https://www.chia.net/assets/Chia_Proof_of_Space_Construction_v1.1.pdf
空间证明的三个阶段:
1、标绘(Plotting) 2、证明(Proving,即挖矿过程) 3、验证(Verifying)
1、标绘(Plotting) 2、证明(Proving,即挖矿过程) 3、验证(Verifying)
1、标绘(Plotting)——initialize space——“P盘”
2,3,4:质询->证明过程(挖矿)->检查质询的证明
是任何拥有至少 100 GiB 可用空间的人,也可能有拥有大量未使用空间的企业。存储空间容量不设上限
标绘过程:
可能持续几个小时到几天的时间,该过程只需执行一次。经过初始化的空间被一个称为 plot 的文件占用。绘图文件(plot 文件)的大小由参数 决定,其中占用空间为 780∗2−10,而最小的 取值为 32,即文件大小为 101.4 GiB
标绘时间:
从 Chia 1.0 版本始,使用快速的商业计算机能够在六小时之内创建一张 k32 绘图文件,而对于具有单核心 CPU 以及几 GB内存的慢速计算机来说,这个过程可能需要 24 个小时。PopSpace 的构建基于 Beyond Hellman 的这篇论文,但是嵌套了 6次并包含较小的修改。
参考论文(Beyond Hellman):论文链接
标绘文件:
以 =32 为例,经过以上操作,我们得到的 plot 文件包含七个具有随机数据的查找表,每张表中有 2 个条目。表 中包含两个指向表 −1 (上一个表)的指针。最后,每张表的条目都包含一对介于 0 和 2 之间的整数,称为“x 值”。空间证明是具有一定数学关系的 64 个 x 值的集合。
证明过程:
证明(Proving)过程旨在通过对挖矿用户发出一系列质询来证明他们已经按照共识中的指定方法使用了一定量的空间。当挖矿用户接收到质询后,他们需要检查自己的 plot 文件,生成证明,并且将证明提交到网络中以进行验证。
从使用者的角度来看:
关键代码:chia/plotting/create_plots.py
create_plots.py:46:create_plots()
它被两个函数调用:
1、class BlockTools->init_plots->create_plots(但是BlockTools中标记了注释:Tools to generate blocks for testing,故可以先略过)
2、create_cmd->中间夹着class Params(object)->最后调用create_plots(Params(), ctx.obj[“root_path”])
Params包含的参数:
size:Plot size//开垦农田(标绘文件)的大小
num:Number of plots or challenges//要开垦的农田数量
buffer:Megabytes for sort/plot buffer
num_threads:Number of threads to use//要使用的线程数
buckets:Number of buckets//桶排序中桶的数量(推荐128)
stripe_size:DEFAULT_STRIPE_SIZE(65535)//每次写入物理磁盘的数据量(KB)
alt_fingerprint:alternative fingerprint
pool_contract_address:Address of where the pool reward will be sent to. Only used if alt_fingerprint and pool public key are None
farmer_public_key:Hex farmer public key
pool_public_key:Hex public key of pool
tmp_dir:Temporary directory for plotting files//保存农田文件的临时目录,我们建议您使用快速的固态硬盘
tmp2_dir:Second temporary directory for plotting files//第二临时目录
final_dir:Final directory for plots (relative or absolute)//保存农田文件的最终目录。我们建议您使用大容量、慢速的硬盘(比如外置机械硬盘)
plotid:PlotID in hex for reproducing plots (debugging only)
memo:Memo in hex for reproducing plots (debugging only)
nobitfield:Disable bitfield
exclude_final_dir:Skips adding [final dir] to harvester for farming
接下来看一下,这个函数拿这些参数做了什么
其关键在于:create_plots.py:163,这里注意调用了chiapos的包,这就是另外一个项目了
继续深入到chiapos,这是一个c++编写的程序,用来与磁盘进行读写交互的,地址是:
https://github.com/Chia-Network/chiapos
create_ployts.py:163调用了chiapos项目中的DiskPlotter,位于plotter_disk.hpp:53
根据日志提示可以看到P盘分为四步:分别在206,232, 253,272,四部分别为:
Starting phase 1/4: Forward Propagation into tmp files…——对应211行RunPhase1,后面类似,
Starting phase 2/4: Backpropagation without bitfield into tmp files…
Starting phase 3/4: Compression without bitfield from tmp files into tmp_2_filename
Starting phase 4/4: Write Checkpoint tables into tmp_2_filename
(注意,以上2,3步有分支,但调用的RunPhase函数相同)
接下来我们看一下每一步做了什么,对应到phase1.hpp,phase2.hpp,phase3.hpp,phase4.hpp
phase1中,就是plot标绘过程中绘图文件(农场)的创建了,重点关注646行:
for (uint8_t table_index = 1; table_index < 7; table_index++)
可以看到,绘图文件一共会创建6个table,注释是这么写的:
For tables 1 through 6, sort the table, calculate matches, and write the next table. This is the left table index.
对于表1到表6,对表进行排序、计算匹配项并编写下一个表。这是左表索引。
在这里停下,我们已经基本明白了在这里farmer要P出一个空间作为稀缺资源的证明,但这样没用,你只有算力,不挖块,根本无法获得币
那么接下来的关键就是:如何证明?——质询
附:此过程暂需以整个CHIA流程图作为支撑,故接下来我们挨个步骤看一下过程
CHIA网络层全节点在建立新区块的时候都有新的challenge_hash,即挑战的hash值,挑战成功,即可获得记账权
可以发现每一个challenge_hash都在不同阶段的不同作用,先来看第一个:DeclareProofOfSpace
也即:声明空间证明
对应到full_node_api.py:630:declare_proof_of_space()产生challenge_hash,然后经由节点网络传播
接下来再看NewProofOfSpace,有两个地方使用它,harvest_api.py:50以及farmer_api.py:29
harvest_api.py:50看注释:
farmer_api.py:29看注释:
farmer_api.py:110及105,返回给full_node的是: sp_hash,challange_hash,以及identifier
现在空间证明给你了,接下来的任务就是full_node的了
在这里做一个小总结
实际上,farmer是不负责打包区块的,它也不负责保存区块。
它只负责提供证明
而打包区块,保存完整区块数据的是全节点
那么full_node用什么接收,然后做了什么呢
看full_node_api.py:918:signed_value及其注释
区块头的hash签名(由harvester完成)。这足以创造一个未完成的块
剩下只需要一个时间证明就可以完成。如果签名有效,我们称之为未完成的块步骤。
所以说,现在这个收到了这么多sp_hash的块叫做unfinished_block,下面关注下全节点full_node:
bundle_tools.py:负责将收来的tx捆绑打包压缩
full_node_store.py:负责处理区块(区块状态,分叉了怎么办等等)
block_store.py,coin_store.py:负责处理打包区块,以及区块与账户存款在本地的保存(sql)
full_node接下来做了什么:看full_node_api:977与983,它发给了timelord,当然,timelord也在fullnode的节点中
而在timelord.py:990行,timelord把proof_of_time交还给了full_node
注意,这之间还有个proof_of_weight的问题需要解决,用来最终决定出块者是谁,在full_node_api的231行
最后,再full_node_api:276行,full_node将最后的区块传播了出去
可以做一个总结:CHIA项目中除了,农民,耕种,其实还有一个非常重要的就是Harvesters收割机
“收割机”对已经“耕种”过的“P盘”,这个过程即空间证明,去查找匹配预估PLOT文件,寻找符合爆块的预估hash,检查空间证明是否足够好
并不是空间证明之后寻找到了符合hash就能爆块,CHIA同样需要像“BTC的pow一样”做“难以计算”且“易于验证”的函数
以下就是全节点交给timelord所要做的事情了:
对空间证明找到的hash,运用“VDF”,即可验证的延时函数(数学背景:密码学、群环域)(这个函数是按轮次,按顺序运算,不可靠堆CPU提高计算速度,每一轮都以上一轮的输出作为输入,提高计算时间,只需提高计算轮次即可)输入之后,几个轮次之后,输出的结果只能是一个唯一确定的结果数值
“时间证明”就是上述过程,也就是把空间证明的hash,运用VDF可验证延迟函数,CPU工作,运算出结果,谁最先计算出来,谁就能获得最新区块的记账权,因为获得XCH奖励(补充:并不耗电,因为不能CPU并行,相对更绿色)
现在可以对farmer,harvest,timelord,fullnode做一个总结
farmer是农场主,P盘是开辟农场,harvest是农场的仆人(知道这个农场的所有信息),fullnode是农业管理部门,timelord是下属的会计部门:
1、农业管理部门每月都会发布一次彩票抽奖,并把抽奖活动的幸运数字下发到各个农场。
2、农场主收到幸运数字后,让仆人去把自家农场的所有信息,计算出一个彩票,然后将彩票提交给农业管理部门
3、农业管理部门收到后,交给会计部门再对所有彩票进行再次计算各个农场主的幸运数字
4、最后谁离幸运数字更近,甚至等于幸运数字,农业管理部门就会把奖励发给农场主
先明确一些基本的东西
POST中的节点是有身份的,以太坊当中是对等节点,不存在不同的身份(除了出块时)
方案一:直接提出一个方案的话:
在POW共识上修改,在以太坊FinalizeAndAssemble组装区块时,先按原样组装
但是要对区块结构相对POST区块的格式进行修改,也就是需要留一个空,用来塞入出块节点,奖励者,相关的时空证明
接下来,广播这个尚未完成的区块(注意区块中要带一个时间),此时没有空间证明也没有时间证明。
接下来,每个节点收到区块后本地出一个空间证明,同时VDF后出一个时间证明(依据区块中带着的时间),然后广播空间证明和实践证明的最后权重
每个节点将收到权重进行排序,选择最高的节点地址进行本地区块完善,账本记录发放奖励
以太坊原有的网络交互需要:收txs打包广播块——收块验证并更新账本,一步就够
CHIA原有的网络交互需要:收txs打包广播挑战——收挑战出证明——收证明再证明出权重——广播块,需要3步
上面这个设计需要:挖块广播未完成块——收块出证明并广播权重——收权重比较并更新账本,需要2步
第二个方案:注意geth中还有个POA共识
简单解释一下这个共识: 1、依靠预设好的授权节点(signers),负责产生block 2、由已授权的signer选举(投票超过50%)加入新的signer
工作流程如下:
1、启动挖矿后, 该组signers开始对生成的block进行 签名并广播,签名结果 保存在区块头的Extra字段中
2、Extra中更新当前高度已授权的 所有signers的地址 ,因为有新加入或踢出的signer
3、每一高度都有一个signer处于IN-TURN状态, 其他signer处于OUT-OF-TURN状态,
IN-TURN的signer签名的block会 立即广播 , OUT-OF-TURN的signer签名的block会 延时一点随机时间后再广播, 保证IN-TURN的签名block有更高的优先级上链
所以尝试下基于POA修改,signer即为full_node,拿来的txs经过FinalizeAndAssemble交给clique文件夹下的POA共识,关注clique.go下的Seal函数,在这里面留一个空,用来填充证明,后面的广播,也就是只广播一个challangehash,关注“以太坊挖矿过程”的第12张
后面的话,就与CHIA一样,farmer收到challenge后用同样方式出证明,而针对chia的farmer节点而言,似乎是不需要作任何修改?只需要针对challangehash返回对应的sphash即可,后面signer接到后由signer的timelord(新增)返回权重,然后决定奖励哪个矿工,广播区块即可
总结的话,就是使用geth以POA实现的节点去替换full_node,并增加timelord作为时间证明
这样的话,fullnode打包节点改变状态可以依照原有以太坊节点EVM来进行(支持智能合约)
现在来关注下具体的技术实现:先来看geth的clique(网上有一些geth以POA启动的教程)
好像是可行的,也就是第一步,我们产生所谓的unfinished block这一步
而下一步,就是交给signer本地的timelord去进行时间证明,这里面很讨厌的一点是,我必须交给signer(也就是full node)才能进行时间证明(当然这样完全没问题)并产生权重
POA+POST=POAST