From 3c139b8a6866ebf6f48530a745e008f52f59c94e Mon Sep 17 00:00:00 2001 From: Guillaume Ballet Date: Thu, 17 Jan 2019 16:38:30 +0100 Subject: [PATCH] core: reuse the gas calculation bigints in bigmodexp precompile --- core/vm/contracts.go | 46 +++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 20b741f8f1..d8268adc86 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -147,7 +147,11 @@ func (c *dataCopy) Run(in []byte) ([]byte, error) { } // bigModExp implements a native big integer exponential modular operation. -type bigModExp struct{} +type bigModExp struct { + baseLen *big.Int + expLen *big.Int + modLen *big.Int +} var ( big1 = big.NewInt(1) @@ -165,11 +169,10 @@ var ( // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bigModExp) RequiredGas(input []byte) uint64 { - var ( - baseLen = new(big.Int).SetBytes(getData(input, 0, 32)) - expLen = new(big.Int).SetBytes(getData(input, 32, 32)) - modLen = new(big.Int).SetBytes(getData(input, 64, 32)) - ) + c.baseLen = new(big.Int).SetBytes(getData(input, 0, 32)) + c.expLen = new(big.Int).SetBytes(getData(input, 32, 32)) + c.modLen = new(big.Int).SetBytes(getData(input, 64, 32)) + if len(input) > 96 { input = input[96:] } else { @@ -177,13 +180,13 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { } // Retrieve the head 32 bytes of exp for the adjusted exponent length var expHead *big.Int - if big.NewInt(int64(len(input))).Cmp(baseLen) <= 0 { + if big.NewInt(int64(len(input))).Cmp(c.baseLen) <= 0 { expHead = new(big.Int) } else { - if expLen.Cmp(big32) > 0 { - expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), 32)) + if c.expLen.Cmp(big32) > 0 { + expHead = new(big.Int).SetBytes(getData(input, c.baseLen.Uint64(), 32)) } else { - expHead = new(big.Int).SetBytes(getData(input, baseLen.Uint64(), expLen.Uint64())) + expHead = new(big.Int).SetBytes(getData(input, c.baseLen.Uint64(), c.expLen.Uint64())) } } // Calculate the adjusted exponent length @@ -192,14 +195,14 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { msb = bitlen - 1 } adjExpLen := new(big.Int) - if expLen.Cmp(big32) > 0 { - adjExpLen.Sub(expLen, big32) + if c.expLen.Cmp(big32) > 0 { + adjExpLen.Sub(c.expLen, big32) 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)) + gas := new(big.Int).Set(math.BigMax(c.modLen, c.baseLen)) switch { case gas.Cmp(big64) <= 0: gas.Mul(gas, gas) @@ -224,31 +227,26 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { } func (c *bigModExp) Run(input []byte) ([]byte, error) { - var ( - baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() - expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() - modLen = new(big.Int).SetBytes(getData(input, 64, 32)).Uint64() - ) if len(input) > 96 { input = input[96:] } else { input = input[:0] } // Handle a special case when both the base and mod length is zero - if baseLen == 0 && modLen == 0 { + if c.baseLen.Uint64() == 0 && c.modLen.Uint64() == 0 { return []byte{}, nil } // Retrieve the operands and execute the exponentiation var ( - base = new(big.Int).SetBytes(getData(input, 0, baseLen)) - exp = new(big.Int).SetBytes(getData(input, baseLen, expLen)) - mod = new(big.Int).SetBytes(getData(input, baseLen+expLen, modLen)) + base = new(big.Int).SetBytes(getData(input, 0, c.baseLen.Uint64())) + exp = new(big.Int).SetBytes(getData(input, c.baseLen.Uint64(), c.expLen.Uint64())) + mod = new(big.Int).SetBytes(getData(input, c.baseLen.Uint64()+c.expLen.Uint64(), c.modLen.Uint64())) ) if mod.BitLen() == 0 { // Modulo 0 is undefined, return zero - return common.LeftPadBytes([]byte{}, int(modLen)), nil + return common.LeftPadBytes([]byte{}, int(c.modLen.Int64())), nil } - return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(modLen)), nil + return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), int(c.modLen.Int64())), nil } // newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point,