slave (M2): stand each shard at its real QKC minor genesis block - #26
slave (M2): stand each shard at its real QKC minor genesis block#26syntrust wants to merge 1 commit into
Conversation
| // the shard's config. It is handed to the ShardChain seam: materializing ALLOC | ||
| // into a real state root, committing the genesis block, and the EVM machinery all | ||
| // belong to the geth-core shard-chain task, not the slave skeleton. | ||
| type Genesis struct { |
There was a problem hiding this comment.
Could we clarify the intended integration path here? Once QKC minor-block types are available, this layer should pass the complete minor-genesis inputs to core and let geth’s existing NewBlockChain -> SetupGenesisBlock -> Genesis.Commit flow construct and persist block 0 on a fresh database, or compare the computed genesis hash and chain configuration on reopen. How are this descriptor, Fingerprint, GenesisRecord, and the stub expected to transition into that path? Without an explicit replacement plan, this appears to introduce a parallel genesis lifecycle in qkc/shard.
There was a problem hiding this comment.
What is the relationship between Geth's genesis.go and the current genesis.go implementation?
There was a problem hiding this comment.
core/genesis.go vs qkc/genesis.go
qkc genesis mirrors geth's genesis lifecycle logically, but reimplements it for the QKC block format.
geth core/genesis.go |
QKC side |
|---|---|
hashAlloc / flushAlloc share one assembly path |
CreateMinorBlock(…, db): memory db = derive identity only, real db = commit state |
Commit refuses Number != 0 |
GENESIS.HEIGHT != 0 rejected |
SetupGenesisBlock: stored block 0 vs config-derived |
ReconcileGenesisBlock: stored genesis block vs config-derived, by block hash |
typed GenesisMismatchError |
same, plus shard id and db path |
chain config stored beside genesis, keyed by its hash; CheckConfigForkOrder + CheckCompatible; never rewrite an identical config |
ShardChainConfig + ReconcileChainConfig — same flow |
Why parallel instead of reused: the state leaf differs (token-balances blob,
fixed-width full_shard_key → qkc/state), and the block differs
(MinorBlock with QKC wire serialization, header+meta split).
| return fmt.Errorf("shard 0x%08x: incompatible chain config (db %s): %w", fullShardID, dbPath, compatErr) | ||
| } | ||
| // Never rewrite an identical config: the datadir is also opened read-only | ||
| // (slave inspect), where any write fails. |
There was a problem hiding this comment.
We support read-only inspect for existing chain config. Should we also handle the missing-chain-config recovery path when the DB is opened read-only?
rawdb.WriteChainConfig(db, genesisHash, cfg)
There was a problem hiding this comment.
ReconcileChainConfig only called from the boot path, never from slave inspect; the comment was misleading.
|
|
||
| // Account is one leaf of the QuarkChain state trie, mirroring pyquarkchain's | ||
| // _Account (quarkchain/evm/state.py:66). The field order is the RLP encoding. | ||
| type Account struct { |
There was a problem hiding this comment.
Does Ping’s MNT implementation modify this type in place, or does it use out-of-place like this?
There was a problem hiding this comment.
A TODO has been added to replace the current one once MNT arrives.
| @@ -0,0 +1,159 @@ | |||
| // Copyright 2026-2027, QuarkChain. | |||
|
|
|||
| package state | |||
There was a problem hiding this comment.
This is genesis-specific glue rather than a general state API. Could we move it next to qkc/genesis.go as qkc/genesis_alloc.go and make the helpers package-private? This also removes the qkc/state dependency on qkc/config and mirrors geth hashAlloc/flushAlloc ownership.
| // genesis links to) is derived here; shard genesis state materialization belongs | ||
| // to the separate shard-chain task. | ||
| // The GenesisManager analog (quarkchain/genesis.py): pure functions of the parsed | ||
| // config that derive the cluster's genesis blocks — the root block, and each |
There was a problem hiding this comment.
This PR has grown too large. Could we move the genesis and minor-block changes together into a separate prerequisite PR, leaving this PR focused on shard bootstrap and lifecycle wiring?
One shard, booted on an isolated pebble chaindb under the slave's datadir and standing at its QuarkChain minor genesis block. The block itself is stored, so reopening a datadir reconciles by block hash (typed GenesisMismatchError, loud on a config change) rather than by a config fingerprint; the chain config is stored separately and reconciled through CheckCompatible against the real chain head. The chain sits behind the ShardChain seam, with StubChainService standing in until the real chain lands — the single genesis-block key is dropped once the chain owns block storage. pyquarkchain's mem-db mode (an empty DB_PATH_ROOT) is supported. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Milestone 2 of the slave-node bootstrap (design doc,
tracking #17), stacked on #44. That PR derives a shard's minor genesis block;
this one stands a shard up on it — an isolated chaindb per shard, the genesis
block persisted, and a reopened datadir reconciled against what is already
there.
Now scoped to
qkc/shardalone. The types, state encoding, andqkc.CreateMinorBlock/ShardChainConfigthis builds on moved to #44.What's here
shard.go—Newopens an isolated pebble chaindb under<datadir>/shard-<full_shard_id>, derives the genesis block, and hands thechain to
ChainService. pyquarkchain's mem-db mode (an emptyDB_PATH_ROOT)is supported;
DBDirName/ParseDBDirNameown the directory naming both ways.rawdb.go— the genesis block itself is stored, so a reopen reconciles byblock hash (typed
GenesisMismatchError, loud on a config change) rather thanby a config fingerprint. The chain config is stored separately and reconciled
through
CheckCompatibleagainst the real chain head, not against block 0.services.go— theShardChain/ChainServiceseam.StubChainServicestands in until the real chain lands; the single genesis-block key is dropped
once the chain owns block storage.
Tests
go build ./... && go test -race ./qkc/... ./cmd/slave/— green.TestShardNewAndReopen: boot shard0x00000001, assertthe datadir layout, the head at genesis and the stored block; reopen cleanly.
incompatible fork schedule is rejected; a failed first boot leaves no genesis
behind; mem-db mode;
Stopis idempotent.rawdb— genesis round trip, reconcile against a head above genesis, ablock-0 fork above genesis, read-only mode, and a missing chain config warning
only where one was expected.
🤖 Generated with Claude Code