背景
- 最近、急速にGasLimitが上昇しているというニュースを見て、分散ネットワーク上でどのようにGasLimitを変化させているのかが気になった。
- GasLimitによるcontractの実行制限を排除する方法を知りたいと思った。
- [解説1] GasLimitとは、contract実行に必要なGas(ether)の上限値である。GasLimitの存在によって、高負荷なプログラムの実行を防止し、無限ループ等によるnode停止を防いでいる。
- [解説2] contractとは、ethereum上で動作するアプリケーションである。
ソースコード
go-ethereum/core/block_validator.go
// CalcGasLimit computes the gas limit of the next block after parent.
// The result may be modified by the caller.
// This is miner strategy, not consensus protocol.
func CalcGasLimit(parent *types.Block) *big.Int {
// contrib = (parentGasUsed * 3 / 2) / 1024
contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3))
contrib = contrib.Div(contrib, big.NewInt(2))
contrib = contrib.Div(contrib, params.GasLimitBoundDivisor)
// decay = parentGasLimit / 1024 -1
decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
decay.Sub(decay, big.NewInt(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.
*/
gl := new(big.Int).Sub(parent.GasLimit(), decay)
gl = gl.Add(gl, contrib)
gl.Set(math.BigMax(gl, params.MinGasLimit))
// however, if we're now below the target (TargetGasLimit) we increase the
// limit as much as we can (parentGasLimit / 1024 -1)
if gl.Cmp(params.TargetGasLimit) < 0 {
gl.Add(parent.GasLimit(), decay)
gl.Set(math.BigMin(gl, params.TargetGasLimit))
}
return gl
}
引用元:https://github.com/ethereum/go-ethereum/tree/master/core
パラメータの説明
- gl: New GasLimit
- GasLimitBoundDivisor: GasLimitの増減率
defined by genesis block
- contrib: GasLimit増加方向に寄与
(parentGasUsed * 3 / 2) / GasLimitBoundDivisor
- decay: GasLimit減少方向に寄与
parentGasLimit / GasLimitBoundDivisor -1
GasLimitの計算方法
-
New GasLimit = parentGasLimit - decay + contrib
->parentGasUsed
とparentGasLimit * (2/3)
の大小関係によって、New GasLimitが増減される -
MinGasLimit ≦ New GasLimit ≦ TargetGasLimit
->MinGasLimit
とTargetGasLimit
の範囲に調整される
GasLimitによるcontract実行制限を解除する
-
MinGasLimit
とTargetGasLimit(GenesisGasLimit)
を十分大きくすれば良い。 -
MinGasLimit,GenesisGasLimit
は、genesis.json
orparams/protocol_params.go
で設定する。
まとめ
- Block生成毎に、GasLimitが再計算される。
-
前ブロックのGas使用量
と前ブロックのGasLimit*(2/3)
の大小関係によって、New GasLimitが増減される - GasLimitによるContractの実行制限を排除したい場合は、MinGasLimitとGenesisGasLimitを十分大きくすれば良い。
- GasLimitの計算は、consensus protocolではないため、minerが決定することができる。