Skip to content

Commit

Permalink
Move atomic trie root to clementine upgrade (#1037)
Browse files Browse the repository at this point in the history
* Move atomic trie root to clementine upgrade

* params: tidy chain config printout

* Fix genesis JSON for blueberry and clementine
  • Loading branch information
aaronbuchwald authored Sep 16, 2022
1 parent 3e233a2 commit b76c749
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 57 deletions.
2 changes: 1 addition & 1 deletion core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ type Header struct {
// headers.
BlockGasCost *big.Int `json:"blockGasCost" rlp:"optional"`

// ExtraStateRoot root was added by Blueberry and is ignored in legacy headers.
// ExtraStateRoot root was added by Clementine and is ignored in legacy headers.
ExtraStateRoot common.Hash `json:"extraStateRoot" rlp:"optional"`
}

Expand Down
63 changes: 42 additions & 21 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ var (
ApricotPhase6BlockTimestamp: big.NewInt(time.Date(2022, time.September, 6, 20, 0, 0, 0, time.UTC).Unix()),
ApricotPhasePost6BlockTimestamp: big.NewInt(time.Date(2022, time.September, 7, 3, 0, 0, 0, time.UTC).Unix()),
// TODO Add Blueberry
// TODO Add Clementine
}

// AvalancheFujiChainConfig is the configuration for the Fuji Test Network
Expand All @@ -100,6 +101,7 @@ var (
ApricotPhase6BlockTimestamp: big.NewInt(time.Date(2022, time.September, 6, 20, 0, 0, 0, time.UTC).Unix()),
ApricotPhasePost6BlockTimestamp: big.NewInt(time.Date(2022, time.September, 7, 6, 0, 0, 0, time.UTC).Unix()),
// TODO Add Blueberry
// TODO Add Clementine
}

// AvalancheLocalChainConfig is the configuration for the Avalanche Local Network
Expand All @@ -126,19 +128,21 @@ var (
ApricotPhase6BlockTimestamp: big.NewInt(0),
ApricotPhasePost6BlockTimestamp: big.NewInt(0),
BlueberryBlockTimestamp: big.NewInt(0),
}

TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0)}
TestLaunchConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, nil}
TestApricotPhase1Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil}
TestApricotPhase2Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil}
TestApricotPhase3Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil}
TestApricotPhase4Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil}
TestApricotPhase5Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil}
TestApricotPhasePre6Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil}
TestApricotPhase6Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil}
TestApricotPhasePost6Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil}
TestBlueberryChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0)}
ClementineBlockTimestamp: big.NewInt(0),
}

TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0)}
TestLaunchConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil}
TestApricotPhase1Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil, nil}
TestApricotPhase2Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil, nil}
TestApricotPhase3Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, nil}
TestApricotPhase4Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil}
TestApricotPhase5Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil}
TestApricotPhasePre6Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil}
TestApricotPhase6Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil}
TestApricotPhasePost6Config = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil}
TestBlueberryChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil}
TestClementineChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0)}
TestRules = TestChainConfig.AvalancheRules(new(big.Int), new(big.Int))
)

Expand Down Expand Up @@ -187,6 +191,8 @@ type ChainConfig struct {
ApricotPhasePost6BlockTimestamp *big.Int `json:"apricotPhasePost6BlockTimestamp,omitempty"`
// Blueberry TODO comment. (nil = no fork, 0 = already activated)
BlueberryBlockTimestamp *big.Int `json:"blueberryBlockTimestamp,omitempty"`
// Clementine TODO comment. (nil = no fork, 0 = already activated)
ClementineBlockTimestamp *big.Int `json:"clementineBlockTimestamp,omitempty"`
}

// String implements the fmt.Stringer interface.
Expand Down Expand Up @@ -214,15 +220,16 @@ func (c *ChainConfig) String() string {
if c.MuirGlacierBlock != nil {
banner += fmt.Sprintf(" - Muir Glacier: %-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/muir-glacier.md)\n", c.MuirGlacierBlock)
}
banner += fmt.Sprintf(" - Apricot Phase 1 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.3.0)\n", c.ApricotPhase1BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase 2 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.4.0)\n", c.ApricotPhase2BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase 3 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.5.0)\n", c.ApricotPhase3BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase 4 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.6.0)\n", c.ApricotPhase4BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase 5 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.7.0)\n", c.ApricotPhase5BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase P6 Timestamp %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0)\n", c.ApricotPhasePre6BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase 6 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0)\n", c.ApricotPhase6BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase 1 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.3.0)\n", c.ApricotPhase1BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase 2 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.4.0)\n", c.ApricotPhase2BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase 3 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.5.0)\n", c.ApricotPhase3BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase 4 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.6.0)\n", c.ApricotPhase4BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase 5 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.7.0)\n", c.ApricotPhase5BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase P6 Timestamp %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0)\n", c.ApricotPhasePre6BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase 6 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0)\n", c.ApricotPhase6BlockTimestamp)
banner += fmt.Sprintf(" - Apricot Phase Post-6 Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.8.0\n", c.ApricotPhasePost6BlockTimestamp)
banner += fmt.Sprintf(" - Blueberry Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.10.0)\n", c.BlueberryBlockTimestamp)
banner += fmt.Sprintf(" - Blueberry Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.9.0)\n", c.BlueberryBlockTimestamp)
banner += fmt.Sprintf(" - Clementine Timestamp: %-8v (https://github.com/ava-labs/avalanchego/releases/tag/v1.10.0)\n", c.ClementineBlockTimestamp)
banner += "\n"
return banner
}
Expand Down Expand Up @@ -335,6 +342,12 @@ func (c *ChainConfig) IsBlueberry(blockTimestamp *big.Int) bool {
return utils.IsForked(c.BlueberryBlockTimestamp, blockTimestamp)
}

// IsClementine returns whether [blockTimestamp] represents a block
// with a timestamp after the Clementine upgrade time.
func (c *ChainConfig) IsClementine(blockTimestamp *big.Int) bool {
return utils.IsForked(c.ClementineBlockTimestamp, blockTimestamp)
}

// CheckCompatible checks whether scheduled fork transitions have been imported
// with a mismatching chain configuration.
func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, timestamp uint64) *ConfigCompatError {
Expand Down Expand Up @@ -413,6 +426,8 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
{name: "apricotPhasePre6BlockTimestamp", block: c.ApricotPhasePre6BlockTimestamp},
{name: "apricotPhase6BlockTimestamp", block: c.ApricotPhase6BlockTimestamp},
{name: "apricotPhasePost6BlockTimestamp", block: c.ApricotPhasePost6BlockTimestamp},
{name: "blueberryBlockTimestamp", block: c.BlueberryBlockTimestamp},
{name: "clementineBlockTimestamp", block: c.ClementineBlockTimestamp},
} {
if lastFork.name != "" {
// Next one must be higher number
Expand Down Expand Up @@ -495,10 +510,14 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headHeight *big.Int,
if isForkIncompatible(c.ApricotPhase5BlockTimestamp, newcfg.ApricotPhase5BlockTimestamp, headTimestamp) {
return newCompatError("ApricotPhase5 fork block timestamp", c.ApricotPhase5BlockTimestamp, newcfg.ApricotPhase5BlockTimestamp)
}
// TODO: add Phase 6 checks

if isForkIncompatible(c.BlueberryBlockTimestamp, newcfg.BlueberryBlockTimestamp, headTimestamp) {
return newCompatError("Blueberry fork block timestamp", c.BlueberryBlockTimestamp, newcfg.BlueberryBlockTimestamp)
}
if isForkIncompatible(c.ClementineBlockTimestamp, newcfg.ClementineBlockTimestamp, headTimestamp) {
return newCompatError("Clementine fork block timestamp", c.ClementineBlockTimestamp, newcfg.ClementineBlockTimestamp)
}
return nil
}

Expand Down Expand Up @@ -563,6 +582,7 @@ type Rules struct {
IsApricotPhase1, IsApricotPhase2, IsApricotPhase3, IsApricotPhase4, IsApricotPhase5 bool
IsApricotPhasePre6, IsApricotPhase6, IsApricotPhasePost6 bool
IsBlueberry bool
IsClementine bool

// Precompiles maps addresses to stateful precompiled contracts that are enabled
// for this rule set.
Expand Down Expand Up @@ -604,6 +624,7 @@ func (c *ChainConfig) AvalancheRules(blockNum, blockTimestamp *big.Int) Rules {
rules.IsApricotPhase6 = c.IsApricotPhase6(blockTimestamp)
rules.IsApricotPhasePost6 = c.IsApricotPhasePost6(blockTimestamp)
rules.IsBlueberry = c.IsBlueberry(blockTimestamp)
rules.IsClementine = c.IsClementine(blockTimestamp)

// Initialize the stateful precompiles that should be enabled at [blockTimestamp].
rules.Precompiles = make(map[common.Address]precompile.StatefulPrecompiledContract)
Expand Down
6 changes: 3 additions & 3 deletions plugin/evm/block_verification.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,13 +241,13 @@ func (v blockValidator) SyntacticVerify(b *Block, rules params.Rules) error {
}
}

if rules.IsBlueberry {
// In Blueberry, ExtraStateRoot must not be empty (should contain the root of the atomic trie).
if rules.IsClementine {
// In Clementine, ExtraStateRoot must not be empty (should contain the root of the atomic trie).
if ethHeader.ExtraStateRoot == (common.Hash{}) {
return fmt.Errorf("%w: ExtraStateRoot must not be empty", errInvalidExtraStateRoot)
}
} else {
// Before Blueberry, ExtraStateRoot must be empty.
// Before Clementine, ExtraStateRoot must be empty.
if ethHeader.ExtraStateRoot != (common.Hash{}) {
return fmt.Errorf("%w: ExtraStateRoot must be empty", errInvalidExtraStateRoot)
}
Expand Down
8 changes: 4 additions & 4 deletions plugin/evm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -775,8 +775,8 @@ func (vm *VM) postBatchOnFinalizeAndAssemble(header *types.Header, state *state.
size += txSize
}

// In Blueberry the block header must include the atomic trie root.
if rules.IsBlueberry {
// In Clementine the block header must include the atomic trie root.
if rules.IsClementine {
// Pass common.Hash{} as the current block's hash to the atomic backend, this avoids
// pinning changes to the atomic trie in memory, as we are still computing the header
// for this block and don't have its hash yet. Here we calculate the root of the atomic
Expand Down Expand Up @@ -848,8 +848,8 @@ func (vm *VM) onExtraStateChange(block *types.Block, state *state.StateDB) (*big
if err != nil {
return nil, nil, err
}
if rules.IsBlueberry {
// In Blueberry, the atomic trie root should be in ExtraStateRoot.
if rules.IsClementine {
// In Clementine, the atomic trie root should be in ExtraStateRoot.
if header.ExtraStateRoot != atomicRoot {
return nil, nil, fmt.Errorf(
"%w: (expected %s) (got %s)", errInvalidExtraStateRoot, header.ExtraStateRoot, atomicRoot,
Expand Down
Loading

0 comments on commit b76c749

Please sign in to comment.