mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
make getPrecompile configurable
This commit is contained in:
parent
e5d5e09faa
commit
6f86fdaf87
8 changed files with 120 additions and 97 deletions
|
|
@ -154,6 +154,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
Difficulty: pre.Env.Difficulty,
|
||||
GasLimit: pre.Env.GasLimit,
|
||||
GetHash: getHash,
|
||||
GetPrecompile: core.GetPrecompile,
|
||||
}
|
||||
// If currentBaseFee is defined, add it to the vmContext.
|
||||
if pre.Env.BaseFee != nil {
|
||||
|
|
|
|||
20
core/evm.go
20
core/evm.go
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
// ChainContext supports retrieving headers and consensus parameters from the
|
||||
|
|
@ -64,6 +65,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
|||
CanTransfer: CanTransfer,
|
||||
Transfer: Transfer,
|
||||
GetHash: GetHashFn(header, chain),
|
||||
GetPrecompile: GetPrecompile,
|
||||
Coinbase: beneficiary,
|
||||
BlockNumber: new(big.Int).Set(header.Number),
|
||||
Time: header.Time,
|
||||
|
|
@ -127,6 +129,24 @@ func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash
|
|||
}
|
||||
}
|
||||
|
||||
func GetPrecompile(rules params.Rules, addr common.Address) (vm.PrecompiledContract, bool) {
|
||||
var precompiles map[common.Address]vm.PrecompiledContract
|
||||
switch {
|
||||
case rules.IsCancun:
|
||||
precompiles = vm.PrecompiledContractsCancun
|
||||
case rules.IsBerlin:
|
||||
precompiles = vm.PrecompiledContractsBerlin
|
||||
case rules.IsIstanbul:
|
||||
precompiles = vm.PrecompiledContractsIstanbul
|
||||
case rules.IsByzantium:
|
||||
precompiles = vm.PrecompiledContractsByzantium
|
||||
default:
|
||||
precompiles = vm.PrecompiledContractsHomestead
|
||||
}
|
||||
p, ok := precompiles[addr]
|
||||
return p, ok
|
||||
}
|
||||
|
||||
// CanTransfer checks whether there are enough funds in the address' account to make a transfer.
|
||||
// This does not take the necessary gas in to account to make the transfer valid.
|
||||
func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool {
|
||||
|
|
|
|||
|
|
@ -35,26 +35,11 @@ type (
|
|||
// GetHashFunc returns the n'th block hash in the blockchain
|
||||
// and is used by the BLOCKHASH EVM op code.
|
||||
GetHashFunc func(uint64) common.Hash
|
||||
// GetPrecompileFunc returns a precompile contract if available for the given
|
||||
// address, it returns false if no precompile is deployed at that address
|
||||
GetPrecompileFunc func(rules params.Rules, addr common.Address) (PrecompiledContract, bool)
|
||||
)
|
||||
|
||||
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
|
||||
var precompiles map[common.Address]PrecompiledContract
|
||||
switch {
|
||||
case evm.chainRules.IsCancun:
|
||||
precompiles = PrecompiledContractsCancun
|
||||
case evm.chainRules.IsBerlin:
|
||||
precompiles = PrecompiledContractsBerlin
|
||||
case evm.chainRules.IsIstanbul:
|
||||
precompiles = PrecompiledContractsIstanbul
|
||||
case evm.chainRules.IsByzantium:
|
||||
precompiles = PrecompiledContractsByzantium
|
||||
default:
|
||||
precompiles = PrecompiledContractsHomestead
|
||||
}
|
||||
p, ok := precompiles[addr]
|
||||
return p, ok
|
||||
}
|
||||
|
||||
// BlockContext provides the EVM with auxiliary information. Once provided
|
||||
// it shouldn't be modified.
|
||||
type BlockContext struct {
|
||||
|
|
@ -65,6 +50,8 @@ type BlockContext struct {
|
|||
Transfer TransferFunc
|
||||
// GetHash returns the hash corresponding to n
|
||||
GetHash GetHashFunc
|
||||
// GetPrecompileFunc gets a precompile by address if available
|
||||
GetPrecompile GetPrecompileFunc
|
||||
|
||||
// Block information
|
||||
Coinbase common.Address // Provides information for COINBASE
|
||||
|
|
@ -172,6 +159,14 @@ func (evm *EVM) Interpreter() *EVMInterpreter {
|
|||
return evm.interpreter
|
||||
}
|
||||
|
||||
func (evm *EVM) GetPrecompile(addr common.Address) (PrecompiledContract, bool) {
|
||||
if evm.Context.GetPrecompile != nil {
|
||||
p, isPrecompile := evm.Context.GetPrecompile(evm.chainRules, addr)
|
||||
return p, isPrecompile
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
@ -186,7 +181,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
|||
return nil, gas, ErrInsufficientBalance
|
||||
}
|
||||
snapshot := evm.StateDB.Snapshot()
|
||||
p, isPrecompile := evm.precompile(addr)
|
||||
p, isPrecompile := evm.GetPrecompile(addr)
|
||||
debug := evm.Config.Tracer != nil
|
||||
|
||||
if !evm.StateDB.Exist(addr) {
|
||||
|
|
@ -286,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 {
|
||||
if p, isPrecompile := evm.GetPrecompile(addr); isPrecompile {
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas)
|
||||
} else {
|
||||
addrCopy := addr
|
||||
|
|
@ -331,7 +326,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
|
|||
}
|
||||
|
||||
// It is allowed to call precompiles, even via delegatecall
|
||||
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||
if p, isPrecompile := evm.GetPrecompile(addr); isPrecompile {
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas)
|
||||
} else {
|
||||
addrCopy := addr
|
||||
|
|
@ -380,7 +375,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
|
|||
}(gas)
|
||||
}
|
||||
|
||||
if p, isPrecompile := evm.precompile(addr); isPrecompile {
|
||||
if p, isPrecompile := evm.GetPrecompile(addr); isPrecompile {
|
||||
ret, gas, err = RunPrecompiledContract(p, input, gas)
|
||||
} else {
|
||||
// At this point, we use a copy of address. If we don't, the go compiler will
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ func NewEnv(cfg *Config) *vm.EVM {
|
|||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
GetHash: cfg.GetHashFn,
|
||||
GetPrecompile: core.GetPrecompile,
|
||||
Coinbase: cfg.Coinbase,
|
||||
BlockNumber: cfg.BlockNumber,
|
||||
Time: cfg.Time,
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
|
|||
context = vm.BlockContext{
|
||||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
GetPrecompile: core.GetPrecompile,
|
||||
Coinbase: test.Context.Miner,
|
||||
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
||||
Time: uint64(test.Context.Time),
|
||||
|
|
@ -225,6 +226,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
|||
context := vm.BlockContext{
|
||||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
GetPrecompile: core.GetPrecompile,
|
||||
Coinbase: test.Context.Miner,
|
||||
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
||||
Time: uint64(test.Context.Time),
|
||||
|
|
@ -269,6 +271,7 @@ func TestInternals(t *testing.T) {
|
|||
context = vm.BlockContext{
|
||||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
GetPrecompile: core.GetPrecompile,
|
||||
Coinbase: common.Address{},
|
||||
BlockNumber: new(big.Int).SetUint64(8000000),
|
||||
Time: 5,
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
|
|||
context := vm.BlockContext{
|
||||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
GetPrecompile: core.GetPrecompile,
|
||||
Coinbase: test.Context.Miner,
|
||||
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
||||
Time: uint64(test.Context.Time),
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
|
|||
context = vm.BlockContext{
|
||||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
GetPrecompile: core.GetPrecompile,
|
||||
Coinbase: test.Context.Miner,
|
||||
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
||||
Time: uint64(test.Context.Time),
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
|
|||
context := vm.BlockContext{
|
||||
CanTransfer: core.CanTransfer,
|
||||
Transfer: core.Transfer,
|
||||
GetPrecompile: core.GetPrecompile,
|
||||
Coinbase: common.Address{},
|
||||
BlockNumber: new(big.Int).SetUint64(uint64(5)),
|
||||
Time: 5,
|
||||
|
|
|
|||
Loading…
Reference in a new issue