core/vm, protocol_params: implement eip-2565 modexp repricing (#21607)
* core/vm, protocol_params: implement eip-2565 modexp repricing * core/vm: fix review concerns
This commit is contained in:
committed by
GitHub
parent
0703c91fba
commit
6f4cccf8d2
@ -58,7 +58,7 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
|
||||
common.BytesToAddress([]byte{2}): &sha256hash{},
|
||||
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
||||
common.BytesToAddress([]byte{5}): &bigModExp{},
|
||||
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
|
||||
common.BytesToAddress([]byte{6}): &bn256AddByzantium{},
|
||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulByzantium{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingByzantium{},
|
||||
@ -71,7 +71,7 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
|
||||
common.BytesToAddress([]byte{2}): &sha256hash{},
|
||||
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
||||
common.BytesToAddress([]byte{5}): &bigModExp{},
|
||||
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
|
||||
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
|
||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
||||
@ -85,7 +85,7 @@ var PrecompiledContractsYoloV2 = map[common.Address]PrecompiledContract{
|
||||
common.BytesToAddress([]byte{2}): &sha256hash{},
|
||||
common.BytesToAddress([]byte{3}): &ripemd160hash{},
|
||||
common.BytesToAddress([]byte{4}): &dataCopy{},
|
||||
common.BytesToAddress([]byte{5}): &bigModExp{},
|
||||
common.BytesToAddress([]byte{5}): &bigModExp{eip2565: false},
|
||||
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
|
||||
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
|
||||
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
|
||||
@ -222,14 +222,19 @@ func (c *dataCopy) Run(in []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
// bigModExp implements a native big integer exponential modular operation.
|
||||
type bigModExp struct{}
|
||||
type bigModExp struct {
|
||||
eip2565 bool
|
||||
}
|
||||
|
||||
var (
|
||||
big0 = big.NewInt(0)
|
||||
big1 = big.NewInt(1)
|
||||
big3 = big.NewInt(3)
|
||||
big4 = big.NewInt(4)
|
||||
big7 = big.NewInt(7)
|
||||
big8 = big.NewInt(8)
|
||||
big16 = big.NewInt(16)
|
||||
big20 = big.NewInt(20)
|
||||
big32 = big.NewInt(32)
|
||||
big64 = big.NewInt(64)
|
||||
big96 = big.NewInt(96)
|
||||
@ -239,6 +244,34 @@ var (
|
||||
big199680 = big.NewInt(199680)
|
||||
)
|
||||
|
||||
// modexpMultComplexity implements bigModexp multComplexity formula, as defined in EIP-198
|
||||
//
|
||||
// def mult_complexity(x):
|
||||
// if x <= 64: return x ** 2
|
||||
// elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072
|
||||
// else: return x ** 2 // 16 + 480 * x - 199680
|
||||
//
|
||||
// where is x is max(length_of_MODULUS, length_of_BASE)
|
||||
func modexpMultComplexity(x *big.Int) *big.Int {
|
||||
switch {
|
||||
case x.Cmp(big64) <= 0:
|
||||
x.Mul(x, x) // x ** 2
|
||||
case x.Cmp(big1024) <= 0:
|
||||
// (x ** 2 // 4 ) + ( 96 * x - 3072)
|
||||
x = new(big.Int).Add(
|
||||
new(big.Int).Div(new(big.Int).Mul(x, x), big4),
|
||||
new(big.Int).Sub(new(big.Int).Mul(big96, x), big3072),
|
||||
)
|
||||
default:
|
||||
// (x ** 2 // 16) + (480 * x - 199680)
|
||||
x = new(big.Int).Add(
|
||||
new(big.Int).Div(new(big.Int).Mul(x, x), big16),
|
||||
new(big.Int).Sub(new(big.Int).Mul(big480, x), big199680),
|
||||
)
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// RequiredGas returns the gas required to execute the pre-compiled contract.
|
||||
func (c *bigModExp) RequiredGas(input []byte) uint64 {
|
||||
var (
|
||||
@ -273,25 +306,36 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
|
||||
adjExpLen.Mul(big8, adjExpLen)
|
||||
}
|
||||
adjExpLen.Add(adjExpLen, big.NewInt(int64(msb)))
|
||||
|
||||
// Calculate the gas cost of the operation
|
||||
gas := new(big.Int).Set(math.BigMax(modLen, baseLen))
|
||||
switch {
|
||||
case gas.Cmp(big64) <= 0:
|
||||
if c.eip2565 {
|
||||
// EIP-2565 has three changes
|
||||
// 1. Different multComplexity (inlined here)
|
||||
// in EIP-2565 (https://eips.ethereum.org/EIPS/eip-2565):
|
||||
//
|
||||
// def mult_complexity(x):
|
||||
// ceiling(x/8)^2
|
||||
//
|
||||
//where is x is max(length_of_MODULUS, length_of_BASE)
|
||||
gas = gas.Add(gas, big7)
|
||||
gas = gas.Div(gas, big8)
|
||||
gas.Mul(gas, gas)
|
||||
case gas.Cmp(big1024) <= 0:
|
||||
gas = new(big.Int).Add(
|
||||
new(big.Int).Div(new(big.Int).Mul(gas, gas), big4),
|
||||
new(big.Int).Sub(new(big.Int).Mul(big96, gas), big3072),
|
||||
)
|
||||
default:
|
||||
gas = new(big.Int).Add(
|
||||
new(big.Int).Div(new(big.Int).Mul(gas, gas), big16),
|
||||
new(big.Int).Sub(new(big.Int).Mul(big480, gas), big199680),
|
||||
)
|
||||
|
||||
gas.Mul(gas, math.BigMax(adjExpLen, big1))
|
||||
// 2. Different divisor (`GQUADDIVISOR`) (3)
|
||||
gas.Div(gas, big3)
|
||||
if gas.BitLen() > 64 {
|
||||
return math.MaxUint64
|
||||
}
|
||||
// 3. Minimum price of 200 gas
|
||||
if gas.Uint64() < 200 {
|
||||
return 200
|
||||
}
|
||||
return gas.Uint64()
|
||||
}
|
||||
gas = modexpMultComplexity(gas)
|
||||
gas.Mul(gas, math.BigMax(adjExpLen, big1))
|
||||
gas.Div(gas, new(big.Int).SetUint64(params.ModExpQuadCoeffDiv))
|
||||
gas.Div(gas, big20)
|
||||
|
||||
if gas.BitLen() > 64 {
|
||||
return math.MaxUint64
|
||||
|
Reference in New Issue
Block a user