Conversation
…etadata Add the per-shard host the slave boots each of its shards through: - genesis.go: Genesis descriptor built from ShardGenesis (fields + parsed ALLOC) with a Petersburg-only ChainConfig, ChainID = BASE_ETH_CHAIN_ID + chain_id + 1 (pyquarkchain config.py:363); Fingerprint() gives the descriptor a deterministic identity the stub reports as its genesis hash. - services.go: the ShardChain seam (genesis hash, head, Stop) between the slave skeleton and the geth-core shard-chain task, plus the Options injection points for #4 (engine/miner), #5 (master conn), and sync; the stub chain reports head height 0 at the descriptor's identity. - rawdb.go: GenesisMeta record (root-genesis linkage + xshard cursor at (root_height, 0, 0), genesis.py:92) under a single QKC-prefixed key, encoded with qkc/serialize; ReconcileGenesisMeta passes reopen only on an exact match and hard-errors naming both genesis hashes and the db path. Marked temporary: re-implemented, not patched, once QKC block format (#1) lands. - shard.go: Shard{Branch, cfg, db, chain}; New opens an isolated pebble chaindb under {datadir}/shard-0x{full_shard_id}/, reconciles the metadata, and constructs the chain through the seam; Stop is idempotent and closes chain then db. qkc/config gains ETH_CHAIN_ID parsing on ChainConfig: pyquarkchain forces ETH_CHAIN_ID = BASE_ETH_CHAIN_ID + CHAIN_ID + 1 on load (config.py:534), so Validate() accepts a configured value only when consistent. Tests cover the descriptor (table-driven over the mainnet/devnet fixtures), fingerprint determinism/sensitivity, metadata round-trip, reconcile, the milestone demo (boot one shard into a temp dir, reopen idempotently), and the loud mismatch errors for shard- and root-genesis config changes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
syntrust
marked this pull request as ready for review
July 14, 2026 09:57
Shard.New logs "existing genesis validated" on reopen and "genesis metadata written" on first boot, using the new existed return value.
An empty DB_PATH_ROOT means an ephemeral in-memory database in pyquarkchain (use_mem_db, cluster_config.py:247) and in goquarkchain (geth's ephemeral-node convention). Previously it silently created a persistent pebble db in the process working directory.
… rule set - The ETH_CHAIN_ID derivation is computed in uint64, matching pyquarkchain's unbounded arithmetic; the uint32 sum wrapped silently (worst case to 0, which reads as "absent" and puts a wrong replay-protection chain id into the EVM rule set). - Fingerprint() now encodes the whole ChainConfig instead of just the chain id, so a change to the compiled-in fork schedule changes every fingerprint and forces a loud re-bootstrap instead of executing new semantics on an old db.
ReconcileGenesisMeta no longer writes on a fresh db: Shard.New commits the record once the chain stands at that genesis, so a boot that fails at chain construction leaves no record behind and the retry re-runs the fresh path instead of reporting a never-validated record as existing.
syntrust
requested review from
blockchaindevsh,
iteyelmp,
ping-ke,
qizhou and
qzhodl
July 15, 2026 11:10
Backport the final shape of the shard package into the milestone that creates it: DBDirName/ParseDBDirName canonicalize the shard chaindb directory names, and the stub-genesis surrogate paths carry their follow-up TODO markers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The record is a bootstrap stamp standing in for the genesis block, not a block "meta" in the pyquarkchain sense — half its fields live in the header there — so free the word before the QKC block format (#1) ports MinorBlockMeta. The chaindb key moves with it (QKC-genesis-meta -> QKC-genesis-record); no migration by design: the record is delete-not- migrate scaffolding, and a stub-era datadir simply re-stamps on its next boot. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Milestone 2 of the slave-node bootstrap (design doc, tracking #17), stacked on #21. Adds
qkc/shard— additions only: everything the slave needs to stand one shard up at its QKC genesis, with the real chain behind a stubbed seam.What's here
genesis.go) — per-shard genesis derived from the cluster config.Fingerprint()is the descriptor's identity and covers the full rule set, compiled-in fork schedule included — any drift forces a loud re-bootstrap instead of new semantics on an old db.ShardChainseam (services.go) — the narrow boundary ({GenesisHash, Head, Stop}) the geth-core shard chain plugs into later;StubChainServicestands in today.Optionscarries named injection points.GenesisRecord(rawdb.go) — the temporary genesis persistence, below.Shard(shard.go) — isolated pebble chaindb per shard under{datadir}/shard-0x{full_shard_id}/.rawdb.go: the temporaryGenesisRecordOne QKC-prefixed key (
QKC-genesis-record) stands in for the genesis block until the QKC block format (#1) lands. It does three jobs:HashPrevRootBlockand the initialXShardCursor((root_height, 0, 0), pyquarkchaingenesis.py:92);ReconcileGenesisRecordhard-errors when the cluster config changed since initialization — where goquarkchain silently keeps the stored genesis;Every symbol carries
TODO: temporary — remove once #1 lands. When #1 merges, the fields move into the genesis block itself, the reopen check becomes geth-native, and the record is deleted, not migrated — the db holds only genesis-level data, so re-bootstrap is free.Tests
go build ./cmd/slave && go test ./qkc/... ./cmd/slave/— 124 tests, 11 packages, green. Shard tests are table-driven over the real mainnet/devnet fixtures.TestShardNewAndReopen: boot shard0x00000001into a temp datadir; assert the datadir layout, head at height 0, and the stored record; stop and reopen the same directory cleanly.TestShardFailedFirstBootLeavesNoRecord).cluster config changed since initialization.Stop; unknown shard rejected;ETH_CHAIN_IDconsistency incl. the uint32-overflow boundary;DBDirNameround-trip.🤖 Generated with Claude Code