请选择 进入手机版 | 继续访问电脑版
点击联系客服
客服QQ: 客服微信:
查看: 64|回复: 50

以太网广场(ETH)挖掘算法Ethash源代码分析

[复制链接]

1

主题

1

帖子

-7

积分

限制会员

积分
-7
发表于 2021-9-15 14:41:30 | 显示全部楼层 |阅读模式
https://github.com/ethereum/go-ethereum  3359 eth  . wiki/en/fundamentals/mining  dataset(Dag)生成过程

Consensus/ethash/algorithm.go

Block  number  - seed  - cache  - dataset

Consensus/ethash/sealer.go

//挖掘矿山核心逻辑,根据种子计算nonce

//mine  is  the  actual  proof-of-work  miner  that  searches  for  a  nonce  starting  from

//seed  that  results  in  correct  final  block  difficulty。

Func(Ethash  * Ethash)Mine(block  * types  . block,int,seed  uint  64,abort  chanstruct  {},found

//Extract  some  data  from  the  header

Var(

标头=块
">.Header()  // 区块头
                hash    = ethash.SealHash(header).Bytes() // 获取区块的hash
                target  = new(big.Int).Div(two256, header.Difficulty) // target =  2^256 / difficulty
                number  = header.Number.Uint64() // 区块高度
                dataset = ethash.dataset(number, false) // 同步生成DAG数据(如果已经生成则直接读取)
        )
        // Start generating random nonces until we abort or find a good one
        var (
                attempts  = int64(0)
                nonce     = seed  // 随机数
                powBuffer = new(big.Int)
        )
        logger := ethash.config.Log.New("miner", id)
        logger.Trace("Started ethash search for new nonces", "seed", seed)
search:
        for {
                select {
                case abort: // 什么情况下会终止呢?  应该是接收到其他矿工
                        // Mining terminated, update stats and abort
                        logger.Trace("Ethash nonce search aborted", "attempts", nonce-seed)
                        ethash.hashrate.Mark(attempts)
                        break search
                default:
                        // We don't have to update hash rate on every nonce, so update after after 2^X nonces
                        attempts++
                        if (attempts % (1  15)) == 0 {
                                ethash.hashrate.Mark(attempts)
                                attempts = 0
                        }
                        // ================== Ethash的核心逻辑 =================
                        // Compute the PoW value of this nonce
                        digest, result := hashimotoFull(dataset.dataset, hash, nonce)
                        if powBuffer.SetBytes(result).Cmp(target)  0 { // target 由 difficulty 决定,
                                // Correct nonce found, create a new header with it
                                header = types.CopyHeader(header)
                                header.Nonce = types.EncodeNonce(nonce)
                                header.MixDigest = common.BytesToHash(digest)
                                // Seal and return a block (if still needed)
                                select {
                                case found  block.WithSeal(header):  // 通知找到了nonce
                                        logger.Trace("Ethash nonce found and reported", "attempts", nonce-seed, "nonce", nonce)
                                case abort:
                                        logger.Trace("Ethash nonce found but discarded", "attempts", nonce-seed, "nonce", nonce)
                                }
                                break search
                        }
                        nonce++  // 继续尝试
                }
        }
        // Datasets are unmapped in a finalizer. Ensure that the dataset stays live
        // during sealing so it's not unmapped while being read.
        runtime.KeepAlive(dataset)
}

consensus/ethash/consensus.go
验证PoW的有效性

// verifySeal checks whether a block satisfies the PoW difficulty requirements,
// either using the usual ethash cache for it, or alternatively using a full DAG
// to make remote mining fast.
func (ethash *Ethash) verifySeal(chain consensus.ChainHeaderReader, header *types.Header, fulldag bool) error {
        // If we're running a fake PoW, accept any seal as valid
        if ethash.config.PowMode == ModeFake || ethash.config.PowMode == ModeFullFake {
                time.Sleep(ethash.fakeDelay)
                if ethash.fakeFail == header.Number.Uint64() {
                        return errInvalidPoW
                }
                return nil
        }
        // If we're running a shared PoW, delegate verification to it
        if ethash.shared != nil {
                return ethash.shared.verifySeal(chain, header, fulldag)
        }
        // Ensure that we have a valid difficulty for the block
        if header.Difficulty.Sign()  0 {
                return errInvalidDifficulty
        }
        // Recompute the digest and PoW values
        number := header.Number.Uint64()
        var (
                digest []byte
                result []byte
        )
        // 全节点
        // If fast-but-heavy PoW verification was requested, use an ethash dataset
        if fulldag {
                dataset := ethash.dataset(number, true)
                if dataset.generated() {
                        digest, result = hashimotoFull(dataset.dataset, ethash.SealHash(header).Bytes(), header.Nonce.Uint64())
                        // Datasets are unmapped in a finalizer. Ensure that the dataset stays alive
                        // until after the call to hashimotoFull so it's not unmapped while being used.
                        runtime.KeepAlive(dataset)
                } else {
                        // Dataset not yet generated, don't hang, use a cache instead
                        fulldag = false
                }
        }
        // 轻节点
        // If slow-but-light PoW verification was requested (or DAG not yet ready), use an ethash cache
        if !fulldag {
                cache := ethash.cache(number) // 使用dag缓存代替DAG文件
                size := datasetSize(number)
                if ethash.config.PowMode == ModeTest {
                        size = 32 * 1024
                }
                // 进行一次hashmoto运算
                digest, result = hashimotoLight(size, cache.cache, ethash.SealHash(header).Bytes(), header.Nonce.Uint64())
                // Caches are unmapped in a finalizer. Ensure that the cache stays alive
                // until after the call to hashimotoLight so it's not unmapped while being used.
                runtime.KeepAlive(cache)
        }
        // 判断mixHash是否一致
        // Verify the calculated values against the ones provided in the header
        if !bytes.Equal(header.MixDigest[:], digest) {
                return errInvalidMixDigest
        }
        // result是否小于 target
        target := new(big.Int).Div(two256, header.Difficulty)
        if new(big.Int).SetBytes(result).Cmp(target) > 0 {
                return errInvalidPoW
        }
        return nil
}
回复

使用道具 举报

1

主题

377

帖子

-146

积分

限制会员

积分
-146
发表于 2021-9-15 14:42:48 | 显示全部楼层
找到好贴不容易,我顶你了,谢了
回复

使用道具 举报

0

主题

392

帖子

-182

积分

限制会员

积分
-182
发表于 2021-9-15 15:04:41 | 显示全部楼层
学习了,谢谢分享、、、
回复

使用道具 举报

0

主题

377

帖子

-161

积分

限制会员

积分
-161
发表于 2021-9-15 15:24:45 | 显示全部楼层
相当不错,感谢无私分享精神!
回复

使用道具 举报

1

主题

335

帖子

-134

积分

限制会员

积分
-134
发表于 2021-9-15 15:44:59 | 显示全部楼层
学习了,不错,讲的太有道理了
回复

使用道具 举报

1

主题

350

帖子

-149

积分

限制会员

积分
-149
发表于 2021-9-15 16:05:14 | 显示全部楼层
沙发!沙发!
回复

使用道具 举报

0

主题

333

帖子

-141

积分

限制会员

积分
-141
发表于 2021-9-15 16:25:35 | 显示全部楼层
帮帮顶顶!!
回复

使用道具 举报

1

主题

354

帖子

-138

积分

限制会员

积分
-138
发表于 2021-9-15 16:48:29 | 显示全部楼层
不错不错,楼主您辛苦了。。。
回复

使用道具 举报

0

主题

363

帖子

-164

积分

限制会员

积分
-164
发表于 2021-9-15 17:10:30 | 显示全部楼层
沙发!沙发!
回复

使用道具 举报

0

主题

363

帖子

-157

积分

限制会员

积分
-157
发表于 2021-9-15 17:31:56 | 显示全部楼层
找到好贴不容易,我顶你了,谢了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|无图版|手机版|小黑屋|汕头@IT精英团

Powered by Discuz! X3.4 © 2021 Comsenz Inc.

GMT+8, 2021-9-27 02:34 , Processed in 0.249601 second(s), 19 queries .

快速回复 返回顶部 返回列表