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,
|
Difficulty: pre.Env.Difficulty,
|
||||||
GasLimit: pre.Env.GasLimit,
|
GasLimit: pre.Env.GasLimit,
|
||||||
GetHash: getHash,
|
GetHash: getHash,
|
||||||
|
GetPrecompile: core.GetPrecompile,
|
||||||
}
|
}
|
||||||
// If currentBaseFee is defined, add it to the vmContext.
|
// If currentBaseFee is defined, add it to the vmContext.
|
||||||
if pre.Env.BaseFee != nil {
|
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/consensus/misc/eip4844"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ChainContext supports retrieving headers and consensus parameters from the
|
// ChainContext supports retrieving headers and consensus parameters from the
|
||||||
|
|
@ -64,6 +65,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
||||||
CanTransfer: CanTransfer,
|
CanTransfer: CanTransfer,
|
||||||
Transfer: Transfer,
|
Transfer: Transfer,
|
||||||
GetHash: GetHashFn(header, chain),
|
GetHash: GetHashFn(header, chain),
|
||||||
|
GetPrecompile: GetPrecompile,
|
||||||
Coinbase: beneficiary,
|
Coinbase: beneficiary,
|
||||||
BlockNumber: new(big.Int).Set(header.Number),
|
BlockNumber: new(big.Int).Set(header.Number),
|
||||||
Time: header.Time,
|
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.
|
// 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.
|
// 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 {
|
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
|
// 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
|
||||||
|
// 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
|
// BlockContext provides the EVM with auxiliary information. Once provided
|
||||||
// it shouldn't be modified.
|
// it shouldn't be modified.
|
||||||
type BlockContext struct {
|
type BlockContext struct {
|
||||||
|
|
@ -65,6 +50,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
|
||||||
|
// GetPrecompileFunc gets a precompile by address if available
|
||||||
|
GetPrecompile GetPrecompileFunc
|
||||||
|
|
||||||
// Block information
|
// Block information
|
||||||
Coinbase common.Address // Provides information for COINBASE
|
Coinbase common.Address // Provides information for COINBASE
|
||||||
|
|
@ -172,6 +159,14 @@ func (evm *EVM) Interpreter() *EVMInterpreter {
|
||||||
return evm.interpreter
|
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
|
// Call executes the contract associated with the addr with the given input as
|
||||||
// parameters. It also handles any necessary value transfer required and takes
|
// 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
|
// 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
|
return nil, gas, ErrInsufficientBalance
|
||||||
}
|
}
|
||||||
snapshot := evm.StateDB.Snapshot()
|
snapshot := evm.StateDB.Snapshot()
|
||||||
p, isPrecompile := evm.precompile(addr)
|
p, isPrecompile := evm.GetPrecompile(addr)
|
||||||
debug := evm.Config.Tracer != nil
|
debug := evm.Config.Tracer != nil
|
||||||
|
|
||||||
if !evm.StateDB.Exist(addr) {
|
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
|
// 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)
|
ret, gas, err = RunPrecompiledContract(p, input, gas)
|
||||||
} else {
|
} else {
|
||||||
addrCopy := addr
|
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
|
// 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)
|
ret, gas, err = RunPrecompiledContract(p, input, gas)
|
||||||
} else {
|
} else {
|
||||||
addrCopy := addr
|
addrCopy := addr
|
||||||
|
|
@ -380,7 +375,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.GetPrecompile(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
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ func NewEnv(cfg *Config) *vm.EVM {
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
GetHash: cfg.GetHashFn,
|
GetHash: cfg.GetHashFn,
|
||||||
|
GetPrecompile: core.GetPrecompile,
|
||||||
Coinbase: cfg.Coinbase,
|
Coinbase: cfg.Coinbase,
|
||||||
BlockNumber: cfg.BlockNumber,
|
BlockNumber: cfg.BlockNumber,
|
||||||
Time: cfg.Time,
|
Time: cfg.Time,
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
|
||||||
context = vm.BlockContext{
|
context = vm.BlockContext{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
|
GetPrecompile: core.GetPrecompile,
|
||||||
Coinbase: test.Context.Miner,
|
Coinbase: test.Context.Miner,
|
||||||
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
||||||
Time: uint64(test.Context.Time),
|
Time: uint64(test.Context.Time),
|
||||||
|
|
@ -225,6 +226,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
||||||
context := vm.BlockContext{
|
context := vm.BlockContext{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
|
GetPrecompile: core.GetPrecompile,
|
||||||
Coinbase: test.Context.Miner,
|
Coinbase: test.Context.Miner,
|
||||||
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
||||||
Time: uint64(test.Context.Time),
|
Time: uint64(test.Context.Time),
|
||||||
|
|
@ -269,6 +271,7 @@ func TestInternals(t *testing.T) {
|
||||||
context = vm.BlockContext{
|
context = vm.BlockContext{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
|
GetPrecompile: core.GetPrecompile,
|
||||||
Coinbase: common.Address{},
|
Coinbase: common.Address{},
|
||||||
BlockNumber: new(big.Int).SetUint64(8000000),
|
BlockNumber: new(big.Int).SetUint64(8000000),
|
||||||
Time: 5,
|
Time: 5,
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
|
||||||
context := vm.BlockContext{
|
context := vm.BlockContext{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
|
GetPrecompile: core.GetPrecompile,
|
||||||
Coinbase: test.Context.Miner,
|
Coinbase: test.Context.Miner,
|
||||||
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
||||||
Time: uint64(test.Context.Time),
|
Time: uint64(test.Context.Time),
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
|
||||||
context = vm.BlockContext{
|
context = vm.BlockContext{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
|
GetPrecompile: core.GetPrecompile,
|
||||||
Coinbase: test.Context.Miner,
|
Coinbase: test.Context.Miner,
|
||||||
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)),
|
||||||
Time: uint64(test.Context.Time),
|
Time: uint64(test.Context.Time),
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ func BenchmarkTransactionTrace(b *testing.B) {
|
||||||
context := vm.BlockContext{
|
context := vm.BlockContext{
|
||||||
CanTransfer: core.CanTransfer,
|
CanTransfer: core.CanTransfer,
|
||||||
Transfer: core.Transfer,
|
Transfer: core.Transfer,
|
||||||
|
GetPrecompile: core.GetPrecompile,
|
||||||
Coinbase: common.Address{},
|
Coinbase: common.Address{},
|
||||||
BlockNumber: new(big.Int).SetUint64(uint64(5)),
|
BlockNumber: new(big.Int).SetUint64(uint64(5)),
|
||||||
Time: 5,
|
Time: 5,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue