以太坊如何控制区块大小

比特币是通过固定大小控制区块,上限是1M

以太坊采用了完全不同于比特币的做法,使用gaslimit来限制,所以以太坊的区块大小是不固定的

Gaslimit确定

每次开始打包的时候都会确定当前包Gaslimit的大小,以下函数确定大小

func CalcGasLimit(parent *types.Block) uint64 {
	// contrib = (parentGasUsed * 3 / 2) / 1024
	contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor

	// decay = parentGasLimit / 1024 -1
	decay := parent.GasLimit()/params.GasLimitBoundDivisor - 1

	/*
		strategy: gasLimit of block-to-mine is set based on parent's
		gasUsed value.  if parentGasUsed > parentGasLimit * (2/3) then we
		increase it, otherwise lower it (or leave it unchanged if it's right
		at that usage) the amount increased/decreased depends on how far away
		from parentGasLimit * (2/3) parentGasUsed is.
	*/
	limit := parent.GasLimit() - decay + contrib
	if limit < params.MinGasLimit {
		limit = params.MinGasLimit
	}
	// however, if we're now below the target (TargetGasLimit) we increase the
	// limit as much as we can (parentGasLimit / 1024 -1)
	if limit < params.TargetGasLimit {
		limit = parent.GasLimit() + decay
		if limit > params.TargetGasLimit {
			limit = params.TargetGasLimit
		}
	}
	return limit
}

其中,targetGasLimit是代码中配置的GenesisGasLimit(现在是4712388)

从代码中的注释描述看意思是当父区块Gas使用量>2/3的时候,会较上次加大gaslimit,反之减小

根据这个公式Gaslimit是会缓慢增加的(当每次使用量都超过2/3的话),从etherscan上也可以看出现在的Gaslimit是800万左右,明显比GenesisGasLimit大了不少了。

公式我就不解释了,自己手动推算一下就能算出来的

区块Gas的使用

在打包区块内每笔交易的时候,会先判断当前区块gas还够不够用

func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsByPriceAndNonce, bc *core.BlockChain, coinbase common.Address) {
	gp := new(core.GasPool).AddGas(env.header.GasLimit)

	var coalescedLogs []*types.Log

	for {
		// If we don't have enough gas for any further transactions then we're done
		if gp.Gas() < params.TxGas {
			log.Trace("Not enough gas for further transactions", "gp", gp)
			break
		}
        ...
}

在这个for循环打包交易的时候,会先判断gp.Gas()是否小于params.TxGas(程序中配置的21000)

gp.Gas()就是计算的区块GasLimit,TxGas是一笔普通转账交易使用的最小Gas。

所以每次打包交易的时候会判断当前区块的Gas余量是否够21000,不够的话就不会打包交易了

那么会不会出现这种情况,区块的Gas使用量大于GasLimit呢,也就是说现在区块的Gas余量大于21000,比如说22000,

但是后面计算交易的时候实际耗费大于22000,导致最终的区块消耗Gas大于GasLimit呢,肯定是不会了

但是代码太多地方了不好挑,大概意思就是:

每次需要消耗gas的时候都会判断Gaslimit是否够用,不够的话会返回Gas不够的错误。比如EVM执行每条指令的时候都会判断gas是否够用,不够就直接返回,然后就打包完成了



你可能感兴趣的:(区块链)