make Precompile injectable into block context

This commit is contained in:
ramtinms 2023-12-21 13:42:57 -08:00
parent cca94792a4
commit fbea4aab3e

View file

@ -35,24 +35,30 @@ type (
// GetHashFunc returns the n'th block hash in the blockchain // GetHashFunc returns the n'th block hash in the blockchain
// and is used by the BLOCKHASH EVM op code. // and is used by the BLOCKHASH EVM op code.
GetHashFunc func(uint64) common.Hash GetHashFunc func(uint64) common.Hash
// HasPrecompileFunc checks if an address has a precompile contract associated with it.
// if yes, it returns the precompiled contract and a boolean
HasPrecompileFunc func(addr common.Address) (PrecompiledContract, bool)
) )
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { // getDefaultPrecompileFunc returns the default precompile function
var precompiles map[common.Address]PrecompiledContract func getDefaultPrecompileFunc(chainRules params.Rules) HasPrecompileFunc {
switch { return func(addr common.Address) (PrecompiledContract, bool) {
case evm.chainRules.IsCancun: var precompiles map[common.Address]PrecompiledContract
precompiles = PrecompiledContractsCancun switch {
case evm.chainRules.IsBerlin: case chainRules.IsCancun:
precompiles = PrecompiledContractsBerlin precompiles = PrecompiledContractsCancun
case evm.chainRules.IsIstanbul: case chainRules.IsBerlin:
precompiles = PrecompiledContractsIstanbul precompiles = PrecompiledContractsBerlin
case evm.chainRules.IsByzantium: case chainRules.IsIstanbul:
precompiles = PrecompiledContractsByzantium precompiles = PrecompiledContractsIstanbul
default: case chainRules.IsByzantium:
precompiles = PrecompiledContractsHomestead precompiles = PrecompiledContractsByzantium
default:
precompiles = PrecompiledContractsHomestead
}
p, ok := precompiles[addr]
return p, ok
} }
p, ok := precompiles[addr]
return p, ok
} }
// BlockContext provides the EVM with auxiliary information. Once provided // BlockContext provides the EVM with auxiliary information. Once provided
@ -65,6 +71,8 @@ type BlockContext struct {
Transfer TransferFunc Transfer TransferFunc
// GetHash returns the hash corresponding to n // GetHash returns the hash corresponding to n
GetHash GetHashFunc GetHash GetHashFunc
// HasPrecompile returns the precompile for an address
HasPrecompile HasPrecompileFunc
// Block information // Block information
Coinbase common.Address // Provides information for COINBASE Coinbase common.Address // Provides information for COINBASE
@ -137,15 +145,23 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig
blockCtx.BlobBaseFee = new(big.Int) blockCtx.BlobBaseFee = new(big.Int)
} }
} }
chainRules := chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time)
// set default precompile if is not set
if blockCtx.HasPrecompile == nil {
blockCtx.HasPrecompile = getDefaultPrecompileFunc(chainRules)
}
evm := &EVM{ evm := &EVM{
Context: blockCtx, Context: blockCtx,
TxContext: txCtx, TxContext: txCtx,
StateDB: statedb, StateDB: statedb,
Config: config, Config: config,
chainConfig: chainConfig, chainConfig: chainConfig,
chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), chainRules: chainRules,
} }
evm.interpreter = NewEVMInterpreter(evm) evm.interpreter = NewEVMInterpreter(evm)
return evm return evm
} }
@ -186,7 +202,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
return nil, gas, ErrInsufficientBalance return nil, gas, ErrInsufficientBalance
} }
snapshot := evm.StateDB.Snapshot() snapshot := evm.StateDB.Snapshot()
p, isPrecompile := evm.precompile(addr) p, isPrecompile := evm.Context.HasPrecompile(addr)
debug := evm.Config.Tracer != nil debug := evm.Config.Tracer != nil
if !evm.StateDB.Exist(addr) { if !evm.StateDB.Exist(addr) {
@ -286,7 +302,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
} }
// It is allowed to call precompiles, even via delegatecall // It is allowed to call precompiles, even via delegatecall
if p, isPrecompile := evm.precompile(addr); isPrecompile { if p, isPrecompile := evm.Context.HasPrecompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas) ret, gas, err = RunPrecompiledContract(p, input, gas)
} else { } else {
addrCopy := addr addrCopy := addr
@ -331,7 +347,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
} }
// It is allowed to call precompiles, even via delegatecall // It is allowed to call precompiles, even via delegatecall
if p, isPrecompile := evm.precompile(addr); isPrecompile { if p, isPrecompile := evm.Context.HasPrecompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas) ret, gas, err = RunPrecompiledContract(p, input, gas)
} else { } else {
addrCopy := addr addrCopy := addr
@ -380,7 +396,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
}(gas) }(gas)
} }
if p, isPrecompile := evm.precompile(addr); isPrecompile { if p, isPrecompile := evm.Context.HasPrecompile(addr); isPrecompile {
ret, gas, err = RunPrecompiledContract(p, input, gas) ret, gas, err = RunPrecompiledContract(p, input, gas)
} else { } else {
// At this point, we use a copy of address. If we don't, the go compiler will // At this point, we use a copy of address. If we don't, the go compiler will