Skip to content

slave (M1.5): derive the real QKC minor genesis block - #44

Open
syntrust wants to merge 4 commits into
goshard/basefrom
slave-m1.5
Open

slave (M1.5): derive the real QKC minor genesis block#44
syntrust wants to merge 4 commits into
goshard/basefrom
slave-m1.5

Conversation

@syntrust

Copy link
Copy Markdown

Split out of #26 as its prerequisite: the pure derivation half of milestone 2
(design doc,
tracking #17). qkc.CreateMinorBlock produces a shard's QuarkChain minor genesis
block — the real block, byte-compatible with pyquarkchain, not a config
fingerprint. No storage and no shard lifecycle here; #26 stacks that on top.

What's here

  • qkc/typesMinorBlockHeader/MinorBlockMeta/MinorBlock with QKC
    serialization. Transactions stay an opaque envelope; a genesis body is empty.
  • qkc/state — the QuarkChain state trie leaf: token-balances blob, and the
    owning address's full_shard_key as a fixed four-byte string rather than a
    uint32, so leading zeros survive into the state root.
  • qkc/genesis_alloc.goGENESIS.ALLOC materialization, split into
    GenesisAllocRoot/CommitGenesisAlloc as in geth's hashAlloc/flushAlloc.
  • qkc/genesis.goCreateMinorBlock and ShardChainConfig next to
    CreateRootBlock, mirroring pyquarkchain's GenesisManager. New validations:
    GENESIS.HEIGHT != 0, ROOT_HEIGHT != 0, ALLOC address ownership.
  • qkc/config — an explicit empty code in an ALLOC entry is a contract
    allocation (nonce 1) and no longer decodes the same as an absent one.

ShardChainConfig has no caller until #26; it ships here because it lives in
genesis.go next to its tests.

Tests

go build ./... && go test -race ./qkc/... ./cmd/slave/ — green.

  • Golden — pyquarkchain create_minor_block() for mainnet+devnet pinned at
    three levels: state root, meta hash, block hash (qkc/testdata/, regeneration
    recipe in qkc/config/singularity/README.md).
  • Negatives — non-zero HEIGHT/ROOT_HEIGHT, foreign-shard ALLOC, unknown
    shard, duplicate ALLOC recipients, inconsistent ETH_CHAIN_ID, chain-id
    overflow; empty-code round trip; derivation determinism and extra-data cloning.

🤖 Generated with Claude Code

syntrust and others added 4 commits July 30, 2026 19:01
…leaf

The QuarkChain-side types the minor genesis block is built out of, ahead of
deriving it.

- qkc/types: MinorBlockMeta/MinorBlockHeader/MinorBlock with QKC
  serialization; TypedTransaction stays an opaque envelope, which is all a
  genesis body (empty) needs. XShardTxCursorInfo is a meta field.
- qkc/state: the state trie leaf, mirroring pyquarkchain's _Account —
  per-token balances as a serialized blob and the owning address's
  full_shard_key as a fixed four-byte string, not a uint32, so leading
  zeros survive. The trie machinery underneath stays geth's.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
pyquarkchain treats an ALLOC entry with an explicit empty "code" as a
contract allocation (nonce 1), which an absent code field is not. Decoding
both into a nil Code erased that distinction and would change the genesis
state root. Record presence separately and decide the field's presence by
inspecting the decoded JSON object rather than substring-matching the raw
input.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Turn a shard's configured allocation into state trie leaves and its root
hash, splitting derivation from persistence the way geth's
hashAlloc/flushAlloc do: GenesisAllocRoot answers what the state root is,
CommitGenesisAlloc writes the nodes. Duplicate recipients are rejected
rather than silently last-one-wins, and an allocation that is blank in
pyquarkchain's terms produces no account at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…kchain

CreateMinorBlock and ShardChainConfig sit next to CreateRootBlock, mirroring
pyquarkchain's GenesisManager: GENESIS.ALLOC is materialized into the passed
database and the resulting state root is sealed into the block's meta, which
the header commits to. Passing an ephemeral database derives the block
without persisting it.

New validations: GENESIS.HEIGHT must be 0, a ROOT_HEIGHT > 0 shard is
refused rather than stood on the wrong root linkage, and every ALLOC address
must belong to the shard being created.

ShardChainConfig is the EVM rule set a shard runs — Petersburg-only, with
the chain id derived as BASE_ETH_CHAIN_ID + CHAIN_ID + 1 and a configured
ETH_CHAIN_ID accepted only when consistent with it. It is kept out of the
genesis block on purpose, as geth keeps its rule set out of the genesis
identity.

Pinned against pyquarkchain at three levels (state root, meta hash, block
hash) for both singularity networks; regeneration recipe in
qkc/config/singularity/README.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant