内容简介:Ethash实现了PoW,PoW的精妙在于通过一个随机数确定,矿工确实做了大量的工作,并且是没有办法作弊的。接下来将介绍:挖矿的本质是找到一个随机数,证明自己做了很多工作(计算)。在Ethash中,该随机数称为
前言
Ethash实现了PoW,PoW的精妙在于通过一个随机数确定,矿工确实做了大量的工作,并且是没有办法作弊的。接下来将介绍:
- Ethash的挖矿本质。
- Ethash是如何挖矿的。
- 如何验证Ethash的随机数。
Ethash的挖矿本质
挖矿的本质是找到一个随机数,证明自己做了很多工作(计算)。在Ethash中,该随机数称为 Nonce
,它需要满足一个公式:
Rand(hash, nonce) ≤ MaxValue / Difficulty
其中,
HashNoNonce()
以上参数中,在得到区块头的hash之后,只有nonce是未知的。
公式的含义是,使用hash和nonce生成的哈希值必须落在合法的区间。利用下图介绍一下,Rand()函数结果取值范围是[0, MaxValue],但只有计算出的哈希值在[0, MaxValue / Difficulty]内,才是符合条件的哈希值,进而该Nonce才是符合条件的,否则只能再去寻找下一个Nonce。
以太坊可以通过调整Difficulty来调节当前挖矿的难度,Difficulty越大,挖矿的难度越大。当Difficulty越大时, MaxValue / Difficulty
越小,合法的哈希值范围越小,造成挖矿难度增加。
哈希值满足条件的概率是 p = (MaxValue / Difficulty) / MaxValue = 1 / Difficulty
,矿工需要进行 1 / p = Difficulty
次的判断,才有可能找到一个符合条件的Nonce,当前以太坊难度为3241847139727150。
如何挖矿
Ethash挖矿的主要思想是,开启多个线程去寻找符合条件的Nonce,给每个线程分配一个随机数,作为本线程的Nonce的初始值,然后每个线程判断当前的Nonce是否符合上面的公式,如果不符合,则把Nonce加1,再次进行判断,这样不定的迭代下去,直到找到一个符合条件的Nonce,或者挖矿被叫停。
接下来介绍挖矿的几个主要函数的实现,它们是:
- 挖矿的入口Seal函数。
- 挖矿函数mine函数。
- 挖矿需要的数据cache和dataset。
- Rand()函数的实现hashimotoFull和hashimoto。
挖矿入口Seal()
Seal
是引擎的挖矿入口函数,它是管理岗位,负责管理挖矿的线程。它发起多个线程执行 Ethash.mine
进行并行挖矿,当要更新或者停止的时候,重新启动或停止这些线程。
挖矿函数mine()
mine
函数负责挖矿。 Seal
在启动每一个 mine
的时候,给它分配了一个 seed
, mine
会把它作为 Nonce
的初始值,然后生成本高度使用的 dataset
,然后把 dataset, hash, nonce
传递给 hashimotoFull
函数,这个函数可以认为是原理介绍中的 Rand
随机函数,他会生成哈希值 Result
,当 Result <= Target
的时候,说明哈希值落在符合条件的区间了, mine找到了符合条件的Nonce
,使用Digest和nonce组成新的区块后,发送给 Seal
,否则验证下一个Nonce是否是符合条件的。
挖矿需要的数据cache和dataset
dataset
用来生成 Result
,而 cache
用来生成 dataset
。至于如何使用 dataset
生成 Result
在 hashimoto()
中讲述,本节介绍如何生成dataset。
dataset和cache中存放的都是伪随机数,每个epoch的区块使用相同的cache和dataset,并且dataset需要暂用大量的内存。刚开始时cache是16MB,dataset是1GB,但每个epoch它们就会增大一次,它们的大小分别定义在 datasetSizes
和 cacheSizes
,dataset每次增长8MB,最大能达到16GB,所以挖矿的节点必须有足够大的内存。
使用cache生成dataset。使用cache的部分数据,进行哈希和异或运算,就能生成一组dataset的item,比如下图中的cache中黄色块,能生成dataset中的黄色块,最后把这些Item拼起来就生成了完整的Dataset,完成该功能的函数是 generateDataset
。
dataset.generate()
是dataset的生成函数,该函数只执行一次,先使用 generateCache()
生成cache,再将cache作为 generateDataset()
的入参生成dataset,其中需要重点关注的是 generateDatasetItem()
,该函数是根据部分cache,生成一组dataset item,验证PoW的nonce的时候,也需要使用该函数。
Rand()的实现hashimotoFull()和hashimoto()
hashimotoFull
功能是使用dataset、hash和nonce生成Digest和Result。它创建一个获取dataset部分数据的lookup函数,该函数能够返回连续的64字节dataset中的数据,然后把lookup函数、hash和nonce传递给 hashimoto
。
hashimoto
的功能是根据hash和nonce,以及lookup函数生成 Digest
和 Result
,lookup函数能够返回64字节的数据就行。它把hash和nonce合成种子,然后根据种子生成混合的数据mix,然后进入一个循环,使用mix和seed获得dataset的行号,使用lookup获取指定行的数据,然后把数据混合到mix中,混合的方式是使用 哈希和异或运算
,循环结束后再使用哈希和异或函数把mix压缩为64字节,把mix转为小端模式就得到了Digest,把seed和mix进行hash运算得到Result。
如何验证
PoW的验证是证明出块人确实进行了大量的哈希计算。Ethash验证区块头中的 Nonce
和 MixDigest
是否合法,如果验证通过,则认为出块人确实进行了大量的哈希运算。验证方式是确定区块头中的 Nonce
是否符合公式,并且区块头中的 MixDigest
是否与使用此 Nonce
计算出的是否相同。
验证与挖矿相比,简直是毫不费力,因为:
hashimoto
接下来介绍验证函数 VerifySeal()
,以及根据cache生成 Digest
和 Result
的 hashimotoLight()
。
验证函数VerifySeal
Ethash.VerifySeal
实现PoW验证功能。首先先判断区块中的Difficulty是否匹配,然后生成(获取)当前区块高度的cache,把cache和nonce传递给 hashimotoLight
,该函数能根据 cache, hash, nonce
生成Digest和Result,然后校验Digest是否匹配以及Result是否符合条件。
hashimotoLight函数
hashimotoLight
使用 cache, hash, nonce
生成 Digest
和 Result
。 生成Digest和Result只需要部分的dataset数据,而这些部分dataset数据时可以通过cache生成,因此也就不需要完整的dataset
。它把 generateDatasetItem
函数封装成了获取部分dataset数据的lookup函数,然后传递给 hashimoto
计算出Digest和Result。
FAQ
-
Q:每30000个块使用同一个dataset,那可以提前挖出一些合法的Nonce?
A: 不行。提前挖去Nonce,意味着还不知道区块头的hash,因此无法生成合法的Nonce。 -
Q:能否根据符合条件的哈希值,反推出Nonce呢?
A:不行。因为哈希运算具有不可逆性,不能根据摘要反推出明文,同理根据哈希值也无法推出Nonce。
以上所述就是小编给大家介绍的《以太坊源码分析:共识(3)Ethash》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 以太坊源码分析:共识(2)引擎
- 以太坊源码分析:共识(1)矿工
- 以太坊源码分析—Ethash共识算法
- 局限于算法的“共识”不是“真共识”
- 科普 | 分布式共识的工作原理,Part-3:使用同步假设的共识算法
- 科普 | 分布式共识的工作原理,Part-4:非确定性共识算法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Persuasive Technology
B.J. Fogg / Morgan Kaufmann / 2002-12 / USD 39.95
Can computers change what you think and do? Can they motivate you to stop smoking, persuade you to buy insurance, or convince you to join the Army? "Yes, they can," says Dr. B.J. Fogg, directo......一起来看看 《Persuasive Technology》 这本书的介绍吧!