From f9e0222507dcac95a8e28b455f787b57a51baf05 Mon Sep 17 00:00:00 2001 From: lightclient Date: Tue, 26 Nov 2024 17:18:02 -0700 Subject: [PATCH] core: remove resolve code mechanism from statedb, put in vm --- core/state/statedb.go | 40 ------------------------------------ core/state/statedb_hooked.go | 7 ------- core/vm/eips.go | 8 ++++---- core/vm/evm.go | 39 +++++++++++++++++++++++++++++------ core/vm/interface.go | 3 --- 5 files changed, 37 insertions(+), 60 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index c24c77261a..a6ee59fa71 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -368,24 +368,6 @@ func (s *StateDB) GetCodeHash(addr common.Address) common.Hash { return common.Hash{} } -// ResolveCode retrieves the code at addr, resolving any delegation designations -// that may exist. -func (s *StateDB) ResolveCode(addr common.Address) []byte { - if obj := s.resolveCode(addr); obj != nil { - return obj.Code() - } - return nil -} - -// ResolveCodeHash retrieves the code at addr, resolving any delegation -// designations that may exist. -func (s *StateDB) ResolveCodeHash(addr common.Address) common.Hash { - if obj := s.resolveCode(addr); obj != nil { - return common.BytesToHash(obj.CodeHash()) - } - return common.Hash{} -} - // GetState retrieves the value associated with the specific key. func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash { stateObject := s.getStateObject(addr) @@ -621,28 +603,6 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject { return obj } -// resolveStateObject follows delegation designations to resolve a state object -// given by the address, returning nil if the object is not found or was deleted -// in this execution context. -func (s *StateDB) resolveCode(addr common.Address) *stateObject { - obj := s.getStateObject(addr) - if obj == nil { - return nil - } - if s.witness != nil { - s.witness.AddCode(obj.Code()) - } - addr, ok := types.ParseDelegation(obj.Code()) - if !ok { - return obj - } - obj = s.getStateObject(addr) - if obj != nil && s.witness != nil { - s.witness.AddCode(obj.Code()) - } - return obj -} - func (s *StateDB) setStateObject(object *stateObject) { s.stateObjects[object.Address()] = object } diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go index 6bf7c0b28e..26d0217099 100644 --- a/core/state/statedb_hooked.go +++ b/core/state/statedb_hooked.go @@ -73,13 +73,6 @@ func (s *hookedStateDB) GetCodeSize(addr common.Address) int { return s.inner.GetCodeSize(addr) } -func (s *hookedStateDB) ResolveCodeHash(addr common.Address) common.Hash { - return s.inner.ResolveCodeHash(addr) -} -func (s *hookedStateDB) ResolveCode(addr common.Address) []byte { - return s.inner.ResolveCode(addr) -} - func (s *hookedStateDB) AddRefund(u uint64) { s.inner.AddRefund(u) } diff --git a/core/vm/eips.go b/core/vm/eips.go index db297ce46b..7c9f614463 100644 --- a/core/vm/eips.go +++ b/core/vm/eips.go @@ -337,7 +337,7 @@ func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC uint64CodeOffset = math.MaxUint64 } addr := common.Address(a.Bytes20()) - code := interpreter.evm.StateDB.ResolveCode(addr) + code := interpreter.evm.resolveCode(addr) contract := &Contract{ Code: code, self: AccountRef(addr), @@ -719,7 +719,7 @@ func opExtCodeCopyEIP7702(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC uint64CodeOffset = math.MaxUint64 } addr := common.Address(a.Bytes20()) - code := interpreter.evm.StateDB.ResolveCode(addr) + code := interpreter.evm.resolveCode(addr) codeCopy := getData(code, uint64CodeOffset, length.Uint64()) scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) @@ -729,7 +729,7 @@ func opExtCodeCopyEIP7702(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC // opExtCodeSizeEIP7702 implements the EIP-7702 variation of opExtCodeSize. func opExtCodeSizeEIP7702(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { slot := scope.Stack.peek() - slot.SetUint64(uint64(len(interpreter.evm.StateDB.ResolveCode(slot.Bytes20())))) + slot.SetUint64(uint64(len(interpreter.evm.resolveCode(slot.Bytes20())))) return nil, nil } @@ -740,7 +740,7 @@ func opExtCodeHashEIP7702(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC if interpreter.evm.StateDB.Empty(address) { slot.Clear() } else { - slot.SetBytes(interpreter.evm.StateDB.ResolveCodeHash(address).Bytes()) + slot.SetBytes(interpreter.evm.resolveCodeHash(address).Bytes()) } return nil, nil } diff --git a/core/vm/evm.go b/core/vm/evm.go index daf4910b65..678293da3a 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -217,7 +217,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } 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. - code := evm.StateDB.ResolveCode(addr) + code := evm.resolveCode(addr) if len(code) == 0 { ret, err = nil, nil // gas is unchanged } else { @@ -225,7 +225,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas // If the account has no code, we can abort here // The depth-check is already done, and precompiles handled above contract := NewContract(caller, AccountRef(addrCopy), value, gas) - contract.SetCallCode(&addrCopy, evm.StateDB.ResolveCodeHash(addrCopy), code) + contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), code) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } @@ -285,7 +285,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // 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. contract := NewContract(caller, AccountRef(caller.Address()), value, gas) - contract.SetCallCode(&addrCopy, evm.StateDB.ResolveCodeHash(addrCopy), evm.StateDB.ResolveCode(addrCopy)) + contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy)) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } @@ -332,7 +332,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by addrCopy := addr // Initialise a new contract and make initialise the delegate values contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate() - contract.SetCallCode(&addrCopy, evm.StateDB.ResolveCodeHash(addrCopy), evm.StateDB.ResolveCode(addrCopy)) + contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy)) ret, err = evm.interpreter.Run(contract, input, false) gas = contract.Gas } @@ -387,7 +387,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte // 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. contract := NewContract(caller, AccountRef(addrCopy), new(uint256.Int), gas) - contract.SetCallCode(&addrCopy, evm.StateDB.ResolveCodeHash(addrCopy), evm.StateDB.ResolveCode(addrCopy)) + contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy)) // When an error was returned by the EVM or when setting the creation code // above we revert to the snapshot and consume any gas remaining. Additionally // when we're in Homestead this also counts for code storage gas errors. @@ -463,7 +463,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, // - the nonce is non-zero // - the code is non-empty // - the storage is non-empty - contractHash := evm.StateDB.ResolveCodeHash(address) + contractHash := evm.resolveCodeHash(address) storageRoot := evm.StateDB.GetStorageRoot(address) if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) || // non-empty code @@ -567,6 +567,33 @@ func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment * return evm.create(caller, codeAndHash, gas, endowment, contractAddr, CREATE2) } +// resolveCode returns the code associated with the provided account. After +// Prague, it can also resolve code pointed to by a delegation designator. +func (evm *EVM) resolveCode(addr common.Address) []byte { + code := evm.StateDB.GetCode(addr) + if !evm.chainRules.IsPrague { + return code + } + if target, ok := types.ParseDelegation(code); ok { + return evm.StateDB.GetCode(target) + } + return code +} + +// resolveCodeHash returns the code hash associated with the provided address. +// After Prague, it can also resolve code hash of the account pointed to by a +// delegation designator. +func (evm *EVM) resolveCodeHash(addr common.Address) common.Hash { + if !evm.chainRules.IsPrague { + return evm.StateDB.GetCodeHash(addr) + } + code := evm.StateDB.GetCode(addr) + if target, ok := types.ParseDelegation(code); ok { + return evm.StateDB.GetCodeHash(target) + } + return evm.StateDB.GetCodeHash(addr) +} + // ChainConfig returns the environment's chain configuration func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } diff --git a/core/vm/interface.go b/core/vm/interface.go index 151768264b..9229f4d2cd 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -45,9 +45,6 @@ type StateDB interface { SetCode(common.Address, []byte) GetCodeSize(common.Address) int - ResolveCodeHash(common.Address) common.Hash - ResolveCode(common.Address) []byte - AddRefund(uint64) SubRefund(uint64) GetRefund() uint64