core: remove resolve code mechanism from statedb, put in vm

This commit is contained in:
lightclient 2024-11-26 17:18:02 -07:00
parent 7dceb35670
commit f9e0222507
No known key found for this signature in database
GPG key ID: 75C916AFEE20183E
5 changed files with 37 additions and 60 deletions

View file

@ -368,24 +368,6 @@ func (s *StateDB) GetCodeHash(addr common.Address) common.Hash {
return 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. // GetState retrieves the value associated with the specific key.
func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash { func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash {
stateObject := s.getStateObject(addr) stateObject := s.getStateObject(addr)
@ -621,28 +603,6 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject {
return obj 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) { func (s *StateDB) setStateObject(object *stateObject) {
s.stateObjects[object.Address()] = object s.stateObjects[object.Address()] = object
} }

View file

@ -73,13 +73,6 @@ func (s *hookedStateDB) GetCodeSize(addr common.Address) int {
return s.inner.GetCodeSize(addr) 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) { func (s *hookedStateDB) AddRefund(u uint64) {
s.inner.AddRefund(u) s.inner.AddRefund(u)
} }

View file

@ -337,7 +337,7 @@ func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC
uint64CodeOffset = math.MaxUint64 uint64CodeOffset = math.MaxUint64
} }
addr := common.Address(a.Bytes20()) addr := common.Address(a.Bytes20())
code := interpreter.evm.StateDB.ResolveCode(addr) code := interpreter.evm.resolveCode(addr)
contract := &Contract{ contract := &Contract{
Code: code, Code: code,
self: AccountRef(addr), self: AccountRef(addr),
@ -719,7 +719,7 @@ func opExtCodeCopyEIP7702(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC
uint64CodeOffset = math.MaxUint64 uint64CodeOffset = math.MaxUint64
} }
addr := common.Address(a.Bytes20()) addr := common.Address(a.Bytes20())
code := interpreter.evm.StateDB.ResolveCode(addr) code := interpreter.evm.resolveCode(addr)
codeCopy := getData(code, uint64CodeOffset, length.Uint64()) codeCopy := getData(code, uint64CodeOffset, length.Uint64())
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), codeCopy) 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. // opExtCodeSizeEIP7702 implements the EIP-7702 variation of opExtCodeSize.
func opExtCodeSizeEIP7702(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { func opExtCodeSizeEIP7702(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
slot := scope.Stack.peek() 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 return nil, nil
} }
@ -740,7 +740,7 @@ func opExtCodeHashEIP7702(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC
if interpreter.evm.StateDB.Empty(address) { if interpreter.evm.StateDB.Empty(address) {
slot.Clear() slot.Clear()
} else { } else {
slot.SetBytes(interpreter.evm.StateDB.ResolveCodeHash(address).Bytes()) slot.SetBytes(interpreter.evm.resolveCodeHash(address).Bytes())
} }
return nil, nil return nil, nil
} }

View file

@ -217,7 +217,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
} else { } else {
// Initialise a new contract and set the code that is to be used by the EVM. // 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. // The contract is a scoped environment for this execution context only.
code := evm.StateDB.ResolveCode(addr) code := evm.resolveCode(addr)
if len(code) == 0 { if len(code) == 0 {
ret, err = nil, nil // gas is unchanged ret, err = nil, nil // gas is unchanged
} else { } 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 // If the account has no code, we can abort here
// The depth-check is already done, and precompiles handled above // The depth-check is already done, and precompiles handled above
contract := NewContract(caller, AccountRef(addrCopy), value, gas) 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) ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas 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. // 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. // The contract is a scoped environment for this execution context only.
contract := NewContract(caller, AccountRef(caller.Address()), value, gas) 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) ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas gas = contract.Gas
} }
@ -332,7 +332,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
addrCopy := addr addrCopy := addr
// Initialise a new contract and make initialise the delegate values // Initialise a new contract and make initialise the delegate values
contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate() 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) ret, err = evm.interpreter.Run(contract, input, false)
gas = contract.Gas 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. // 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. // The contract is a scoped environment for this execution context only.
contract := NewContract(caller, AccountRef(addrCopy), new(uint256.Int), gas) 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 // 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 // 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. // 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 nonce is non-zero
// - the code is non-empty // - the code is non-empty
// - the storage is non-empty // - the storage is non-empty
contractHash := evm.StateDB.ResolveCodeHash(address) contractHash := evm.resolveCodeHash(address)
storageRoot := evm.StateDB.GetStorageRoot(address) storageRoot := evm.StateDB.GetStorageRoot(address)
if evm.StateDB.GetNonce(address) != 0 || if evm.StateDB.GetNonce(address) != 0 ||
(contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) || // non-empty code (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) 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 // ChainConfig returns the environment's chain configuration
func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }

View file

@ -45,9 +45,6 @@ type StateDB interface {
SetCode(common.Address, []byte) SetCode(common.Address, []byte)
GetCodeSize(common.Address) int GetCodeSize(common.Address) int
ResolveCodeHash(common.Address) common.Hash
ResolveCode(common.Address) []byte
AddRefund(uint64) AddRefund(uint64)
SubRefund(uint64) SubRefund(uint64)
GetRefund() uint64 GetRefund() uint64