mirror of
https://github.com/luxfi/dex.git
synced 2026-09-24 00:26:31 +00:00
Height 0 was built by calling the block composition with the creation
document's digest in the slot that means "parent" everywhere else. The slot
was unused, so the convention held — and nothing enforced it. When the custody
ledger entered ComposeRoot in v1.14.0 every chain's genesis moved with it,
silently, because genesis was downstream of a composition that has nothing to
do with chain identity.
Genesis now has its own domain-separated construction and no longer touches
the block root:
GenesisDigest = keccak256("dex/genesis/v1" | init.Genesis)
GenesisRoot = keccak256("dex/genesis-root/v1" | digest | book | trade | tx | ledger)
BlockRoot = keccak256("dex/block-root/v1" | parent | book | trade | tx | ledger | height)
Different creation document -> different digest -> different genesis root ->
different root at every descendant height. That is now structural rather than
a property of a field that happens to be free.
GenesisDigest is defined for every input including none, so a running chain
always has one; whether a chain may run without a creation document is a
policy question and stays where it was answered.
The vectors verify the derivation against the written construction, using a
separate keccak and the empty sub-roots read from pinned hex, so they do not
drift by being updated to match. They also hold the three fleet documents to
their on-chain sha256, and pin the genesis against a VM carrying arbitrary
runtime state: same bytes in, same chain out, whatever the binary is doing.
Perturbing the block root now leaves every fleet genesis unmoved; routing
genesis back through the block composition fails the vector.
Co-authored-by: Hanzo Dev <[email protected]>