Skip to content

slave (M2): stand each shard at its real QKC minor genesis block - #26

Open
syntrust wants to merge 1 commit into
slave-m1.5from
slave-m2
Open

slave (M2): stand each shard at its real QKC minor genesis block#26
syntrust wants to merge 1 commit into
slave-m1.5from
slave-m2

Conversation

@syntrust

@syntrust syntrust commented Jul 3, 2026

Copy link
Copy Markdown

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/shard alone. The types, state encoding, and
qkc.CreateMinorBlock/ShardChainConfig this builds on moved to #44.

What's here

  • shard.goNew opens an isolated pebble chaindb under
    <datadir>/shard-<full_shard_id>, derives the genesis block, and hands the
    chain to ChainService. pyquarkchain's mem-db mode (an empty DB_PATH_ROOT)
    is supported; DBDirName/ParseDBDirName own the directory naming both ways.
  • rawdb.go — the genesis block itself is stored, so a reopen 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, not against block 0.
  • services.go — the ShardChain/ChainService seam. StubChainService
    stands 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.

  • Milestone demoTestShardNewAndReopen: boot shard 0x00000001, assert
    the datadir layout, the head at genesis and the stored block; reopen cleanly.
  • Reopen edges — genesis and root-genesis mismatch each fail loudly; an
    incompatible fork schedule is rejected; a failed first boot leaves no genesis
    behind; mem-db mode; Stop is idempotent.
  • rawdb — genesis round trip, reconcile against a head above genesis, a
    block-0 fork above genesis, read-only mode, and a missing chain config warning
    only where one was expected.

🤖 Generated with Claude Code

@syntrust
syntrust marked this pull request as draft July 3, 2026 09:45
@syntrust
syntrust marked this pull request as ready for review July 14, 2026 09:57
@syntrust syntrust changed the title slave (M2): add shard skeleton with ShardChain stub and genesis metadata slave (M2): add shard skeleton with ShardChain stub and genesis record Jul 16, 2026
@syntrust
syntrust changed the base branch from slave-m1 to goshard/base July 28, 2026 03:49
Comment thread qkc/shard/genesis.go Outdated
// 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 {

@qzhodl qzhodl Jul 28, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Updated in eaa33e9

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What is the relationship between Geth's genesis.go and the current genesis.go implementation?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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_keyqkc/state), and the block differs
(MinorBlock with QKC wire serialization, header+meta split).

@syntrust syntrust changed the title slave (M2): add shard skeleton with ShardChain stub and genesis record slave (M2): add shard skeleton with ShardChain stub and temporary genesis record Jul 28, 2026
@syntrust
syntrust requested a review from qzhodl July 28, 2026 10:35
@syntrust syntrust changed the title slave (M2): add shard skeleton with ShardChain stub and temporary genesis record slave (M2): stand each shard at its real QKC minor genesis block Jul 29, 2026
Comment thread qkc/shard/rawdb.go Outdated
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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

ReconcileChainConfig only called from the boot path, never from slave inspect; the comment was misleading.

Comment thread qkc/state/account.go

// 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 {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Does Ping’s MNT implementation modify this type in place, or does it use out-of-place like this?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

A TODO has been added to replace the current one once MNT arrives.

Comment thread qkc/state/alloc.go Outdated
@@ -0,0 +1,159 @@
// Copyright 2026-2027, QuarkChain.

package state

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done in b239117

Comment thread qkc/genesis.go
// 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

See #44

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>
@syntrust
syntrust changed the base branch from goshard/base to slave-m1.5 July 30, 2026 11:17
@syntrust
syntrust requested review from iteyelmp and qzhodl July 31, 2026 03:10
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