Consensus simulator
LatticeSim is the deterministic simulator harness for the implemented
Hierarchical-GHOST fork-choice path in docs/consensus-fork-choice.md.
Run it from a clean checkout:
swift run LatticeSim --seed 42The output is sorted JSON. The same seed must produce the same trace byte-for-byte. The three default scenarios pin the chain-local edges in the current library:
- equal subtree work chooses by canonical same-chain child block CID bytes only;
- a seeded withhold/release schedule converges to the heavier GHOST subtree;
- the 1h absolute schedule uses
ChainSpec.calculateAsertTargetfrom a height-1 anchor, on time and running slow.
For custom fixtures, LatticeConsensusSimulator.runDiscreteEventScenario(_:)
accepts a ConsensusSimScenarioSpec with block topology, release times
(atMillis), and per-block work weights. The harness turns those inputs into
BlockMeta fixtures and still evaluates them through ChainState.
The simulator does not implement a second fork-choice rule. It constructs
BlockMeta fixtures and records ChainState.forkChoiceSnapshot(startingAt:),
which wraps the library’s real same-chain GHOST decision. Cross-chain proof and
contribution derivation are tested at import rather than simulated by a live
parent-weight provider.
Adversarial model
Section titled “Adversarial model”The same run regenerates the checked-in adversarial report
(docs/consensus/adversarial-report.md and its .json), and
ConsensusSimulatorTests fails if the committed files differ from what the
seed produces. Every scenario drives the real chain-local ChainState fork
choice: greatest true cumulative work first, then the smaller canonical CID of
the competing child blocks. Parent canonicity and sibling state are not inputs.
With seed 42 it establishes three results, as a function of the attacker’s
share f of this chain’s root-grind contributions:
- Deep reorganization. Racing a 24-block honest segment over 200 seeded
trials, the attacker’s reorganization probability is 0% up to
f= 30%, 0.5% at 33%, 7% at 40%, 41.5% at 50%, and 89% at 60%. Deep reorganizations become likely only asfapproaches and exceeds a majority. - Selfish mining. Driving the matched-tie race through the real fork
choice measures a tie-break advantage of γ = 1/2: with equal targets and
independent hashes, either miner’s block wins half the ties. At that γ the
Eyal–Sirer revenue share equals
fat exactlyf= 1/4. Above it selfish mining is profitable. - Balancing. Sustaining two equal-work branches requires winning every
re-balancing race, so full-horizon survival scales as
f^horizon. Over a 64-round horizon no testedfsurvives. This is a cost curve, not a separate threshold.
The deterministic tie-break therefore costs no weight, since any strictly heavier branch still wins, but it sets the selfish-mining threshold at 1/4. Security-budget analysis must price the lower, economic threshold rather than the majority point, and must state which attack it prices.
Source: Lattice/docs/consensus-simulator.md at 54.2.1