以太坊 区块大小

以太坊的区块大小是不固定的,平均大小大约是20KB左右 。不同于比特币使用区块大小来规定区块的交易量上限,以太坊使用燃料 gas 限制。

燃料限制决定了每个区块中处理的交易量、存储/带宽的上限,因为交易和智能合约中函数的执行都要根据指令的复杂度多少来付出相应的燃料,所以使用燃料限制来约束区块大小是可行的。

以太坊网络中不同的事务,所需要的计算成本各不相同。举个例子,对于转帐交易类事务,每笔交易是固定的 210000 wei,但对于智能合约则不同,有单独的计算方法。

Gaslimit 计算方法

以太坊使用 gaslimit 来限制区块大小,每次开始打包的时候都会计算当前包 Gaslimit 的大小。

// 计算区块的 gaslimit
func CalcGasLimit(parentGasLimit, desiredLimit uint64) uint64 {
	// default 800 0000
	delta := parentGasLimit/params.GasLimitBoundDivisor - 1 //调整值 1/1024的父gaslimit

	limit := parentGasLimit //设定 gaslimit 为父亲limit
	if desiredLimit < params.MinGasLimit {
		// 期望值设定太小,需要调整为 5000
		desiredLimit = params.MinGasLimit
	}
	// If we're outside our allowed gas range, we try to hone towards them
	if limit < desiredLimit {
		// 如果 limit 小于期望值,每次就增大 1/1024
		limit = parentGasLimit + delta

		// 如果 limit 调整后大于期望值,就直接设定为期望值
		if limit > desiredLimit {
			limit = desiredLimit
		}
		return limit
	}
	if limit > desiredLimit {
		// 如果 limit 大于期望值,每次就减小 1/1024
		limit = parentGasLimit - delta
		if limit < desiredLimit {
			// 如果 limit 调整后小于期望值,就直接设定为期望值
			limit = desiredLimit
		}
	}
	return limit
}
// Defaults 包含 Ethereum 主网的默认设置 ethconfig/config.go
var Defaults = Config{
	Ethash: ethash.Config{
		CacheDir:         "ethash",
	},
	NetworkId: 1,
	Miner: miner.Config{
		GasCeil:  8000000, // 默认期望值
		GasPrice: big.NewInt(params.GWei),
		Recommit: 3 * time.Second,
	},
	TxPool:        core.DefaultTxPoolConfig,
}

根据这个公式 Gaslimit 会缓慢增加,从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
		}
        ...
}
// gaslimit 和 gasused 参数定义。位于:protocal_params.go
const (
	GasLimitBoundDivisor uint64 = 1024               // The bound divisor of the gas limit, used in update calculations.
	MinGasLimit          uint64 = 5000               // Minimum the gas limit may ever be.
	MaxGasLimit          uint64 = 0x7fffffffffffffff // Maximum the gas limit (2^63-1).
	GenesisGasLimit      uint64 = 4712388            // 创世纪区块的Gas limit 
	TxGas                 uint64 = 21000 // 单笔交易的Gas used
)

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

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

所以每次打包交易的时候会判断当前区块的Gas余量是否够21000,不够的话会返回Gas不够的错误。比如EVM执行每条指令的时候都会判断gas是否够用,不够就直接返回,然后就打包完成了。

下一章:以太坊为什么会有空块

以太坊区块链中会产生空块,有人认为会对以太坊造成巨大的威胁。CoinFi首席数据科学家Alex Svanevik认为,这一情况是由“间谍挖矿”造成的。针对类似消息,鱼池回应称,近期传播的矿池产生 ...