|
|
@@ -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
|