Cairn threat model

What this project defends, against whom, and what it knowingly leaves open, row by row against the code it ships.

How to read this

The first model was written on 30 August 2026, in French and outside the repository, against a commit three hundred and twenty eight commits older than this revision. On 25 September it was read again row by row against the code, and nineteen of its thirty seven rows turned out to be contradicted or qualified by what had been found since. A model a reader cannot reach and nobody keeps in step is the same kind of claim as a figure nothing holds, so this one lives beside the code and moves with it.

Each row names a threat, what stands in its way and where, the test that holds that, and what is left. What is left is written as the identifiers of the findings that show it, from the audit wave of 25 and 26 September 2026: NN-Fk is a defect, NN-Ik an improvement and NN-Qk a question. An empty residue means the mitigation holds as far as anybody has looked, which is not the same as holding. Every file this document names is checked to exist by crates/cairn-explorer/tests/site.rs, and every item named beside a file is checked to appear in it, so a row that points at code which has moved fails a test rather than standing.

1

What is defended

In order of how bad a failure would be.

AssetWhat stands in the wayHeld byLeft open
Money: no pebble created or destroyed outside the rulesthe coinbase cap and the running supply in the state root, crates/cairn-ledger/src/validation.rs, CoinbaseOverpay; crates/cairn-ledger/src/state.rs, supply_after; the ceiling, crates/cairn-primitives/src/amount.rs, MAX_MONEYcrates/cairn-ledger/tests/audit_emission.rs, crates/cairn-ledger/tests/audit_supply_and_overflow.rs
Funds: nothing spent without its key, nothing spent twicestrict verification, crates/cairn-crypto/src/lib.rs, verify_strict; keys outside the prime order subgroup refused, is_torsion_free; a cold note emptied in placecrates/cairn-crypto/tests/audit_the_verification_rule.rs, crates/cairn-crypto/tests/audit_a_key_nobody_holds.rs
Agreement: two honest nodes reach the same statecommit and revert through one replay, crates/cairn-ledger/src/state.rs, fn revert; the handover held field by field, crates/cairn-ledger/src/handover.rs, pub fn acceptcrates/cairn-ledger/tests/invariants.rs, crates/cairn-ledger/tests/handover.rs09-F1, 05-F1, 05-F2, 07-F1
Availability: no message anyone can send stops a nodea frame ceiling before any allocation, crates/cairn-net/src/wire.rs, MAX_FRAME_BYTES; a per-peer allowance, crates/cairn-net/src/sync.rs, ALLOWANCE; a connection ceiling, crates/cairn-net/src/node.rs, MAX_PEERScrates/cairn-net/tests/hostile_peer.rs, crates/cairn-net/tests/fuzz_wire.rs13-F1, 16-F1, 16-F2, 16-F3, 14-F1, 15-F1, 04-F1
A newcomer's start: nobody below the honest majority puts one on a false chainthe sampled weighing, crates/cairn-ledger/src/sampling.rs, pub const SAMPLES, the count taken from the age the tip claims against the reader's clock; a fresh draw priced by holding the tip to its run, crates/cairn-ledger/src/sampling.rs, pub const MOST_FALLcrates/cairn-ledger/tests/audit_the_bound.rs, crates/cairn-ledger/tests/the_price_of_a_seed.rs12-F1
Privacy: the software adds nothing to what the chain showsby decision the chain is public, amounts and owners included; what the software must not do is tell anyone more than that38-F1, 38-F2, 38-F3, 38-F4, 38-F5, 44-I7
The rules and their schedule: they change only as the source says, and visiblya rule changes at a height written into the build, crates/cairn-ledger/src/validation.rs, version_at; a node past its schedule says so and stops, crates/cairn-node/src/main.rs, rules_running_out; nobody votescrates/cairn-ledger/tests/audit_rule_change.rs, crates/cairn-chain/tests/audit_rule_change.rs05-F1, 05-F2, 44-I1

The 30 August model put privacy outside the model, as a property a public chain does not have. That was the wrong row. The chain is public by decision, and the open questions paper says what it shows; but a wallet that tells a peer which notes are its own, or a node that advertises the address of the phone it runs on, spends privacy the protocol never asked for. That is a failure of the software, and the model counts it as one.

It also said governance was none. There is no key, no vote and no authority, and that part holds. But whoever writes the build decides the rules and the height they change at, and the release is published by a workflow; that is a party, and it is in the table of actors below.

2

Who acts

ActorWhat it can doWhat stands in the wayLeft open
A usersign transfers of its own notesevery input signed over the network, the version, the identifier, the index and the note spent, crates/cairn-ledger/src/transaction.rs, fn message
A minerorder a block, date it within bounds, claim the reward and fees, fill its own block space for freethe retarget, the median of past times and the drift a reader allows, crates/cairn-ledger/src/validation.rs, max_timestamp_drift; the coinbase cap; the eviction cap, max_evictions_per_block04-F1, 04-F2, 44-F1
A majority minerrewrite recent history, censor, spend twice deepnothing: it is the assumption. A node will not undo past crates/cairn-chain/src/lib.rs, MAX_REORG_DEPTH, which is a local policy tied to the burial and the maturity
A miner with a third to a half of the workearn more than its share by withholding blocks, as on every Nakamoto chain; try to mislead a newcomer's startselfish mining is untreated, and the only lever taken is keeping the branch already followed at equal work; the start is bounded at the share the papers publish, measured and not proved06-F2, 44-I4
A hostile peersend malformed or costly messages, poison an address book, try to eclipse a nodethe frame ceiling and allowance above; a ceiling on connections from any one address, crates/cairn-net/src/node.rs, MAX_PER_HOST; a bounded share of the book per address group, crates/cairn-net/src/book.rs, MAX_PER_GROUP14-F1, 14-F2, 13-F1, 08-F1
An adversary on the pathread every message, delay or withhold blocks, eclipse a node without any Sybilnothing on the wire is private or bound to a peer; what it cannot do is forge, since every block needs work and every transfer a signature. Transport privacy is a decision not yet taken44-I3, 38-F3
An operatorcontrol a node's disk, its clock and its settingsa node replays its block log at start and validates it again rather than trusting its own disk; the clock is read for the drift a block may run ahead and nothing else05-F2, 11-F2, 21-F1, 25-F1
The maintainer and the releasedecide the rules and their heights; publish the binaries people runevery action pinned by hash; a provenance attestation, .github/workflows/release.yml, attestations; reproducible bytes; a schedule visible in the source months before its height. Nothing bounds what a schedule may change28-F1, 28-F2, 28-F3, 27-F2, 44-I1
An archivistserve paths for fallen notes; stay silent; watch who asks; vanishevery answer is folded against roots the asker's own node worked out, so it cannot lie; crates/cairn-net/src/message.rs, GetProofs. A wallet offline past its node's retention depends on one, which is the design's stated cost, and the archive's durability is not yet the software's37-F1, 38-F1, 38-F4, 20-F1, 44-I2
The seed operatorsee every first contact and every wallet session; hand a newcomer only addresses it choosesone name, crates/cairn-net/src/seeds.rs, seed.cairnchain.org; the sampling makes any chain it shows checkable, so the harm is eclipse and observation rather than a false chain38-F5, 14-Q3, 44-I6
Absent by designno validator set, no admin key, no checkpoint, no oracle, no bridgenone of them exists in the source, so none of them is a surface
3

What is assumed

AssumptionIf it is falseHeld byLeft open
Most of the work is honesthistory is rewritten, and a newcomer can be misledthe root assumption of proof of work; nothing holds it12-F1
Clocks are roughly righta node refuses valid blocks or takes future ones, a drift local to it while the median holdscrates/cairn-ledger/tests/retarget_timewarp.rs, crates/cairn-chain/tests/clock_skew.rs04-F1, 06-F1, 07-Q1
Each network's first block is written into the builda newcomer believes whichever first block a peer hands itcrates/cairn-ledger/src/validation.rs, for_network; crates/cairn-ledger/tests/network_rules.rs
The sampling bound holdsa forger below half the work puts a newcomer on its chaincrates/cairn-ledger/tests/audit_the_bound.rs06-F2, 12-F1
Undoing a block is the exact inverse of applying itafter a reorganisation a node's state root parts from the network's, with no attacker neededcrates/cairn-ledger/tests/invariants.rs, crates/cairn-chain/tests/audit_a_reorganisation_is_the_inverse.rs09-F1, 11-F1, 11-F2, 11-F3, 17-F1
A handed ledger is the ledger a node would have builta node started from one follows another chaincrates/cairn-ledger/tests/handover.rs, crates/cairn-ledger/tests/audit_forged_join.rs07-F1, 16-F3
The hot set never passes its capacitythe one bound the whole design rests on is not a boundcrates/cairn-ledger/src/state.rs, plan_evictions; crates/cairn-ledger/tests/tiers.rs44-F1
The operating system's randomness is there and goodkeys are guessable; there is no weaker fallback for a key, so a failure is an errorcrates/cairn-crypto/src/lib.rs, random_bytes
Arithmetic does not wrap in a release buildan unchecked sum wraps where a checked one refusesCargo.toml, overflow-checks = true, with unchecked arithmetic denied in every crate31-F3

3.1The three assumptions that would stop the project

The 30 August model named three of these as the ones whose failure ends the project rather than costs it something, because each one false is a disagreement between honest nodes. Where each stands now:

  1. The sampling bound. Then: a derivation of 512 samples, unreviewed and unmeasured. Now: 4 096 samples, the adversary's best placement measured, the count taken from the age a tip claims against a clock the reader holds, a tip held to the run below it so that a fresh draw costs work, and the whole stated as a conjecture rather than a theorem. It was broken once by this project and mended. Still open: 12-F1.
  2. Undo is the exact inverse of apply. Then: held by debug assertions on the length of the hot set, and nothing in a release build. Now: held by property tests over random sequences and forks, and by a test that undoes every block of a chain and compares roots. Still open: 09-F1, and 11-F1 to 11-F3 on the node-local structures around it.
  3. A handed ledger is exact. Then: held by the state root and the chain of recent headers. Now: held field by field, with every refusal named by a test, and tied to the chain that was weighed by the run of headers between the ledger and the tip. Still open: 07-F1 and 16-F3.

None of the three has the shape it had on 30 August, and none is closed.

4

Where it can be reached

SurfaceWhat stands in the wayHeld byLeft open
The peer protocolevery message capped at decode; an allowance per peercrates/cairn-net/tests/protocol.rs, crates/cairn-net/tests/fuzz.rs13-F1, 16-F1, 16-F2, 16-F3, 14-F1, 14-F2, 15-F1
The wallet's pageserved on the loopback, behind a secret drawn for the run, refusing another host or origin; it moves money, crates/cairn-wallet/src/serve.rs, /api/send; a body read only for a POST and capped, crates/cairn-http/src/http.rs, MAX_BODY_BYTEScrates/cairn-wallet/tests/page.rs, crates/cairn-http/tests/fuzz_request.rs22-F1, 24-F1, 24-F6
The explorerpublic by design, read only, bounded per requestcrates/cairn-explorer/tests/answers.rs25-F1, 26-F1
The poolbounded in count and in bytes, conflicts refused, a fee floor asked again when the state moves, crates/cairn-chain/src/lib.rs, MAX_POOL_BYTEScrates/cairn-chain/tests/pool.rs21-F3
A wallet as a nodea wallet joins the network as a node of its own, listening, crates/cairn-wallet/src/lib.rs, 0.0.0.0:0; every cost a greeted peer can impose lands on the device the design exists for38-F2, 16-F1, 13-F1, 14-F1, 44-I5
The sampled startnew, and the part of the design with no deployed precedent in this formcrates/cairn-ledger/tests/sampling.rs, crates/cairn-ledger/tests/audit_the_bound.rs06-F2, 12-F1
The two tiers and cold proofsnew; a proof is checked against the forest as it stands and nothing older, crates/cairn-accumulator/src/forest.rs, pub fn verify; a fallen note stays spendable without a proof for a window, crates/cairn-ledger/src/state.rs, GRACE_BLOCKScrates/cairn-ledger/tests/tiers.rs, crates/cairn-ledger/tests/cold_spends.rs44-F1, 21-Q2
Files read back from diskevery record framed and checked; the block log validated again at startcrates/cairn-store/tests/fuzz_record_framing.rs, crates/cairn-store/tests/block_log.rs17-F1, 18-F1
The installer and the unitsone script, deploy/install.sh, writes the units deploy/cairnd.service and deploy/cairn-explorer.service27-F1, 27-F2
Dependenciesthe crates a shipped program pulls in, few on purpose, checked against the advisory database every week, .github/workflows/audit.yml, cargo audit
Contracts, a virtual machine, a bridgenone exists
5

What makes this model unusual

There is no finality. A node will not undo more than MAX_REORG_DEPTH blocks, and that is its own policy, not a rule of the chain: two nodes with different limits part company only over a reorganisation deeper than one of them accepts.

The bound on what a node holds is itself a claim this model has to carry. If the state a validator holds is not bounded after all, the thesis falls without anyone losing money: it is a failure of the promise rather than of consensus. The papers state every term of it and a test computes each one.

And two mechanisms carry the security that have no deployed precedent in this form, the sampled start and the handover. That is where review is most worth spending, and where every row above that ends in an open finding points.