From 883b83ca9a743724b24c5dfb4e7bd2b64cd223cc Mon Sep 17 00:00:00 2001 From: Ceyhun Onur Date: Thu, 2 Mar 2023 13:29:47 +0300 Subject: [PATCH 1/2] add unmarshaller --- internal/ethapi/api.go | 4 +- params/config.go | 149 +++++++++++++++++++++++------------------ params/config_test.go | 25 ++++++- 3 files changed, 109 insertions(+), 69 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 947fd32bb1..e9216e085e 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -138,8 +138,8 @@ func (s *EthereumAPI) Syncing() (interface{}, error) { return false, nil } -func (s *BlockChainAPI) GetChainConfig(ctx context.Context) *params.ChainConfigWithUpgradesMarshalled { - return s.b.ChainConfig().ToWithUpgradesMarshalled() +func (s *BlockChainAPI) GetChainConfig(ctx context.Context) *params.ChainConfigWithUpgradesJSON { + return s.b.ChainConfig().ToWithUpgradesJSON() } // TxPoolAPI offers and API for the transaction pool. It only operates on data that is non confidential. diff --git a/params/config.go b/params/config.go index 81067168f3..db412f9746 100644 --- a/params/config.go +++ b/params/config.go @@ -133,6 +133,24 @@ var ( } ) +// UpgradeConfig includes the following configs that may be specified in upgradeBytes: +// - Timestamps that enable avalanche network upgrades, +// - Enabling or disabling precompiles as network upgrades. +type UpgradeConfig struct { + // Config for blocks/timestamps that enable network upgrades. + // Note: if NetworkUpgrades is specified in the JSON all previously activated + // forks must be present or upgradeBytes will be rejected. + NetworkUpgrades *NetworkUpgrades `json:"networkUpgrades,omitempty"` + + // Config for enabling and disabling precompiles as network upgrades. + PrecompileUpgrades []PrecompileUpgrade `json:"precompileUpgrades,omitempty"` +} + +// AvalancheContext provides Avalanche specific context directly into the EVM. +type AvalancheContext struct { + SnowCtx *snow.Context +} + // ChainConfig is the core config which determines the blockchain settings. // // ChainConfig is stored in the database on a per block basis. This means @@ -213,71 +231,6 @@ func (c ChainConfig) MarshalJSON() ([]byte, error) { return json.Marshal(raw) } -type ChainConfigWithUpgradesMarshalled struct { - *ChainConfig - UpgradeConfig UpgradeConfig `json:"upgrades,omitempty"` -} - -// MarshalJSON implements json.Marshaler. This is a workaround for the fact that -// the embedded ChainConfig struct has a MarshalJSON method, which prevents -// the default JSON marshalling from working for UpgradeConfig. -// TODO: consider removing this method by allowing external tag for the embedded -// ChainConfig struct. -func (s *ChainConfigWithUpgradesMarshalled) MarshalJSON() ([]byte, error) { - // embed the ChainConfig struct into the response - chainConfigJSON, err := json.Marshal(s.ChainConfig) - if err != nil { - return nil, err - } - if len(chainConfigJSON) > maxJSONLen { - return nil, errors.New("value too large") - } - - type upgrades struct { - UpgradeConfig UpgradeConfig `json:"upgrades"` - } - - upgradeJSON, err := json.Marshal(upgrades{s.UpgradeConfig}) - if err != nil { - return nil, err - } - if len(upgradeJSON) > maxJSONLen { - return nil, errors.New("value too large") - } - - // merge the two JSON objects - mergedJSON := make([]byte, 0, len(chainConfigJSON)+len(upgradeJSON)+1) - mergedJSON = append(mergedJSON, chainConfigJSON[:len(chainConfigJSON)-1]...) - mergedJSON = append(mergedJSON, ',') - mergedJSON = append(mergedJSON, upgradeJSON[1:]...) - return mergedJSON, nil -} - -func (c *ChainConfig) ToWithUpgradesMarshalled() *ChainConfigWithUpgradesMarshalled { - return &ChainConfigWithUpgradesMarshalled{ - ChainConfig: c, - UpgradeConfig: c.UpgradeConfig, - } -} - -// UpgradeConfig includes the following configs that may be specified in upgradeBytes: -// - Timestamps that enable avalanche network upgrades, -// - Enabling or disabling precompiles as network upgrades. -type UpgradeConfig struct { - // Config for blocks/timestamps that enable network upgrades. - // Note: if NetworkUpgrades is specified in the JSON all previously activated - // forks must be present or upgradeBytes will be rejected. - NetworkUpgrades *NetworkUpgrades `json:"networkUpgrades,omitempty"` - - // Config for enabling and disabling precompiles as network upgrades. - PrecompileUpgrades []PrecompileUpgrade `json:"precompileUpgrades,omitempty"` -} - -// AvalancheContext provides Avalanche specific context directly into the EVM. -type AvalancheContext struct { - SnowCtx *snow.Context -} - // String implements the fmt.Stringer interface. func (c *ChainConfig) String() string { // convert nested data structures to json @@ -664,3 +617,69 @@ func (c *ChainConfig) GetFeeConfig() commontype.FeeConfig { func (c *ChainConfig) AllowedFeeRecipients() bool { return c.AllowFeeRecipients } + +type ChainConfigWithUpgradesJSON struct { + ChainConfig + UpgradeConfig UpgradeConfig `json:"upgrades,omitempty"` +} + +// MarshalJSON implements json.Marshaler. This is a workaround for the fact that +// the embedded ChainConfig struct has a MarshalJSON method, which prevents +// the default JSON marshalling from working for UpgradeConfig. +// TODO: consider removing this method by allowing external tag for the embedded +// ChainConfig struct. +func (cu ChainConfigWithUpgradesJSON) MarshalJSON() ([]byte, error) { + // embed the ChainConfig struct into the response + chainConfigJSON, err := json.Marshal(cu.ChainConfig) + if err != nil { + return nil, err + } + if len(chainConfigJSON) > maxJSONLen { + return nil, errors.New("value too large") + } + + type upgrades struct { + UpgradeConfig UpgradeConfig `json:"upgrades"` + } + + upgradeJSON, err := json.Marshal(upgrades{cu.UpgradeConfig}) + if err != nil { + return nil, err + } + if len(upgradeJSON) > maxJSONLen { + return nil, errors.New("value too large") + } + + // merge the two JSON objects + mergedJSON := make([]byte, 0, len(chainConfigJSON)+len(upgradeJSON)+1) + mergedJSON = append(mergedJSON, chainConfigJSON[:len(chainConfigJSON)-1]...) + mergedJSON = append(mergedJSON, ',') + mergedJSON = append(mergedJSON, upgradeJSON[1:]...) + return mergedJSON, nil +} + +func (cu *ChainConfigWithUpgradesJSON) UnmarshalJSON(input []byte) error { + var cc ChainConfig + if err := json.Unmarshal(input, &cc); err != nil { + return err + } + + type upgrades struct { + UpgradeConfig UpgradeConfig `json:"upgrades"` + } + + var u upgrades + if err := json.Unmarshal(input, &u); err != nil { + return err + } + cu.ChainConfig = cc + cu.UpgradeConfig = u.UpgradeConfig + return nil +} + +func (c *ChainConfig) ToWithUpgradesJSON() *ChainConfigWithUpgradesJSON { + return &ChainConfigWithUpgradesJSON{ + ChainConfig: *c, + UpgradeConfig: c.UpgradeConfig, + } +} diff --git a/params/config_test.go b/params/config_test.go index 1b4fadbdb3..12d7b8beb2 100644 --- a/params/config_test.go +++ b/params/config_test.go @@ -230,8 +230,24 @@ func TestActivePrecompiles(t *testing.T) { } func TestChainConfigMarshalWithUpgrades(t *testing.T) { - config := ChainConfigWithUpgradesMarshalled{ - ChainConfig: TestChainConfig, + config := ChainConfigWithUpgradesJSON{ + ChainConfig: ChainConfig{ + ChainID: big.NewInt(1), + FeeConfig: DefaultFeeConfig, + AllowFeeRecipients: false, + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP150Hash: common.Hash{}, + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + NetworkUpgrades: NetworkUpgrades{big.NewInt(0)}, + GenesisPrecompiles: Precompiles{}, + }, UpgradeConfig: UpgradeConfig{ PrecompileUpgrades: []PrecompileUpgrade{ { @@ -244,4 +260,9 @@ func TestChainConfigMarshalWithUpgrades(t *testing.T) { require.NoError(t, err) expectedJSON := `{"chainId":1,"feeConfig":{"gasLimit":8000000,"targetBlockRate":2,"minBaseFee":25000000000,"targetGas":15000000,"baseFeeChangeDenominator":36,"minBlockGasCost":0,"maxBlockGasCost":1000000,"blockGasCostStep":200000},"homesteadBlock":0,"eip150Block":0,"eip150Hash":"0x0000000000000000000000000000000000000000000000000000000000000000","eip155Block":0,"eip158Block":0,"byzantiumBlock":0,"constantinopleBlock":0,"petersburgBlock":0,"istanbulBlock":0,"muirGlacierBlock":0,"subnetEVMTimestamp":0,"upgrades":{"precompileUpgrades":[{"txAllowListConfig":{"blockTimestamp":100}}]}}` require.JSONEq(t, expectedJSON, string(result)) + + var unmarshalled ChainConfigWithUpgradesJSON + err = json.Unmarshal(result, &unmarshalled) + require.NoError(t, err) + require.Equal(t, config, unmarshalled) } From 473e9578a355826b412c660171bf94b984f77f3c Mon Sep 17 00:00:00 2001 From: Ceyhun Onur Date: Thu, 2 Mar 2023 19:42:05 +0300 Subject: [PATCH 2/2] add comments --- params/config.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/params/config.go b/params/config.go index db412f9746..af5010f3a2 100644 --- a/params/config.go +++ b/params/config.go @@ -677,6 +677,9 @@ func (cu *ChainConfigWithUpgradesJSON) UnmarshalJSON(input []byte) error { return nil } +// ToWithUpgradesJSON converts the ChainConfig to ChainConfigWithUpgradesJSON with upgrades explicitly displayed. +// ChainConfig does not include upgrades in its JSON output. +// This is a workaround for showing upgrades in the JSON output. func (c *ChainConfig) ToWithUpgradesJSON() *ChainConfigWithUpgradesJSON { return &ChainConfigWithUpgradesJSON{ ChainConfig: *c,