主页 > token.im钱包下载 > 以太坊小知识(三)——区块奖励机制解析

以太坊小知识(三)——区块奖励机制解析

token.im钱包下载 2023-03-22 07:27:38

以太坊的区块奖励机制

在以太坊中以太坊孤儿交易,区块奖励包括三部分,分别是区块奖励(类似于比特币中的50BTC)、交易手续费(这部分在比特币中也存在)、打包叔块的奖励(这部分在比特币中不存在)。

以太坊区块奖励

在以太坊中,每个区块的奖励是 5 个以太币。

blockReward *big.Int = big.NewInt(5e+18) // Block reward in wei for successfully mining a block   5ether

但是在拜占庭硬分叉之后,每个区块的奖励是3ether。

ByzantiumBlockReward   *big.Int = big.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Byzantium

叔块(uncle)和叔块奖励分配机制

每个块中包含的叔块的最大数量为 2。

maxUncles            = 2                 // Maximum number of uncles allowed in a single block

根据以太坊设计指南中的部分,叔块最多只能被其兄弟块的第七代引用。 至于为什么选择7,设计指南中也给出了三个原因。 因此,当区块入链(/core/blockchain.go#(bc *BlockChain) InsertChain(…))验证区块头中的叔块时,只回溯了7层。 下面是验证叔块的关键代码:

/consensus/ethash/consensus.go
func (ethash *Ethash) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
    //...
    // Gather the set of past uncles and ancestors
    uncles, ancestors := set.New(), make(map[common.Hash]*types.Header)
    number, parent := block.NumberU64()-1, block.ParentHash()
    //从当前区块回溯7层(或7代),搜集祖先(主链上的块)和叔伯块
    for i := 0; i < 7; i++ { 
        ancestor := chain.GetBlock(parent, number)  
        if ancestor == nil {
            break
        }
        ancestors[ancestor.Hash()] = ancestor.Header()
        for _, uncle := range ancestor.Uncles() {
            uncles.Add(uncle.Hash())
        }
        parent, number = ancestor.ParentHash(), number-1
    }
    // Verify each of the uncles that it's recent, but not an ancestor  验证叔伯块不是祖先(即不能是主链的块)
    for _, uncle := range block.Uncles() {
    // Make sure every uncle is rewarded only once  每一个叔伯块只能被奖励一次,否则就“多重奖励”了
    hash := uncle.Hash()
    if uncles.Has(hash) {
        return errDuplicateUncle
    }
    uncles.Add(hash)
    // Make sure the uncle has a valid ancestry 该叔伯块为祖先区块,即为主链上的块
    if ancestors[hash] != nil {
        return errUncleIsAncestor
    }
    //叔伯块的祖先不在7层祖先之中 或者 叔伯块和当前区块在同一区块高度
    if ancestors[uncle.ParentHash] == nil || uncle.ParentHash == block.ParentHash() {
        return errDanglingUncle
    }
    //验证叔伯块头部的有效性
    if err := ethash.verifyHeader(chain, uncle, ancestors[uncle.ParentHash], true, true); err != nil {
        return err
    }
    //...
}

叔块激励也是以太坊设计的一大特色。 因为在比特币中以太坊孤儿交易,产生孤块(即以太坊中的叔块)的矿工一般是无利可图的。

计算累积回报的函数

func AccumulateRewards(state *state.StateDB, header *types.Header, uncles []*types.Header) {
    reward := new(big.Int).Set(blockReward)     //侄子区块拿到的恒定区块奖励
    r := new(big.Int)
    for _, uncle := range uncles {
        r.Add(uncle.Number, big8)
        r.Sub(r, header.Number)
        r.Mul(r, blockReward)
        r.Div(r, big8)
        state.AddBalance(uncle.Coinbase, r)     //叔伯块拿到的奖励
        r.Div(blockReward, big32)
        reward.Add(reward, r)                   //侄子区块确认叔伯块拿到的奖励r
    }
    state.AddBalance(header.Coinbase, reward)   //侄子区块获得的总的奖励
}

根据这个函数我们知道,后续区块对每个叔块的引用(将叔块的块摘要值合并到自己块头的相应字段中)会给自己带来1/32*5【其中5个块比特系统对叔块发放的奖励]。 这就是计算后续块中叔块奖励的方式。

ps:拜占庭硬分叉后,一个叔块的奖励为1/32*3。 #5931460区块奖励中的0.09375是1/32*3的结果。