From 6a08dd2e7da960665e2b806d05e105765e85c61c Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Mon, 20 Mar 2023 18:53:27 -0400 Subject: [PATCH] setup --- core/vm/contracts.go | 44 +++++++++++++++++------------------ core/vm/contracts_test.go | 2 +- core/vm/evm.go | 27 +++++++-------------- core/vm/interface.go | 28 ++++++++++++++++++++++ core/vm/precompile_manager.go | 4 ++-- 5 files changed, 61 insertions(+), 44 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index e4e025f2dc50..e2073b2138eb 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -42,7 +42,7 @@ type PrecompiledContract interface { // RequiredGas calculates the contract static gas use. RequiredGas(input []byte) uint64 // Run runs the precompiled contract with the given context. - Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) + Run(ctx context.Context, evm PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) } // PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum @@ -156,7 +156,7 @@ func (c *ecrecover) RequiredGas(input []byte) uint64 { return params.EcrecoverGas } -func (c *ecrecover) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *ecrecover) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { const ecRecoverInputLength = 128 input = common.RightPadBytes(input, ecRecoverInputLength) @@ -201,7 +201,7 @@ func (c *sha256hash) RegistryKey() common.Address { func (c *sha256hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas } -func (c *sha256hash) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *sha256hash) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { h := sha256.Sum256(input) return h[:], nil } @@ -220,7 +220,7 @@ func (c *ripemd160hash) RegistryKey() common.Address { func (c *ripemd160hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas } -func (c *ripemd160hash) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *ripemd160hash) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { ripemd := ripemd160.New() ripemd.Write(input) return common.LeftPadBytes(ripemd.Sum(nil), 32), nil @@ -240,7 +240,7 @@ func (c *dataCopy) RegistryKey() common.Address { func (c *dataCopy) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas } -func (c *dataCopy) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *dataCopy) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return input, nil } @@ -371,7 +371,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { return gas.Uint64() } -func (c *bigModExp) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bigModExp) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { var ( baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() @@ -455,7 +455,7 @@ func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256AddGasIstanbul } -func (c *bn256AddIstanbul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256AddIstanbul) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Add(input) } @@ -472,7 +472,7 @@ func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 { return params.Bn256AddGasByzantium } -func (c *bn256AddByzantium) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256AddByzantium) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Add(input) } @@ -501,7 +501,7 @@ func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasIstanbul } -func (c *bn256ScalarMulIstanbul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256ScalarMulIstanbul) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256ScalarMul(input) } @@ -518,7 +518,7 @@ func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasByzantium } -func (c *bn256ScalarMulByzantium) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256ScalarMulByzantium) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256ScalarMul(input) } @@ -577,7 +577,7 @@ func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul } -func (c *bn256PairingIstanbul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256PairingIstanbul) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Pairing(input) } @@ -594,7 +594,7 @@ func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium } -func (c *bn256PairingByzantium) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256PairingByzantium) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Pairing(input) } @@ -624,7 +624,7 @@ var ( errBlake2FInvalidFinalFlag = errors.New("invalid final flag") ) -func (c *blake2F) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *blake2F) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Make sure the input is valid (correct length and final flag) if len(input) != blake2FInputLength { return nil, errBlake2FInvalidInputLength @@ -682,7 +682,7 @@ func (c *bls12381G1Add) RequiredGas(input []byte) uint64 { return params.Bls12381G1AddGas } -func (c *bls12381G1Add) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G1Add) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly 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). @@ -724,7 +724,7 @@ func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G1MulGas } -func (c *bls12381G1Mul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G1Mul) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly 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). @@ -778,7 +778,7 @@ func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000 } -func (c *bls12381G1MultiExp) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G1MultiExp) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly 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). @@ -825,7 +825,7 @@ func (c *bls12381G2Add) RequiredGas(input []byte) uint64 { return params.Bls12381G2AddGas } -func (c *bls12381G2Add) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G2Add) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly 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). @@ -867,7 +867,7 @@ func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G2MulGas } -func (c *bls12381G2Mul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G2Mul) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly 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). @@ -921,7 +921,7 @@ func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000 } -func (c *bls12381G2MultiExp) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G2MultiExp) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly 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). @@ -968,7 +968,7 @@ func (c *bls12381Pairing) RequiredGas(input []byte) uint64 { return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas } -func (c *bls12381Pairing) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381Pairing) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly 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 @@ -1051,7 +1051,7 @@ func (c *bls12381MapG1) RequiredGas(input []byte) uint64 { return params.Bls12381MapG1Gas } -func (c *bls12381MapG1) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381MapG1) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly 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. @@ -1090,7 +1090,7 @@ func (c *bls12381MapG2) RequiredGas(input []byte) uint64 { return params.Bls12381MapG2Gas } -func (c *bls12381MapG2) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381MapG2) Run(ctx context.Context, _ PrecompileEVM, input []byte, caller common.Address, value *big.Int, readonly 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. diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index 4ed94d93a950..bf9756cebb57 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -99,7 +99,7 @@ func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uin return nil, 0, ErrOutOfGas } suppliedGas -= gasCost - output, err := p.Run(context.Background(), input, common.Address{}, new(big.Int), true) + output, err := p.Run(context.Background(), nil, input, common.Address{}, new(big.Int), true) return output, suppliedGas, err } diff --git a/core/vm/evm.go b/core/vm/evm.go index 223c7c16f05f..f1ab566bfde0 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -40,21 +40,6 @@ type ( GetHashFunc func(uint64) common.Hash ) -// `PrecompileManager` allows the EVM to execute a precompiled contract. -type PrecompileManager interface { - // `Has` returns if a precompiled contract was found at `addr`. - Has(addr common.Address) bool - - // `Get` returns the precompiled contract at `addr`. Returns nil if no - // contract is found at `addr`. - Get(addr common.Address) PrecompiledContract - - // `Run` runs a precompiled contract and returns the remaining gas. - Run(sdb StateDB, p PrecompiledContract, input []byte, caller common.Address, - value *big.Int, suppliedGas uint64, readonly bool, - ) (ret []byte, remainingGas uint64, err error) -} - // BlockContext provides the EVM with auxiliary information. Once provided // it shouldn't be modified. type BlockContext struct { @@ -171,6 +156,10 @@ func (evm *EVM) Interpreter() *EVMInterpreter { return evm.interpreter } +func (evm *EVM) GetStateDB() StateDB { + return evm.StateDB +} + // Call executes the contract associated with the addr with the given input as // parameters. It also handles any necessary value transfer required and takes // the necessary steps to create accounts and reverses the state in case of an @@ -223,7 +212,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas if isPrecompile { ret, gas, err = evm.PrecompileManager.Run( - evm.StateDB, evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, false, + evm, evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, false, ) } else { // Initialise a new contract and set the code that is to be used by the EVM. @@ -288,7 +277,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // It is allowed to call precompiles, even via delegatecall if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { ret, gas, err = evm.PrecompileManager.Run( - evm.StateDB, evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, true, + evm, evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, true, ) } else { addrCopy := addr @@ -336,7 +325,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { parent := caller.(*Contract) ret, gas, err = evm.PrecompileManager.Run( - evm.StateDB, evm.PrecompileManager.Get(addr), input, parent.CallerAddress, parent.value, gas, false, + evm, evm.PrecompileManager.Get(addr), input, parent.CallerAddress, parent.value, gas, false, ) } else { addrCopy := addr @@ -387,7 +376,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { ret, gas, err = evm.PrecompileManager.Run( - evm.StateDB, evm.PrecompileManager.Get(addr), input, caller.Address(), new(big.Int), gas, true, + evm, evm.PrecompileManager.Get(addr), input, caller.Address(), new(big.Int), gas, true, ) } else { // At this point, we use a copy of address. If we don't, the go compiler will diff --git a/core/vm/interface.go b/core/vm/interface.go index 24ee2c04ffbd..4ed3ab23cbaf 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -21,6 +21,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" + "github.com/holiman/uint256" ) // StateDB is an EVM database for full state querying. @@ -38,3 +39,30 @@ type CallContext interface { // Create creates a new contract Create(env *EVM, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error) } + +type ( + // PrecompileManager allows the EVM to execute a precompiled contract. + PrecompileManager interface { + // `Has` returns if a precompiled contract was found at `addr`. + Has(addr common.Address) bool + + // `Get` returns the precompiled contract at `addr`. Returns nil if no + // contract is found at `addr`. + Get(addr common.Address) PrecompiledContract + + // `Run` runs a precompiled contract and returns the remaining gas. + Run(evm PrecompileEVM, p PrecompiledContract, input []byte, caller common.Address, + value *big.Int, suppliedGas uint64, readonly bool, + ) (ret []byte, remainingGas uint64, err error) + } + + // PrecompileEVM is the interface through which stateful precompiles can call back into the EVM. + PrecompileEVM interface { + GetStateDB() StateDB + + Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) + StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) + Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) + Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *uint256.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) + } +) diff --git a/core/vm/precompile_manager.go b/core/vm/precompile_manager.go index 90ec4ad26cc0..b225d0ef66ef 100644 --- a/core/vm/precompile_manager.go +++ b/core/vm/precompile_manager.go @@ -56,7 +56,7 @@ func (pm *precompileManager) Get(addr common.Address) PrecompiledContract { // Run runs the given precompiled contract with the given input data and returns the remaining gas. func (pm *precompileManager) Run( - _ StateDB, p PrecompiledContract, input []byte, + evm PrecompileEVM, p PrecompiledContract, input []byte, caller common.Address, value *big.Int, suppliedGas uint64, readonly bool, ) (ret []byte, remainingGas uint64, err error) { gasCost := p.RequiredGas(input) @@ -65,7 +65,7 @@ func (pm *precompileManager) Run( } suppliedGas -= gasCost - output, err := p.Run(context.Background(), input, caller, value, readonly) + output, err := p.Run(context.Background(), evm, input, caller, value, readonly) return output, suppliedGas, err }