Skip to content

feat: unified hardfork upgrade system with CollectUpgrades registry#68

Merged
0xmhha merged 8 commits intodevfrom
feat/hardfork-upgrade-system
Apr 2, 2026
Merged

feat: unified hardfork upgrade system with CollectUpgrades registry#68
0xmhha merged 8 commits intodevfrom
feat/hardfork-upgrade-system

Conversation

@0xmhha
Copy link
Copy Markdown
Member

@0xmhha 0xmhha commented Mar 25, 2026

Summary

  • Introduce ChainConfig.CollectUpgrades() as the single source of truth for hardfork registration, replacing scattered manual append patterns
  • Add block-0 hardfork overlay in InjectContracts so mainnet genesis correctly includes all hardforks activated at genesis (e.g., Boho GovMinter v2)
  • Refactor GetSystemContractsStateTransition to merge multiple upgrades at the same block height
  • Separate system contract initialization (initialize*) and upgrade (upgrade*) paths
  • Fix genesis-updater tool to preserve block-0 hardforks in stripHardforkConfig

System Contract Versioning

System contracts follow a strict versioning protocol:

  • Version v1 is mandatory as the initial version. The initialize*() functions (e.g., initializeValidator, initializeMinter) are only invoked when Version == "v1". These functions set up the required storage layout (owner, quorum, members, etc.). Starting with any other version will skip initialization, leaving the contract in an uninitialized state.
  • Subsequent versions must increase monotonically (v2, v3, ...) in ascending block order. A higher version at a lower block followed by a lower version at a higher block (e.g., v3 at block 100, v2 at block 200) is invalid — downgrades are not supported.

Initialize vs Upgrade

Path Trigger Behavior
initialize*() Version == "v1" Full storage initialization with all required parameters
upgrade*() Version != "v1" (v2, v3, ...) Partial state migration — only keys present in Params are written; missing keys preserve on-chain state

When Params is nil, only the contract bytecode is replaced and no state changes are made. This is the standard hardfork upgrade scenario where code is swapped but existing governance state is preserved.

Genesis Hardfork Overlay

When a hardfork activates at block 0 (e.g., mainnet BohoBlock=0), InjectContracts applies it as an overlay on top of the baseline v1 contracts:

InjectContracts()
  Phase 1: Deploy Anzeon baseline (v1) — all system contracts initialized
  Phase 2: Apply block-0 hardfork overlays from CollectUpgrades()
           → e.g., Boho replaces GovMinter v1 bytecode with v2 (Params=nil → code only)

Hardforks with Block > 0 are skipped during genesis — they are applied at runtime via processFinalizeGetSystemContractsStateTransition.

Adding a New Hardfork

Adding a new hardfork requires only:

  1. Standard go-ethereum fields in ChainConfig (CForkBlock, CFork, IsCFork(), etc.)
  2. One entry in CollectUpgrades() — genesis and runtime paths are handled automatically

No changes needed in InjectContracts, SetConfigFromChainConfig, or processFinalize.

Changed files

Area Files Change
Registry params/config.go CollectUpgrades() method, updated genesis hash
Genesis core/genesis.go InjectContracts block-0 overlay via applyUpgradeOverlay
Runtime consensus/wbft/config.go Merge-based GetSystemContractsStateTransition
Engine eth/ethconfig/config.go SetConfigFromChainConfig uses CollectUpgrades()
Contracts systemcontracts/*.go initialize*/upgrade* split, Params nil guard
Tooling scripts/cmd/genesis-updater/main.go Preserve block-0 hardforks in stripHardforkConfig
Tests *_test.go (10 files) Comprehensive tests for all upgrade paths

Test plan

  • go test ./params/ — CollectUpgrades ordering, Boho at block 0 and block N
  • go test ./core/ — Genesis hash consistency, SetupGenesis, Anzeon init, Boho overlay
  • go test ./consensus/wbft/ — Merge-based state transition, multi-upgrade at same block
  • go test ./systemcontracts/ — initialize/upgrade routing, Params nil guard, partial params
  • go test ./eth/ethconfig/ — Engine config setup
  • go vet and gofmt pass on all modified packages

@0xmhha 0xmhha self-assigned this Mar 25, 2026
@0xmhha 0xmhha added the enhancement New feature or request label Mar 25, 2026
0xmhha added 5 commits March 30, 2026 18:04
Introduce a centralized hardfork registration mechanism via
ChainConfig.CollectUpgrades(), replacing scattered manual append
patterns. Block-0 hardforks are now applied during genesis through
InjectContracts overlay, and runtime hardforks via WBFT block
finalization with merged StateTransitions.

Key changes:
- Add CollectUpgrades() as single source of truth for hardfork registry
- Add InjectContracts with block-0 hardfork overlay support
- Refactor SetConfigFromChainConfig to use CollectUpgrades()
- Add upgrade*() functions for partial-param state migrations
- Fix genesis-updater to preserve block-0 hardforks in stripHardforkConfig
- Update mainnet genesis hash to reflect Boho overlay at genesis
- Add comprehensive tests for all upgrade paths
Update mainnet genesis gasLimit and difficulty to non-zero values.
Regenerate devp2p ethtest testdata with new validator keys and
fix snap test expected values to match updated state trie.
Replace manual Boho hardfork registration with CollectUpgrades()
to keep testutil.go in sync with ethconfig.SetConfigFromChainConfig.
Warn that contract params may have been modified by governance
proposals before a hardfork upgrade, and that upgrade authors
must query on-chain state to avoid silently overwriting
governance-approved values.
@0xmhha 0xmhha force-pushed the feat/hardfork-upgrade-system branch from 12cfee9 to 3a63463 Compare March 30, 2026 09:05
Enforce code-only upgrade principle: hardfork upgrades now only deploy
new contract bytecode without modifying on-chain state. State initialization
is restricted to v1 (genesis) only, preserving governance-modified values.
Copy link
Copy Markdown
Contributor

@colinkim colinkim left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Copy Markdown
Collaborator

@hominlee-wemade hominlee-wemade left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Copy Markdown
Contributor

@eomti-wm eomti-wm left a comment

Choose a reason for hiding this comment

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

LGTM

@0xmhha 0xmhha merged commit 05a81ec into dev Apr 2, 2026
3 checks passed
@hominlee-wemade hominlee-wemade deleted the feat/hardfork-upgrade-system branch April 9, 2026 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants