From 8497d107dde37a7c56ce6fe1f68dbdbd53589599 Mon Sep 17 00:00:00 2001 From: Josh Dechant Date: Fri, 7 Feb 2025 15:01:01 -0500 Subject: [PATCH] add precompiles to named fork config; fix issue with maps on fork configs --- core/vm/evm.go | 2 +- grpc/execution/server_test.go | 2 +- params/astria_config.go | 75 +++++++++++++++++++++++++++++------ params/astria_config_test.go | 23 ++++++++++- precompile/config/config.go | 40 +++++++++++++++---- 5 files changed, 119 insertions(+), 23 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index ac510f5fb..23ed3d79b 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -156,7 +156,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig // Set up precompiles evm.precompileManager = NewPrecompileManager(evm) - evm.precompileManager.RegisterMap(pconfig.PrecompileConfig(chainConfig, blockCtx.BlockNumber.Uint64(), blockCtx.Time)) + evm.precompileManager.RegisterMap(pconfig.GetPrecompiles(chainConfig, blockCtx.BlockNumber.Uint64(), blockCtx.Time)) return evm } diff --git a/grpc/execution/server_test.go b/grpc/execution/server_test.go index c92748903..f03dabb08 100644 --- a/grpc/execution/server_test.go +++ b/grpc/execution/server_test.go @@ -31,7 +31,7 @@ func TestExecutionService_GetGenesisInfo(t *testing.T) { hashedRollupId := sha256.Sum256([]byte(ethservice.BlockChain().Config().AstriaRollupName)) require.True(t, bytes.Equal(genesisInfo.RollupId.Inner, hashedRollupId[:]), "RollupId is not correct") - require.Equal(t, genesisInfo.GetSequencerStartBlockHeight(), ethservice.BlockChain().Config().AstriaForks.GetForkAtHeight(1).Sequencer.StartHeight, "SequencerInitialHeight is not correct") + require.Equal(t, genesisInfo.GetSequencerStartHeight(), ethservice.BlockChain().Config().AstriaForks.GetForkAtHeight(1).Sequencer.StartHeight, "SequencerInitialHeight is not correct") require.Equal(t, genesisInfo.GetCelestiaBlockVariance(), ethservice.BlockChain().Config().AstriaForks.GetForkAtHeight(1).Celestia.HeightVariance, "CelestiaHeightVariance is not correct") require.True(t, serviceV1Alpha1.genesisInfoCalled, "GetGenesisInfo should be called") } diff --git a/params/astria_config.go b/params/astria_config.go index a8fb83d76..a7bf3db69 100644 --- a/params/astria_config.go +++ b/params/astria_config.go @@ -20,15 +20,16 @@ type AstriaForks struct { } type AstriaForkConfig struct { - Height uint64 `json:"height"` - Halt bool `json:"halt,omitempty"` - SnapshotChecksum string `json:"snapshotChecksum,omitempty"` - ExtraDataOverride hexutil.Bytes `json:"extraDataOverride,omitempty"` - FeeCollector *common.Address `json:"feeCollector,omitempty"` - EIP1559Params *AstriaEIP1559Params `json:"eip1559Params,omitempty"` - Sequencer *AstriaSequencerConfig `json:"sequencer,omitempty"` - Celestia *AstriaCelestiaConfig `json:"celestia,omitempty"` - BridgeAddresses []AstriaBridgeAddressConfig `json:"bridgeAddresses,omitempty"` + Height uint64 `json:"height"` + Halt bool `json:"halt,omitempty"` + SnapshotChecksum string `json:"snapshotChecksum,omitempty"` + ExtraDataOverride hexutil.Bytes `json:"extraDataOverride,omitempty"` + FeeCollector *common.Address `json:"feeCollector,omitempty"` + EIP1559Params *AstriaEIP1559Params `json:"eip1559Params,omitempty"` + Sequencer *AstriaSequencerConfig `json:"sequencer,omitempty"` + Celestia *AstriaCelestiaConfig `json:"celestia,omitempty"` + BridgeAddresses []AstriaBridgeAddressConfig `json:"bridgeAddresses,omitempty"` + Precompiles map[common.Address]PrecompileType `json:"precompiles,omitempty"` } type AstriaForkData struct { @@ -44,6 +45,7 @@ type AstriaForkData struct { Celestia AstriaCelestiaConfig BridgeAddresses map[string]*AstriaBridgeAddressConfig // astria bridge addess to config for that bridge account BridgeAllowedAssets map[string]struct{} // a set of allowed asset IDs structs are left empty + Precompiles map[common.Address]PrecompileType } type AstriaSequencerConfig struct { @@ -114,9 +116,22 @@ func NewAstriaForks(forks map[string]AstriaForkConfig) (*AstriaForks, error) { if i > 0 { // Copy previous fork's configuration as the base orderedForks[i] = orderedForks[i-1] - } else { - // set default values - orderedForks[i] = GetDefaultAstriaForkData() + + // maps are pointers, so we need to create new maps for each fork + orderedForks[i].BridgeAddresses = make(map[string]*AstriaBridgeAddressConfig) + orderedForks[i].BridgeAllowedAssets = make(map[string]struct{}) + orderedForks[i].Precompiles = make(map[common.Address]PrecompileType) + + // Copy previous fork's maps if needed + for k, v := range orderedForks[i-1].BridgeAddresses { + orderedForks[i].BridgeAddresses[k] = v + } + for k, v := range orderedForks[i-1].BridgeAllowedAssets { + orderedForks[i].BridgeAllowedAssets[k] = v + } + for k, v := range orderedForks[i-1].Precompiles { + orderedForks[i].Precompiles[k] = v + } } // Set fork-specific fields @@ -186,6 +201,17 @@ func NewAstriaForks(forks map[string]AstriaForkConfig) (*AstriaForks, error) { } } } + + // add precompiles + if len(currentFork.Precompiles) > 0 { + for addr, pType := range currentFork.Precompiles { + orderedForks[i].Precompiles[addr] = pType + } + } + + if orderedForks[i].Precompiles == nil { + orderedForks[i].Precompiles = make(map[common.Address]PrecompileType) + } } if err := validateAstriaForks(orderedForks); err != nil { @@ -229,6 +255,12 @@ func validateAstriaForks(forks []AstriaForkData) error { if fork.FeeCollector == (common.Address{}) { log.Warn("fee asset collectors not set, assets will be burned", "fork", fork.Name) } + + for _, pType := range fork.Precompiles { + if err := pType.Validate(); err != nil { + return fmt.Errorf("fork %s: invalid precompile %s", fork.Name, pType) + } + } } else { log.Warn("fork will halt", "fork", fork.Name, "height", fork.Height) } @@ -249,6 +281,7 @@ func GetDefaultAstriaForkData() AstriaForkData { }, BridgeAddresses: make(map[string]*AstriaBridgeAddressConfig), BridgeAllowedAssets: make(map[string]struct{}), + Precompiles: make(map[common.Address]PrecompileType), } } @@ -370,3 +403,21 @@ func (abc *AstriaBridgeAddressConfig) ScaledDepositAmount(deposit *big.Int) *big return new(big.Int).Mul(deposit, multiplier) } + +// PrecompileType represents the type of precompile to enable +type PrecompileType string + +const ( + PrecompileBase64 PrecompileType = "base64" + // Add other precompile types here as needed +) + +// Validate ensures the PrecompileType is a known value +func (p PrecompileType) Validate() error { + switch p { + case PrecompileBase64: + return nil + default: + return fmt.Errorf("unknown precompile type: %s", p) + } +} diff --git a/params/astria_config_test.go b/params/astria_config_test.go index c90b48170..824810421 100644 --- a/params/astria_config_test.go +++ b/params/astria_config_test.go @@ -466,6 +466,9 @@ func TestAstriaForksInheritance(t *testing.T) { ElasticityMultiplier: 4, BaseFeeChangeDenominator: 16, }, + Precompiles: map[common.Address]PrecompileType{ + common.HexToAddress("0x01"): PrecompileBase64, + }, }, "fork3": { Height: 251, @@ -483,7 +486,9 @@ func TestAstriaForksInheritance(t *testing.T) { ChainID: "chain3", StartHeight: 325, }, - // EIP1559Params should be inherited from fork2 + Precompiles: map[common.Address]PrecompileType{ + common.HexToAddress("0x02"): PrecompileBase64, + }, }, } @@ -501,6 +506,7 @@ func TestAstriaForksInheritance(t *testing.T) { t.Logf(" Sequencer:") t.Logf(" ChainID: %s", fork.Sequencer.ChainID) t.Logf(" StartHeight: %d", fork.Sequencer.StartHeight) + t.Logf(" Precompiles: %v", fork.Precompiles) } type testCheck struct { @@ -513,6 +519,7 @@ func TestAstriaForksInheritance(t *testing.T) { celestiaChainID string celestiaStartHeight uint64 celestiaHeightVariance uint64 + precompiles map[common.Address]PrecompileType } tests := []struct { @@ -533,6 +540,7 @@ func TestAstriaForksInheritance(t *testing.T) { celestiaChainID: "celestia1", celestiaStartHeight: 1, celestiaHeightVariance: 100, + precompiles: map[common.Address]PrecompileType{}, }, }, { @@ -548,6 +556,9 @@ func TestAstriaForksInheritance(t *testing.T) { celestiaChainID: "celestia1", celestiaStartHeight: 1, celestiaHeightVariance: 100, + precompiles: map[common.Address]PrecompileType{ + common.HexToAddress("0x01"): PrecompileBase64, + }, }, }, { @@ -563,6 +574,9 @@ func TestAstriaForksInheritance(t *testing.T) { celestiaChainID: "celestia1", celestiaStartHeight: 1, celestiaHeightVariance: 100, + precompiles: map[common.Address]PrecompileType{ + common.HexToAddress("0x01"): PrecompileBase64, + }, }, }, { @@ -578,6 +592,10 @@ func TestAstriaForksInheritance(t *testing.T) { celestiaChainID: "celestia1", celestiaStartHeight: 1, celestiaHeightVariance: 100, + precompiles: map[common.Address]PrecompileType{ + common.HexToAddress("0x01"): PrecompileBase64, + common.HexToAddress("0x02"): PrecompileBase64, + }, }, }, } @@ -613,6 +631,9 @@ func TestAstriaForksInheritance(t *testing.T) { if got := fork.Celestia.HeightVariance; got != test.checks.celestiaHeightVariance { t.Errorf("Celestia.HeightVariance = %v, want %v", got, test.checks.celestiaHeightVariance) } + if !reflect.DeepEqual(fork.Precompiles, test.checks.precompiles) { + t.Errorf("Precompiles = %v, want %v", fork.Precompiles, test.checks.precompiles) + } }) } } diff --git a/precompile/config/config.go b/precompile/config/config.go index 9a60604f7..f0e9dea83 100644 --- a/precompile/config/config.go +++ b/precompile/config/config.go @@ -1,19 +1,43 @@ package config import ( + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/precompile" + pcbase64 "github.com/ethereum/go-ethereum/precompile/contracts/base64" ) var NullPrecompiles = precompile.PrecompileMap{} +// Cache of initialized precompiles for each fork +var precompileCache = make(map[string]precompile.PrecompileMap) + // return precompiles that are enabled at height -func PrecompileConfig(chainConfig *params.ChainConfig, height uint64, timestamp uint64) precompile.PrecompileMap { - // Example, enable the base64 precompile at address 0x0000000000000000000000000000000000001000: - // (add `import pcbase64 "github.com/ethereum/go-ethereum/precompile/contracts/base64"`) - // return precompile.PrecompileMap{ - // common.HexToAddress("0x01000"): pcbase64.NewBase64(), - // } - - return NullPrecompiles +func GetPrecompiles(chainConfig *params.ChainConfig, height uint64, timestamp uint64) precompile.PrecompileMap { + fork := chainConfig.GetAstriaForks().GetForkAtHeight(height) + + // Return early if no precompiles configured + if len(fork.Precompiles) == 0 { + return NullPrecompiles + } + + // Check if we've already initialized precompiles for this fork + if cached, exists := precompileCache[fork.Name]; exists { + return cached + } + + // Initialize precompiles for this fork + precompiles := make(precompile.PrecompileMap) + for addr, precompileType := range fork.Precompiles { + switch precompileType { + case params.PrecompileBase64: + precompiles[addr] = pcbase64.NewBase64() + default: + log.Error("Unknown precompile type", "type", precompileType, "address", addr) + } + } + + // Cache the initialized precompiles + precompileCache[fork.Name] = precompiles + return precompiles }