Skip to content

Design: GoQuarkChain rearchitecture — without regenesis#139

Open
ping-ke wants to merge 3 commits intomainfrom
goqkc-upgrade-design
Open

Design: GoQuarkChain rearchitecture — without regenesis#139
ping-ke wants to merge 3 commits intomainfrom
goqkc-upgrade-design

Conversation

@ping-ke
Copy link
Copy Markdown
Contributor

@ping-ke ping-ke commented May 7, 2026

Summary

Adds the primary design doc for the GoQuarkChain rearchitecture ( Embedded geth — Avoids Regenesis), which drives the upcoming Go / geth upgrade and EVM alignment work.

The document specifies how to replace the vendored go-ethereum v1.8.20 with a QuarkChain fork of upstream geth v1.17.2+ without regenesis, covering the architectural split, hard-fork mechanism, lazy state migration, transaction format migration, xshard redesign, block header mapping, the geth patch set, and the new module layout.

Highlights

  • Go / geth upgrade: Go bumped to 1.24+; go.mod uses replace to point at QuarkChain/go-ethereum v1.17.2-qkc. Divergence from upstream is collapsed into 6 targeted patches, so future upgrades land via git merge upstream with conflicts confined to those files.
  • CL/EL split inside the Slave binary: a clean ExecutionLayer Go interface boundary is introduced, but the deployment topology (master + N slaves), the master–slave gRPC protocol, and the P2P wire protocol are all unchanged.
  • Hard fork instead of regenesis: the fork is keyed on root block height. A single Slave binary routes per minor block to LegacyEL (existing MinorBlockChain) or ModernEL (embedded upstream geth) based on PrevRootBlockHeight.
  • Lazy state migration: legacy TokenBalance Map accounts are decoded on read and rewritten in standard geth format on commit. Non-native tokens migrate via a pre-deployed TokenMigrationRegistry + per-token ERC-20 contracts, with system mints triggered on first account access — zero overhead at the fork block.
  • xshard redesign with unchanged external semantics: source side becomes an XshardSend system contract; destination side introduces an OP-style EIP-2718 type 0x71 XShardDepositTx system transaction. Slave-to-slave TCP distribution, the gas model, and execution ordering are all preserved.
  • Transaction format: post-fork ModernEL accepts EIP-1559 (type 0x02) only. Two pre-fork suspension windows (N-20 xshard pause, N-10 full tx pause) drain the mempool and xshard queue before cutover. MetaMask users transition transparently via baseFee auto-detection.
  • Block header: MinorBlockHeader is kept as the on-chain type so the root block format is unchanged. Two projection helpers (toGethHeader() / gethHeaderToMinorBlockHeader()) bridge to/from ethTypes.Header; post-fork, the canonical minor-block hash is geth's Header.Hash().

Scope of this PR

  • Adds a single document: L1/goquarkchain-redesign-avoids-regenesis.md (916 lines).
  • No code changes. Implementation will land in follow-up PRs split along the document's structure: the 6-patch geth fork, shardcl/, shardel/, system contracts (XshardSend, TokenMigrationRegistry), and metamask_api.go adaptation.

Open Questions

Items the doc flags as undecided and worth resolving during review:

  • The concrete value of QKCForkRootHeight (governance decision).
  • Whether ModernEL needs any backward compatibility for legacy QKC v1/v2 or EIP-155 legacy txs (see the explicit Question in §7.4 Phase 1).
  • Whether to replace gorocksdb with pebble, and whether to drop bou.ke/monkey (Go 1.17+ unsafe restrictions).
  • Snap-sync support for legacy-encoded accounts — relies on patch P4 and needs its own implementation PR.

Reviewer Focus

Suggested areas for close review:

  1. §5 Hard Fork: do the N-20 / N-10 suspension windows plus the setHead(confirmedHeaderTip) cutover inside AddRootBlock(N) actually guarantee an empty mempool and an empty xshard queue at the fork boundary?
  2. §6 State migration: is forcing journal.dirty inside load() for accounts with non-native balances sufficient to prevent the double-mint hazard on read-only access?
  3. §9 Header projection: dropping QKC-only fields (CoinbaseAmount, MetaHash) post-fork — any consensus implication on the root chain side?
  4. §11 geth patch set: are the 6 patches the minimal viable surface, or can any of them be pushed out of the geth tree into the QKC side?

Comment thread L1/goquarkchain-redesign-avoids-regenesis.md Outdated
Comment thread L1/goquarkchain-redesign-avoids-regenesis.md Outdated
Comment thread L1/goquarkchain-redesign-avoids-regenesis.md Outdated
Comment thread L1/goquarkchain-redesign-avoids-regenesis.md Outdated
Comment thread L1/goquarkchain-redesign-avoids-regenesis.md Outdated
Comment thread L1/goquarkchain-redesign-avoids-regenesis.md
Comment thread L1/goquarkchain-redesign-avoids-regenesis.md
Comment thread L1/goquarkchain-redesign-avoids-regenesis.md Outdated
@qzhodl
Copy link
Copy Markdown
Contributor

qzhodl commented May 8, 2026

There’s a lot of overlap with #137. Could you show only the differences so reviewers don’t have to go through the same content again?

@ping-ke
Copy link
Copy Markdown
Contributor Author

ping-ke commented May 8, 2026

GoQuarkChain Redesign: Plan Comparison

Two redesign plans are under consideration:


Core Differences

Dimension Plan A (No Regenesis) Plan B (Regenesis)
Regenesis No — hard fork continues existing chain Yes — full regenesis required
EL Architecture Embedded geth library (in-process Go interface) Separate geth process (Engine API over HTTP loopback)
Historical Data Fully preserved — pre-fork blocks replayed via LegacyEL Balance snapshot only — tx history not migrated
State Migration Lazy in-place conversion (TokenBalance Map → standard account on first access) Not needed — new genesis writes standard format directly
Multi-native Token Lazy ERC-20 migration: token owners must register ERC-20 contract before fork; unregistered balances are permanently inaccessible Dropped entirely — only native token remains; other tokens re-deployed as ERC-20
Block Header Keeps MinorBlockHeader struct; hash computation is fork-aware (pre-fork: QKC serialization, post-fork: projects to geth Header) Standard Ethereum block header embedded directly in root block; MinorBlockHeader/MinorBlockMeta split eliminated
Client Diversity Not supported — EL is tightly coupled as embedded library Supported — Engine API boundary allows swapping to reth, Erigon, etc.

xshard Design

The xshard design is not the main part of the review; the xshard designs in the two plans can be applied to each other.


Pros and Cons

Plan A — No Regenesis

Pros

  • Chain continuity: users retain full history, no asset migration required
  • No community consensus needed on regenesis
  • Deployment topology unchanged (master + N slaves); zero new processes
  • Smooth rollout: LegacyEL and ModernEL run in parallel during transition

Cons

  • Higher implementation complexity: dual EL routing, lazy state migration, fork-aware header hashing, shared state DB
  • Lazy migration edge case: non-native token balances are not available until the block after first account access
  • Unregistered non-native token balances are permanently lost — requires early public announcement and token owner action before fork
  • LegacyEL code lives in the codebase indefinitely, increasing long-term maintenance burden
  • EL is not swappable — locked to embedded geth

Plan B — Regenesis

Pros

  • Cleanest implementation — no legacy compatibility layer
  • Full Ethereum ecosystem compatibility from day one (standard EIP-1559 txs, tooling, block explorers)
  • Engine API boundary enables future EL client diversity (reth, Erigon, etc.)
  • Lowest long-term maintenance cost — geth upgrades are routine rebases

Cons

  • Regenesis carries the highest non-engineering cost: community acceptance, user asset migration, dApp redeployment, loss of transaction history
  • Requires additional infrastructure: snapshot tooling, new genesis generation, migration scripts
  • One EL process per shard increases operational complexity

Summary

The choice reduces to engineering cost vs. community cost:

  • If regenesis is socially and operationally acceptable, Plan B is the better long-term choice — cleaner code, full ecosystem compatibility, and lower ongoing maintenance.
  • If chain continuity is required (exchange listings, existing dApp ecosystem, user base), Plan A is the only viable path, at the cost of a significantly more complex implementation.

@ping-ke ping-ke changed the title Design: GoQuarkChain rearchitecture — embedded geth, no regenesis Design: GoQuarkChain rearchitecture — without regenesis May 8, 2026
@ping-ke ping-ke requested a review from blockchaindevsh May 11, 2026 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants