Skip to content
4 changes: 2 additions & 2 deletions core/blockchain_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ import (
"github.com/ava-labs/subnet-evm/core/types"
"github.com/ava-labs/subnet-evm/core/vm"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/precompile/feemanager"
"github.com/ava-labs/subnet-evm/precompile/rewardmanager"
"github.com/ava-labs/subnet-evm/precompile/contracts/feemanager"
"github.com/ava-labs/subnet-evm/precompile/contracts/rewardmanager"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event"
)
Expand Down
2 changes: 1 addition & 1 deletion core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
}

// Configure any stateful precompiles that should be enabled in the genesis.
err = g.Config.ConfigurePrecompiles(nil, types.NewBlockWithHeader(head), statedb)
err = ApplyPrecompileActivations(g.Config, nil, types.NewBlockWithHeader(head), statedb)
if err != nil {
panic(fmt.Sprintf("unable to configure precompiles in genesis block: %v", err))
}
Expand Down
8 changes: 4 additions & 4 deletions core/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import (
"github.com/ava-labs/subnet-evm/ethdb"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/precompile/allowlist"
"github.com/ava-labs/subnet-evm/precompile/deployerallowlist"
"github.com/ava-labs/subnet-evm/precompile/contracts/deployerallowlist"
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -192,7 +192,7 @@ func TestStatefulPrecompilesConfigure(t *testing.T) {
getConfig: func() *params.ChainConfig {
config := *params.TestChainConfig
config.GenesisPrecompiles = params.ChainConfigPrecompiles{
deployerallowlist.ConfigKey: deployerallowlist.NewContractDeployerAllowListConfig(big.NewInt(0), []common.Address{addr}, nil),
deployerallowlist.ConfigKey: deployerallowlist.NewConfig(big.NewInt(0), []common.Address{addr}, nil),
}
return &config
},
Expand Down Expand Up @@ -268,10 +268,10 @@ func TestPrecompileActivationAfterHeaderBlock(t *testing.T) {
require.Greater(block.Time(), bc.lastAccepted.Time())

activatedGenesis := customg
contractDeployerConfig := deployerallowlist.NewContractDeployerAllowListConfig(big.NewInt(51), nil, nil)
contractDeployerConfig := deployerallowlist.NewConfig(big.NewInt(51), nil, nil)
activatedGenesis.Config.UpgradeConfig.PrecompileUpgrades = []params.PrecompileUpgrade{
{
StatefulPrecompileConfig: contractDeployerConfig,
Config: contractDeployerConfig,
},
}

Expand Down
51 changes: 50 additions & 1 deletion core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ import (
"github.com/ava-labs/subnet-evm/core/types"
"github.com/ava-labs/subnet-evm/core/vm"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/precompile/contract"
"github.com/ava-labs/subnet-evm/precompile/modules"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
Expand Down Expand Up @@ -79,7 +81,7 @@ func (p *StateProcessor) Process(block *types.Block, parent *types.Header, state
)

// Configure any stateful precompiles that should go into effect during this block.
err := p.config.ConfigurePrecompiles(new(big.Int).SetUint64(parent.Time), block, statedb)
err := ApplyPrecompileActivations(p.config, new(big.Int).SetUint64(parent.Time), block, statedb)
if err != nil {
log.Error("failed to configure precompiles processing block", "hash", block.Hash(), "number", block.NumberU64(), "timestamp", block.Time(), "err", err)
return nil, nil, 0, err
Expand Down Expand Up @@ -168,3 +170,50 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg)
return applyTransaction(msg, config, author, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
}

// ApplyPrecompileActivations checks if any of the precompiles specified by the chain config are enabled or disabled by the block
// transition from [parentTimestamp] to the timestamp set in [blockContext]. If this is the case, it calls [Configure]
// to apply the necessary state transitions for the upgrade.
// This function is called:
// - within genesis setup to configure the starting state for precompiles enabled at genesis,
// - during block processing to update the state before processing the given block.
// - during block producing to apply the precompile upgrades before producing the block.
func ApplyPrecompileActivations(c *params.ChainConfig, parentTimestamp *big.Int, blockContext contract.BlockContext, statedb *state.StateDB) error {
blockTimestamp := blockContext.Timestamp()
// Note: RegisteredModules returns precompiles sorted by module addresses.
// This is important because we want to configure precompiles in the same order
// so that the state is deterministic.
for _, module := range modules.RegisteredModules() {
key := module.ConfigKey
for _, activatingConfig := range c.GetActivatingPrecompileConfigs(module.Address, parentTimestamp, blockTimestamp, c.PrecompileUpgrades) {
// If this transition activates the upgrade, configure the stateful precompile.
// (or deconfigure it if it is being disabled.)
if activatingConfig.IsDisabled() {
log.Info("Disabling precompile", "name", key)
statedb.Suicide(module.Address)
// Calling Finalise here effectively commits Suicide call and wipes the contract state.
// This enables re-configuration of the same contract state in the same block.
// Without an immediate Finalise call after the Suicide, a reconfigured precompiled state can be wiped out
// since Suicide will be committed after the reconfiguration.
statedb.Finalise(true)
} else {
module, ok := modules.GetPrecompileModule(key)
if !ok {
return fmt.Errorf("could not find module for activating precompile, name: %s", key)
}
log.Info("Activating new precompile", "name", key, "config", activatingConfig)
// Set the nonce of the precompile's address (as is done when a contract is created) to ensure
// that it is marked as non-empty and will not be cleaned up when the statedb is finalized.
statedb.SetNonce(module.Address, 1)
// Set the code of the precompile's address to a non-zero length byte slice to ensure that the precompile
// can be called from within Solidity contracts. Solidity adds a check before invoking a contract to ensure
// that it does not attempt to invoke a non-existent contract.
statedb.SetCode(module.Address, []byte{0x1})
if err := module.Configure(c, activatingConfig, statedb, blockContext); err != nil {
return fmt.Errorf("could not configure precompile, name: %s, reason: %w", key, err)
}
}
}
}
return nil
}
16 changes: 8 additions & 8 deletions core/state_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ import (
"github.com/ava-labs/subnet-evm/core/types"
"github.com/ava-labs/subnet-evm/core/vm"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/precompile/txallowlist"
"github.com/ava-labs/subnet-evm/precompile/contracts/txallowlist"
"github.com/ava-labs/subnet-evm/trie"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"golang.org/x/crypto/sha3"
)

var (
config = params.TestChainConfig
signer = types.LatestSigner(config)
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
chainConfig = params.TestChainConfig
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we can undo this rename.
I changed it but prefer to keep the import name as precompileConfig

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it makes sense, we can keep it.

signer = types.LatestSigner(chainConfig)
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
)

func makeTx(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *types.Transaction {
Expand All @@ -71,12 +71,12 @@ func mkDynamicTx(nonce uint64, to common.Address, gasLimit uint64, gasTipCap, ga
// blockchain imports bad blocks, meaning blocks which have valid headers but
// contain invalid transactions
func TestStateProcessorErrors(t *testing.T) {
config.FeeConfig.MinBaseFee = params.TestMaxBaseFee
chainConfig.FeeConfig.MinBaseFee = params.TestMaxBaseFee
{ // Tests against a 'recent' chain definition
var (
db = rawdb.NewMemoryDatabase()
gspec = &Genesis{
Config: config,
Config: chainConfig,
Alloc: GenesisAlloc{
common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{
Balance: big.NewInt(2000000000000000000), // 2 ether
Expand Down Expand Up @@ -254,7 +254,7 @@ func TestStateProcessorErrors(t *testing.T) {
var (
db = rawdb.NewMemoryDatabase()
gspec = &Genesis{
Config: config,
Config: chainConfig,
Alloc: GenesisAlloc{
common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{
Balance: big.NewInt(1000000000000000000), // 1 ether
Expand Down Expand Up @@ -316,7 +316,7 @@ func TestBadTxAllowListBlock(t *testing.T) {
SubnetEVMTimestamp: big.NewInt(0),
},
GenesisPrecompiles: params.ChainConfigPrecompiles{
txallowlist.ConfigKey: txallowlist.NewTxAllowListConfig(big.NewInt(0), nil, nil),
txallowlist.ConfigKey: txallowlist.NewConfig(big.NewInt(0), nil, nil),
},
}
signer = types.LatestSigner(config)
Expand Down
2 changes: 1 addition & 1 deletion core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import (
"github.com/ava-labs/subnet-evm/core/types"
"github.com/ava-labs/subnet-evm/core/vm"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/precompile/txallowlist"
"github.com/ava-labs/subnet-evm/precompile/contracts/txallowlist"
"github.com/ava-labs/subnet-evm/vmerrs"
"github.com/ethereum/go-ethereum/common"
)
Expand Down
8 changes: 4 additions & 4 deletions core/test_blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import (
"github.com/ava-labs/subnet-evm/ethdb"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/precompile/allowlist"
"github.com/ava-labs/subnet-evm/precompile/deployerallowlist"
"github.com/ava-labs/subnet-evm/precompile/feemanager"
"github.com/ava-labs/subnet-evm/precompile/contracts/deployerallowlist"
"github.com/ava-labs/subnet-evm/precompile/contracts/feemanager"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -1549,8 +1549,8 @@ func TestStatefulPrecompiles(t *testing.T, create func(db ethdb.Database, chainC
config := *params.TestChainConfig
// Set all of the required config parameters
config.GenesisPrecompiles = params.ChainConfigPrecompiles{
deployerallowlist.ConfigKey: deployerallowlist.NewContractDeployerAllowListConfig(big.NewInt(0), []common.Address{addr1}, nil),
feemanager.ConfigKey: feemanager.NewFeeManagerConfig(big.NewInt(0), []common.Address{addr1}, nil, nil),
deployerallowlist.ConfigKey: deployerallowlist.NewConfig(big.NewInt(0), []common.Address{addr1}, nil),
feemanager.ConfigKey: feemanager.NewConfig(big.NewInt(0), []common.Address{addr1}, nil, nil),
}
gspec := &Genesis{
Config: &config,
Expand Down
4 changes: 2 additions & 2 deletions core/tx_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ import (
"github.com/ava-labs/subnet-evm/core/types"
"github.com/ava-labs/subnet-evm/metrics"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/precompile/feemanager"
"github.com/ava-labs/subnet-evm/precompile/txallowlist"
"github.com/ava-labs/subnet-evm/precompile/contracts/feemanager"
"github.com/ava-labs/subnet-evm/precompile/contracts/txallowlist"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/prque"
Expand Down
17 changes: 9 additions & 8 deletions core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ import (

"github.com/ava-labs/subnet-evm/constants"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/precompile"
"github.com/ava-labs/subnet-evm/precompile/contract"
"github.com/ava-labs/subnet-evm/precompile/modules"
"github.com/ava-labs/subnet-evm/vmerrs"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
Expand All @@ -57,7 +58,7 @@ type PrecompiledContract interface {

// PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum
// contracts used in the Frontier and Homestead releases.
var PrecompiledContractsHomestead = map[common.Address]precompile.StatefulPrecompiledContract{
var PrecompiledContractsHomestead = map[common.Address]contract.StatefulPrecompiledContract{
common.BytesToAddress([]byte{1}): newWrappedPrecompiledContract(&ecrecover{}),
common.BytesToAddress([]byte{2}): newWrappedPrecompiledContract(&sha256hash{}),
common.BytesToAddress([]byte{3}): newWrappedPrecompiledContract(&ripemd160hash{}),
Expand All @@ -66,7 +67,7 @@ var PrecompiledContractsHomestead = map[common.Address]precompile.StatefulPrecom

// PrecompiledContractsByzantium contains the default set of pre-compiled Ethereum
// contracts used in the Byzantium release.
var PrecompiledContractsByzantium = map[common.Address]precompile.StatefulPrecompiledContract{
var PrecompiledContractsByzantium = map[common.Address]contract.StatefulPrecompiledContract{
common.BytesToAddress([]byte{1}): newWrappedPrecompiledContract(&ecrecover{}),
common.BytesToAddress([]byte{2}): newWrappedPrecompiledContract(&sha256hash{}),
common.BytesToAddress([]byte{3}): newWrappedPrecompiledContract(&ripemd160hash{}),
Expand All @@ -79,7 +80,7 @@ var PrecompiledContractsByzantium = map[common.Address]precompile.StatefulPrecom

// PrecompiledContractsIstanbul contains the default set of pre-compiled Ethereum
// contracts used in the Istanbul release.
var PrecompiledContractsIstanbul = map[common.Address]precompile.StatefulPrecompiledContract{
var PrecompiledContractsIstanbul = map[common.Address]contract.StatefulPrecompiledContract{
common.BytesToAddress([]byte{1}): newWrappedPrecompiledContract(&ecrecover{}),
common.BytesToAddress([]byte{2}): newWrappedPrecompiledContract(&sha256hash{}),
common.BytesToAddress([]byte{3}): newWrappedPrecompiledContract(&ripemd160hash{}),
Expand All @@ -93,7 +94,7 @@ var PrecompiledContractsIstanbul = map[common.Address]precompile.StatefulPrecomp

// PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum
// contracts used in the Berlin release.
var PrecompiledContractsBerlin = map[common.Address]precompile.StatefulPrecompiledContract{
var PrecompiledContractsBerlin = map[common.Address]contract.StatefulPrecompiledContract{
common.BytesToAddress([]byte{1}): newWrappedPrecompiledContract(&ecrecover{}),
common.BytesToAddress([]byte{2}): newWrappedPrecompiledContract(&sha256hash{}),
common.BytesToAddress([]byte{3}): newWrappedPrecompiledContract(&ripemd160hash{}),
Expand All @@ -107,7 +108,7 @@ var PrecompiledContractsBerlin = map[common.Address]precompile.StatefulPrecompil

// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
// contracts specified in EIP-2537. These are exported for testing purposes.
var PrecompiledContractsBLS = map[common.Address]precompile.StatefulPrecompiledContract{
var PrecompiledContractsBLS = map[common.Address]contract.StatefulPrecompiledContract{
common.BytesToAddress([]byte{10}): newWrappedPrecompiledContract(&bls12381G1Add{}),
common.BytesToAddress([]byte{11}): newWrappedPrecompiledContract(&bls12381G1Mul{}),
common.BytesToAddress([]byte{12}): newWrappedPrecompiledContract(&bls12381G1MultiExp{}),
Expand Down Expand Up @@ -158,8 +159,8 @@ func init() {

// Ensure that this package will panic during init if there is a conflict present with the declared
// precompile addresses.
for _, module := range precompile.RegisteredModules() {
address := module.Address()
for _, module := range modules.RegisteredModules() {
address := module.Address
if _, ok := PrecompileAllNativeAddresses[address]; ok {
panic(fmt.Errorf("precompile address collides with existing native address: %s", address))
}
Expand Down
8 changes: 4 additions & 4 deletions core/vm/contracts_stateful.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
package vm

import (
"github.com/ava-labs/subnet-evm/precompile"
"github.com/ava-labs/subnet-evm/precompile/contract"
"github.com/ethereum/go-ethereum/common"
)

Expand All @@ -16,16 +16,16 @@ type wrappedPrecompiledContract struct {

// newWrappedPrecompiledContract returns a wrapped version of [PrecompiledContract] to be executed according to the StatefulPrecompiledContract
// interface.
func newWrappedPrecompiledContract(p PrecompiledContract) precompile.StatefulPrecompiledContract {
func newWrappedPrecompiledContract(p PrecompiledContract) contract.StatefulPrecompiledContract {
return &wrappedPrecompiledContract{p: p}
}

// Run implements the StatefulPrecompiledContract interface
func (w *wrappedPrecompiledContract) Run(accessibleState precompile.PrecompileAccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
func (w *wrappedPrecompiledContract) Run(accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
return RunPrecompiledContract(w.p, input, suppliedGas)
}

// RunStatefulPrecompiledContract confirms runs [precompile] with the specified parameters.
func RunStatefulPrecompiledContract(precompile precompile.StatefulPrecompiledContract, accessibleState precompile.PrecompileAccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
func RunStatefulPrecompiledContract(precompile contract.StatefulPrecompiledContract, accessibleState contract.AccessibleState, caller common.Address, addr common.Address, input []byte, suppliedGas uint64, readOnly bool) (ret []byte, remainingGas uint64, err error) {
return precompile.Run(accessibleState, caller, addr, input, suppliedGas, readOnly)
}
27 changes: 16 additions & 11 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,18 @@ import (
"github.com/ava-labs/avalanchego/snow"
"github.com/ava-labs/subnet-evm/constants"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/precompile"
"github.com/ava-labs/subnet-evm/precompile/deployerallowlist"
"github.com/ava-labs/subnet-evm/precompile/contract"
"github.com/ava-labs/subnet-evm/precompile/contracts/deployerallowlist"
"github.com/ava-labs/subnet-evm/precompile/modules"
"github.com/ava-labs/subnet-evm/vmerrs"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/holiman/uint256"
)

var (
_ precompile.PrecompileAccessibleState = &EVM{}
_ precompile.BlockContext = &BlockContext{}
_ contract.AccessibleState = &EVM{}
_ contract.BlockContext = &BlockContext{}
)

// IsProhibited returns true if [addr] is in the prohibited list of addresses which should
Expand All @@ -55,7 +56,7 @@ func IsProhibited(addr common.Address) bool {
return true
}

return precompile.ReservedAddress(addr)
return modules.ReservedAddress(addr)
}

// emptyCodeHash is used by create to ensure deployment is disallowed to already
Expand All @@ -72,8 +73,8 @@ type (
GetHashFunc func(uint64) common.Hash
)

func (evm *EVM) precompile(addr common.Address) (precompile.StatefulPrecompiledContract, bool) {
var precompiles map[common.Address]precompile.StatefulPrecompiledContract
func (evm *EVM) precompile(addr common.Address) (contract.StatefulPrecompiledContract, bool) {
var precompiles map[common.Address]contract.StatefulPrecompiledContract
switch {
case evm.chainRules.IsSubnetEVM:
precompiles = PrecompiledContractsBerlin
Expand All @@ -92,8 +93,12 @@ func (evm *EVM) precompile(addr common.Address) (precompile.StatefulPrecompiledC
}

// Otherwise, check the chain rules for the additionally configured precompiles.
p, ok = evm.chainRules.ActivePrecompiles[addr]
return p, ok
if _, ok = evm.chainRules.ActivePrecompiles[addr]; ok {
module, ok := modules.GetPrecompileModuleByAddress(addr)
return module.Contract, ok
}

return nil, false
}

// BlockContext provides the EVM with auxiliary information. Once provided
Expand Down Expand Up @@ -208,12 +213,12 @@ func (evm *EVM) GetSnowContext() *snow.Context {
}

// GetStateDB returns the evm's StateDB
func (evm *EVM) GetStateDB() precompile.StateDB {
func (evm *EVM) GetStateDB() contract.StateDB {
return evm.StateDB
}

// GetBlockContext returns the evm's BlockContext
func (evm *EVM) GetBlockContext() precompile.BlockContext {
func (evm *EVM) GetBlockContext() contract.BlockContext {
return &evm.Context
}

Expand Down
2 changes: 1 addition & 1 deletion eth/gasprice/gasprice.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import (
"github.com/ava-labs/subnet-evm/core"
"github.com/ava-labs/subnet-evm/core/types"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/precompile/feemanager"
"github.com/ava-labs/subnet-evm/precompile/contracts/feemanager"
"github.com/ava-labs/subnet-evm/rpc"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
Expand Down
Loading