diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 20b741f8f1..cce3358332 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -33,7 +33,7 @@ import ( // requires a deterministic gas count based on the input size of the Run method of the // contract. type PrecompiledContract interface { - RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use + RequiredGas(evm *EVM, input []byte) uint64 // RequiredPrice calculates the contract gas use Run(input []byte) ([]byte, error) // Run runs the precompiled contract } @@ -60,8 +60,8 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ } // RunPrecompiledContract runs and evaluates the output of a precompiled contract. -func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) { - gas := p.RequiredGas(input) +func RunPrecompiledContract(evm *EVM, p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) { + gas := p.RequiredGas(evm, input) if contract.UseGas(gas) { return p.Run(input) } @@ -71,7 +71,7 @@ func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contr // ECRECOVER implemented as a native contract. type ecrecover struct{} -func (c *ecrecover) RequiredGas(input []byte) uint64 { +func (c *ecrecover) RequiredGas(_ *EVM, input []byte) uint64 { return params.EcrecoverGas } @@ -108,7 +108,7 @@ type sha256hash struct{} // // This method does not require any overflow checking as the input size gas costs // required for anything significant is so high it's impossible to pay for. -func (c *sha256hash) RequiredGas(input []byte) uint64 { +func (c *sha256hash) RequiredGas(_ *EVM, input []byte) uint64 { return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas } func (c *sha256hash) Run(input []byte) ([]byte, error) { @@ -123,7 +123,7 @@ type ripemd160hash struct{} // // This method does not require any overflow checking as the input size gas costs // required for anything significant is so high it's impossible to pay for. -func (c *ripemd160hash) RequiredGas(input []byte) uint64 { +func (c *ripemd160hash) RequiredGas(_ *EVM, input []byte) uint64 { return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas } func (c *ripemd160hash) Run(input []byte) ([]byte, error) { @@ -139,7 +139,7 @@ type dataCopy struct{} // // This method does not require any overflow checking as the input size gas costs // required for anything significant is so high it's impossible to pay for. -func (c *dataCopy) RequiredGas(input []byte) uint64 { +func (c *dataCopy) RequiredGas(_ *EVM, input []byte) uint64 { return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas } func (c *dataCopy) Run(in []byte) ([]byte, error) { @@ -164,7 +164,7 @@ var ( ) // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bigModExp) RequiredGas(input []byte) uint64 { +func (c *bigModExp) RequiredGas(_ *EVM, input []byte) uint64 { var ( baseLen = new(big.Int).SetBytes(getData(input, 0, 32)) expLen = new(big.Int).SetBytes(getData(input, 32, 32)) @@ -275,7 +275,10 @@ func newTwistPoint(blob []byte) (*bn256.G2, error) { type bn256Add struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bn256Add) RequiredGas(input []byte) uint64 { +func (c *bn256Add) RequiredGas(evm *EVM, input []byte) uint64 { + if evm.ChainConfig().IsConstantinople(evm.BlockNumber) { + return params.OptimizedBn256AddGas + } return params.Bn256AddGas } @@ -297,7 +300,10 @@ func (c *bn256Add) Run(input []byte) ([]byte, error) { type bn256ScalarMul struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 { +func (c *bn256ScalarMul) RequiredGas(evm *EVM, input []byte) uint64 { + if evm.ChainConfig().IsConstantinople(evm.BlockNumber) { + return params.OptimizedBn256ScalarMulGas + } return params.Bn256ScalarMulGas } @@ -326,7 +332,10 @@ var ( type bn256Pairing struct{} // RequiredGas returns the gas required to execute the pre-compiled contract. -func (c *bn256Pairing) RequiredGas(input []byte) uint64 { +func (c *bn256Pairing) RequiredGas(evm *EVM, input []byte) uint64 { + if evm.ChainConfig().IsConstantinople(evm.BlockNumber) { + return params.OptimizedBn256PairingBaseGas + uint64(len(input)/192)*params.OptimizedBn256PairingPerPointGas + } return params.Bn256PairingBaseGas + uint64(len(input)/192)*params.Bn256PairingPerPointGas } diff --git a/core/vm/evm.go b/core/vm/evm.go index 58618f8115..e88a82d34e 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -48,7 +48,7 @@ func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, err precompiles = PrecompiledContractsByzantium } if p := precompiles[*contract.CodeAddr]; p != nil { - return RunPrecompiledContract(p, input, contract) + return RunPrecompiledContract(evm, p, input, contract) } } for _, interpreter := range evm.interpreters { diff --git a/params/protocol_params.go b/params/protocol_params.go index 4b53b3320a..217978450d 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -62,18 +62,22 @@ const ( // Precompiled contract gas prices - EcrecoverGas uint64 = 3000 // Elliptic curve sender recovery gas price - Sha256BaseGas uint64 = 60 // Base price for a SHA256 operation - Sha256PerWordGas uint64 = 12 // Per-word price for a SHA256 operation - Ripemd160BaseGas uint64 = 600 // Base price for a RIPEMD160 operation - Ripemd160PerWordGas uint64 = 120 // Per-word price for a RIPEMD160 operation - IdentityBaseGas uint64 = 15 // Base price for a data copy operation - IdentityPerWordGas uint64 = 3 // Per-work price for a data copy operation - ModExpQuadCoeffDiv uint64 = 20 // Divisor for the quadratic particle of the big int modular exponentiation - Bn256AddGas uint64 = 500 // Gas needed for an elliptic curve addition - Bn256ScalarMulGas uint64 = 40000 // Gas needed for an elliptic curve scalar multiplication - Bn256PairingBaseGas uint64 = 100000 // Base price for an elliptic curve pairing check - Bn256PairingPerPointGas uint64 = 80000 // Per-point price for an elliptic curve pairing check + EcrecoverGas uint64 = 3000 // Elliptic curve sender recovery gas price + Sha256BaseGas uint64 = 60 // Base price for a SHA256 operation + Sha256PerWordGas uint64 = 12 // Per-word price for a SHA256 operation + Ripemd160BaseGas uint64 = 600 // Base price for a RIPEMD160 operation + Ripemd160PerWordGas uint64 = 120 // Per-word price for a RIPEMD160 operation + IdentityBaseGas uint64 = 15 // Base price for a data copy operation + IdentityPerWordGas uint64 = 3 // Per-work price for a data copy operation + ModExpQuadCoeffDiv uint64 = 20 // Divisor for the quadratic particle of the big int modular exponentiation + Bn256AddGas uint64 = 500 // Gas needed for an elliptic curve addition + Bn256ScalarMulGas uint64 = 40000 // Gas needed for an elliptic curve scalar multiplication + Bn256PairingBaseGas uint64 = 100000 // Base price for an elliptic curve pairing check + Bn256PairingPerPointGas uint64 = 80000 // Per-point price for an elliptic curve pairing check + OptimizedBn256AddGas uint64 = 50 // Gas needed for an elliptic curve addition using optimized Cloudflare’s bn256 library + OptimizedBn256ScalarMulGas uint64 = 2000 // Gas needed for an elliptic curve scalar multiplication using optimized Cloudflare’s bn256 library + OptimizedBn256PairingBaseGas uint64 = 80000 // Base price for an elliptic curve pairing check using optimized Cloudflare’s bn256 library + OptimizedBn256PairingPerPointGas uint64 = 5000 // Per-point price for an elliptic curve pairing check using optimized Cloudflare’s bn256 library ) var (