diff --git a/core/vm/contracts.go b/core/vm/contracts.go index aa4a3f13df..f6b16b2b44 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -40,9 +40,12 @@ type PrecompiledContract interface { Run(input []byte) ([]byte, error) // Run runs the precompiled contract } +// PrecompiledContractByName contains the precompiled contracts supported at the given fork. +type PrecompiledContracts map[common.Address]PrecompiledContract + // PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum // contracts used in the Frontier and Homestead releases. -var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{ +var PrecompiledContractsHomestead = PrecompiledContracts{ common.BytesToAddress([]byte{1}): &ecrecover{}, common.BytesToAddress([]byte{2}): &sha256hash{}, common.BytesToAddress([]byte{3}): &ripemd160hash{}, @@ -51,7 +54,7 @@ var PrecompiledContractsHomestead = map[common.Address]PrecompiledContract{ // PrecompiledContractsByzantium contains the default set of pre-compiled Ethereum // contracts used in the Byzantium release. -var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ +var PrecompiledContractsByzantium = PrecompiledContracts{ common.BytesToAddress([]byte{1}): &ecrecover{}, common.BytesToAddress([]byte{2}): &sha256hash{}, common.BytesToAddress([]byte{3}): &ripemd160hash{}, @@ -64,7 +67,7 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ // PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum // contracts used in the Istanbul release. -var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{ +var PrecompiledContractsIstanbul = PrecompiledContracts{ common.BytesToAddress([]byte{1}): &ecrecover{}, common.BytesToAddress([]byte{2}): &sha256hash{}, common.BytesToAddress([]byte{3}): &ripemd160hash{}, @@ -78,7 +81,7 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{ // PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum // contracts used in the Berlin release. -var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{ +var PrecompiledContractsBerlin = PrecompiledContracts{ common.BytesToAddress([]byte{1}): &ecrecover{}, common.BytesToAddress([]byte{2}): &sha256hash{}, common.BytesToAddress([]byte{3}): &ripemd160hash{}, @@ -92,7 +95,7 @@ var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{ // PrecompiledContractsBLS contains the set of pre-compiled Ethereum // contracts specified in EIP-2537. These are exported for testing purposes. -var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ +var PrecompiledContractsBLS = PrecompiledContracts{ common.BytesToAddress([]byte{10}): &bls12381G1Add{}, common.BytesToAddress([]byte{11}): &bls12381G1Mul{}, common.BytesToAddress([]byte{12}): &bls12381G1MultiExp{}, @@ -126,6 +129,15 @@ func init() { } } +// Copy returns a copy of the precompiled contracts. +func (p PrecompiledContracts) Copy() PrecompiledContracts { + c := make(PrecompiledContracts) + for k, v := range p { + c[k] = v + } + return c +} + // ActivePrecompiles returns the precompiles enabled with the current configuration. func ActivePrecompiles(rules params.Rules) []common.Address { switch { diff --git a/core/vm/evm.go b/core/vm/evm.go index 9f7735ac6d..59e65ef715 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -41,24 +41,7 @@ type ( ) func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { - var precompiles map[common.Address]PrecompiledContract - switch { - case evm.chainRules.IsBerlin: - precompiles = PrecompiledContractsBerlin - case evm.chainRules.IsIstanbul: - precompiles = PrecompiledContractsIstanbul - case evm.chainRules.IsByzantium: - precompiles = PrecompiledContractsByzantium - default: - precompiles = PrecompiledContractsHomestead - } - // ECRecoverCode can be set only through RPC calls - if evm.Config.DisableECRecover { - if addr == common.BytesToAddress([]byte{1}) { - return nil, false - } - } - p, ok := precompiles[addr] + p, ok := evm.precompiles[addr] return p, ok } @@ -125,6 +108,8 @@ type EVM struct { // available gas is calculated in gasCall* according to the 63/64 rule and later // applied in opCall*. callGasTemp uint64 + // precompiles holds the precompiled contracts for the current epoch + precompiles map[common.Address]PrecompiledContract } // NewEVM returns a new EVM. The returned EVM is not thread safe and should @@ -138,6 +123,20 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig chainConfig: chainConfig, chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), } + switch { + case evm.chainRules.IsBerlin: + evm.precompiles = PrecompiledContractsBerlin.Copy() + case evm.chainRules.IsIstanbul: + evm.precompiles = PrecompiledContractsIstanbul.Copy() + case evm.chainRules.IsByzantium: + evm.precompiles = PrecompiledContractsByzantium.Copy() + default: + evm.precompiles = PrecompiledContractsHomestead.Copy() + } + // ECRecoverCode can be set only through RPC calls + if config.DisableECRecover { + delete(evm.precompiles, common.BytesToAddress([]byte{1})) + } evm.interpreter = NewEVMInterpreter(evm) return evm }