比特币是通过固定大小控制区块,上限是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,比如说2200,
但是后面计算交易的时候实际耗费大于2200,导致最终的区块消耗Gas大于GasLimit呢
但是代码太多地方了不好挑,大概意思就是:
每次需要消耗gas的时候都会判断Gaslimit是否够用,不够的话会返回Gas不够的错误。
转载请标明出处:以太坊如何控制区块大小
文章来源: 以太坊如何控制区块大小