此处,我们对以太坊的POW共识的实现进行一些简单的梳理,大概了解下POW究竟是如何运作的。
区块结构
首先了解下以太坊的区块结构
1 | // /core/type/block.go |
再看表头结构
1 | type Header struct { |
在表头结构中,与POW算法相关的是区块hash,Nonce以及Difficulty
POW 算法
POW简单的描述可以表示为如下公式1
RAND(hash, Nonce) <= M / Difficulty
M是一个极大的整数,在hash和M确定的情况下,增大Difficulty会使满足条件的Nonce更少,暴力算出的概率会降低,反之亦然
整体的POW算法就是在得到了需要打包的交易之后开始计算Nonce,在算出来后开始打包生成区块,接下来看在以太坊中的具体实现
1 |
|
可以看到整个挖矿方法,在首先获取了Block的header数据之后开始了组装,然后开始根据随机的种子ethash.rand.Int63()
开始遍历的计算hashimotoFull
的结果是否满足new(big.Int).SetBytes(result).Cmp(target) <= 0
,如果满足,则说明找到了正确的nonce,就可以开始打包区块。
接下来我们来看下如何的计算hashimotoFull
的
1 | func hashimoto(hash []byte, nonce uint64, size uint64, lookup func(index uint32) []uint32) ([]byte, []byte) { |
这一部分代码就很头疼了。没有太多的逻辑,完全是符合公式的计算。
最后,还有一个关键点就是如何计算Difficulty
1 | // /consensus/ethash/consensus.go |
这里根据不同的配置计算不同情况下的难度值,这里简单的以拜占庭为例
1 |
|
至此,POW共识的实现简单的梳理完成。