From 0050f0abba7b982208fada7b1efc1db941c3f4ff Mon Sep 17 00:00:00 2001 From: Jeremy Wei Date: Mon, 23 Sep 2024 08:29:25 -0400 Subject: [PATCH] Pass delegatecall flag into precompile RunAndCalculateGas (#34) * pass delegatecall flag into precompile RunAndCalculateGas * add isFromDelegateCall to Precompile Run * CallCode also uses Delegatecall to call Precompile --- core/vm/contracts.go | 56 ++++++++++++++++++++++---------------------- core/vm/evm.go | 8 +++---- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 5accdc0c732e..3248e15c67f2 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -39,12 +39,12 @@ 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 - Run(evm *EVM, sender common.Address, callingContract common.Address, input []byte, value *big.Int, readOnly bool) ([]byte, error) // Run runs the precompiled contract + RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use + Run(evm *EVM, sender common.Address, callingContract common.Address, input []byte, value *big.Int, readOnly bool, isFromDelegateCall bool) ([]byte, error) // Run runs the precompiled contract } type DynamicGasPrecompiledContract interface { - RunAndCalculateGas(evm *EVM, sender common.Address, callingContract common.Address, input []byte, suppliedGas uint64, value *big.Int, logger *tracing.Hooks, readOnly bool) (ret []byte, remainingGas uint64, err error) // Run runs the precompiled contract and calculate gas dynamically + RunAndCalculateGas(evm *EVM, sender common.Address, callingContract common.Address, input []byte, suppliedGas uint64, value *big.Int, logger *tracing.Hooks, readOnly bool, isFromDelegateCall bool) (ret []byte, remainingGas uint64, err error) // Run runs the precompiled contract and calculate gas dynamically } // PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum @@ -173,11 +173,11 @@ func ActivePrecompiles(rules params.Rules) []common.Address { // - the returned bytes, // - the _remaining_ gas, // - any error that occurred -func RunPrecompiledContract(p PrecompiledContract, evm *EVM, sender common.Address, callingContract common.Address, input []byte, suppliedGas uint64, value *big.Int, logger *tracing.Hooks, readOnly bool) (ret []byte, remainingGas uint64, err error) { +func RunPrecompiledContract(p PrecompiledContract, evm *EVM, sender common.Address, callingContract common.Address, input []byte, suppliedGas uint64, value *big.Int, logger *tracing.Hooks, readOnly bool, isFromDelegateCall bool) (ret []byte, remainingGas uint64, err error) { evm.depth++ defer func() { evm.depth-- }() if dp, ok := p.(DynamicGasPrecompiledContract); ok { - return dp.RunAndCalculateGas(evm, sender, callingContract, input, suppliedGas, value, logger, readOnly) + return dp.RunAndCalculateGas(evm, sender, callingContract, input, suppliedGas, value, logger, readOnly, isFromDelegateCall) } gasCost := p.RequiredGas(input) if suppliedGas < gasCost { @@ -187,7 +187,7 @@ func RunPrecompiledContract(p PrecompiledContract, evm *EVM, sender common.Addre logger.OnGasChange(suppliedGas, suppliedGas-gasCost, tracing.GasChangeCallPrecompiledContract) } suppliedGas -= gasCost - output, err := p.Run(evm, sender, callingContract, input, value, readOnly) + output, err := p.Run(evm, sender, callingContract, input, value, readOnly, isFromDelegateCall) return output, suppliedGas, err } @@ -198,7 +198,7 @@ func (c *Ecrecover) RequiredGas(input []byte) uint64 { return params.EcrecoverGas } -func (c *Ecrecover) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Ecrecover) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { const ecRecoverInputLength = 128 input = common.RightPadBytes(input, ecRecoverInputLength) @@ -239,7 +239,7 @@ type Sha256hash struct{} func (c *Sha256hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas } -func (c *Sha256hash) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Sha256hash) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { h := sha256.Sum256(input) return h[:], nil } @@ -254,7 +254,7 @@ type Ripemd160hash struct{} func (c *Ripemd160hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas } -func (c *Ripemd160hash) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Ripemd160hash) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { ripemd := ripemd160.New() ripemd.Write(input) return common.LeftPadBytes(ripemd.Sum(nil), 32), nil @@ -270,7 +270,7 @@ type DataCopy struct{} func (c *DataCopy) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas } -func (c *DataCopy) Run(_ *EVM, _ common.Address, _ common.Address, in []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *DataCopy) Run(_ *EVM, _ common.Address, _ common.Address, in []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { return common.CopyBytes(in), nil } @@ -396,7 +396,7 @@ func (c *BigModExp) RequiredGas(input []byte) uint64 { return gas.Uint64() } -func (c *BigModExp) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *BigModExp) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { var ( baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() @@ -476,7 +476,7 @@ func (c *Bn256AddIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256AddGasIstanbul } -func (c *Bn256AddIstanbul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Bn256AddIstanbul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { return runBn256Add(input) } @@ -489,7 +489,7 @@ func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 { return params.Bn256AddGasByzantium } -func (c *bn256AddByzantium) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *bn256AddByzantium) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { return runBn256Add(input) } @@ -514,7 +514,7 @@ func (c *Bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasIstanbul } -func (c *Bn256ScalarMulIstanbul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Bn256ScalarMulIstanbul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { return runBn256ScalarMul(input) } @@ -527,7 +527,7 @@ func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasByzantium } -func (c *bn256ScalarMulByzantium) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *bn256ScalarMulByzantium) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { return runBn256ScalarMul(input) } @@ -582,7 +582,7 @@ func (c *Bn256PairingIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul } -func (c *Bn256PairingIstanbul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Bn256PairingIstanbul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { return runBn256Pairing(input) } @@ -595,7 +595,7 @@ func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium } -func (c *bn256PairingByzantium) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *bn256PairingByzantium) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { return runBn256Pairing(input) } @@ -621,7 +621,7 @@ var ( ErrBlake2FInvalidFinalFlag = errors.New("invalid final flag") ) -func (c *Blake2F) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Blake2F) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { // Make sure the input is valid (correct length and final flag) if len(input) != Blake2FInputLength { return nil, ErrBlake2FInvalidInputLength @@ -675,7 +675,7 @@ func (c *Bls12381G1Add) RequiredGas(input []byte) uint64 { return params.Bls12381G1AddGas } -func (c *Bls12381G1Add) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Bls12381G1Add) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { // Implements EIP-2537 G1Add precompile. // > G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each). // > Output is an encoding of addition operation result - single G1 point (`128` bytes). @@ -713,7 +713,7 @@ func (c *Bls12381G1Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G1MulGas } -func (c *Bls12381G1Mul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Bls12381G1Mul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { // Implements EIP-2537 G1Mul precompile. // > G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiplication operation result - single G1 point (`128` bytes). @@ -763,7 +763,7 @@ func (c *Bls12381G1MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000 } -func (c *Bls12381G1MultiExp) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Bls12381G1MultiExp) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { // Implements EIP-2537 G1MultiExp precompile. // G1 multiplication call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes). @@ -806,7 +806,7 @@ func (c *Bls12381G2Add) RequiredGas(input []byte) uint64 { return params.Bls12381G2AddGas } -func (c *Bls12381G2Add) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Bls12381G2Add) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { // Implements EIP-2537 G2Add precompile. // > G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each). // > Output is an encoding of addition operation result - single G2 point (`256` bytes). @@ -844,7 +844,7 @@ func (c *Bls12381G2Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G2MulGas } -func (c *Bls12381G2Mul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Bls12381G2Mul) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { // Implements EIP-2537 G2MUL precompile logic. // > G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiplication operation result - single G2 point (`256` bytes). @@ -894,7 +894,7 @@ func (c *Bls12381G2MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000 } -func (c *Bls12381G2MultiExp) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Bls12381G2MultiExp) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { // Implements EIP-2537 G2MultiExp precompile logic // > G2 multiplication call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes). @@ -937,7 +937,7 @@ func (c *Bls12381Pairing) RequiredGas(input []byte) uint64 { return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas } -func (c *Bls12381Pairing) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Bls12381Pairing) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { // Implements EIP-2537 Pairing precompile logic. // > Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure: // > - `128` bytes of G1 point encoding @@ -1016,7 +1016,7 @@ func (c *Bls12381MapG1) RequiredGas(input []byte) uint64 { return params.Bls12381MapG1Gas } -func (c *Bls12381MapG1) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Bls12381MapG1) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { // Implements EIP-2537 Map_To_G1 precompile. // > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field. // > Output of this call is `128` bytes and is G1 point following respective encoding rules. @@ -1051,7 +1051,7 @@ func (c *Bls12381MapG2) RequiredGas(input []byte) uint64 { return params.Bls12381MapG2Gas } -func (c *Bls12381MapG2) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (c *Bls12381MapG2) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { // Implements EIP-2537 Map_FP2_TO_G2 precompile logic. // > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field. // > Output of this call is `256` bytes and is G2 point following respective encoding rules. @@ -1106,7 +1106,7 @@ var ( ) // Run executes the point evaluation precompile. -func (b *KzgPointEvaluation) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool) ([]byte, error) { +func (b *KzgPointEvaluation) Run(_ *EVM, _ common.Address, _ common.Address, input []byte, _ *big.Int, _ bool, _ bool) ([]byte, error) { if len(input) != blobVerifyInputLength { return nil, errBlobVerifyInvalidInputLength } diff --git a/core/vm/evm.go b/core/vm/evm.go index 79132c6b78dc..d6428a7623f4 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -215,7 +215,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas evm.Context.Transfer(evm.StateDB, caller.Address(), addr, value) if isPrecompile { - ret, gas, err = RunPrecompiledContract(p, evm, caller.Address(), caller.Address(), input, gas, value, evm.Config.Tracer, evm.interpreter.readOnly) + ret, gas, err = RunPrecompiledContract(p, evm, caller.Address(), caller.Address(), input, gas, value, evm.Config.Tracer, evm.interpreter.readOnly, false) } else { // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. @@ -281,7 +281,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // It is allowed to call precompiles, even via delegatecall if p, isPrecompile := evm.precompile(addr); isPrecompile { - ret, gas, err = RunPrecompiledContract(p, evm, caller.Address(), caller.Address(), input, gas, big0, evm.Config.Tracer, evm.interpreter.readOnly) + ret, gas, err = RunPrecompiledContract(p, evm, caller.Address(), caller.Address(), input, gas, big0, evm.Config.Tracer, evm.interpreter.readOnly, true) } else { addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. @@ -332,7 +332,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by // NOTE: caller must, at all times be a contract. It should never happen // that caller is something other than a Contract. parent := caller.(*Contract) - ret, gas, err = RunPrecompiledContract(p, evm, parent.CallerAddress, caller.Address(), input, gas, nil, evm.Config.Tracer, evm.interpreter.readOnly) + ret, gas, err = RunPrecompiledContract(p, evm, parent.CallerAddress, caller.Address(), input, gas, nil, evm.Config.Tracer, evm.interpreter.readOnly, true) } else { addrCopy := addr // Initialise a new contract and make initialise the delegate values @@ -383,7 +383,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte evm.StateDB.AddBalance(addr, new(big.Int), tracing.BalanceChangeTouchAccount) if p, isPrecompile := evm.precompile(addr); isPrecompile { - ret, gas, err = RunPrecompiledContract(p, evm, caller.Address(), caller.Address(), input, gas, nil, evm.Config.Tracer, true) + ret, gas, err = RunPrecompiledContract(p, evm, caller.Address(), caller.Address(), input, gas, nil, evm.Config.Tracer, true, false) } else { // At this point, we use a copy of address. If we don't, the go compiler will // leak the 'contract' to the outer scope, and make allocation for 'contract'