Skip to content

feat(network): MVP v2 -- tri-net's receipt, admission and verifier economics, with our quorum, replay and key-id rules - #8685

Merged
gHashTag merged 1 commit into
masterfrom
feat/network-mvp-v2-8648
Oct 10, 2026
Merged

gHashTag merged 1 commit into
masterfrom
feat/network-mvp-v2-8648

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

Closes #8648

Part of the network MVP epic (see #8613); v1 is specs/network/mvp.t27 (see #8610) and is unchanged. specs/network/mvp_v2.t27 uses v1's draws and helpers through use network::mvp and replaces its receipt, admission, settlement and accounts.

Taken from gHashTag/tri-net (at d6deeb39)

t27 cannot use another repository, so these are restated in section 1 under tri-net's own names:

  • tri_compute_receipt.t27: digest_pre, a one-block SHA-256 preimage [TAG "TRCP" 0x54524350, request_id, device_id, executor, task, in_hash, out, epoch, prev_head, pad]. Also merkle_pair_pre (the verifier signs one root over a job's receipts) and ledger_entry_pre ("TRLG": the ledger head commits every credit, slash, finalize and clawback). SHA-256 is tri/crypto/sha256.t27 compress, checked against the FIPS "abc" vector.
  • tri_receipt_verify.t27: a claim is accepted iff its signature checks, it is in the batch and its result recomputes, judged in that order (RV_BAD_SIG 1, RV_NOT_IN_BATCH 2, RV_BAD_COMPUTE 3).
  • tri_compute_challenge.t27:
    • a dissenter loses its stake;
    • verifier_reward = burned / honest_count, so the VERIFIER_FEE comes out of slashed stake, never the pool; floor division leaves the dust unminted;
    • a challenge upheld gives the executor's bond to the challenger (the watcher), and a frivolous challenger's stake is burned (challenger_stake_after).
  • tri_compute_account.t27:
    • every reward is pending until is_final (a window of CHALLENGE_WINDOW epochs);
    • may_finalize adds our gates: never while a challenge is open, never once slashed;
    • an upheld challenge claws the job's pending rewards back.

Our corrections, kept

  • Quorum 2M > N + F with M <= N - F (tri-bridge.t27 quorum_valid, quorum_met), N 4, F 1, M 3, not tri-net's n/2 + 1. The test walks N 1..9 and every F, and shows where n/2 + 1 is unsafe (for example N 3, F 1).
  • Replay is the spent (node, nonce) set of specs/trinet/ledger.t27 settle(), plus the durable nonce mark of node-work-credit.t27 (may_issue, next_mark, resume_nonce), not a task-id high-water mark. The test shows a high-water mark refusing honest work settled out of order. A dispatcher restart resumes at the mark, and the observer checks that no nonce is issued twice.
  • 64-bit key ids (KEY_ID_HEX_LEN 16) and the die's 64-bit FUSE_DNA as the device id, so digest_pre's device_id and executor are two words each (44 bytes, still one block):
  • The treasurer settles every authenticated claim through specs/trinet/ledger.t27 settle(), the real ledger's rule: eligibility, identity, verdict, once per (node, nonce), and the slash amount. NOT_IN_BATCH with a committed leaf is told to the ledger as a nonce mismatch (a replay) or a wrong result (an equivocation). A claim no key vouches for never reaches the ledger.
  • Payout kinds stay payout.t27's: BOUNTY, EXECUTOR_FEE, PROVIDER_FEE, VERIFIER_FEE, AUTHOR_ROYALTY. All are non-transferable, minted only on the chain of record (one minter).

The network

Actors are pids (actors.t27): supervisor, dispatcher, executor and three verifiers, verifier, treasurer, watcher, griefer.

Faults drawn from the seed:

  • a lie;
  • an unsigned receipt;
  • an impostor under a colliding 32-bit id;
  • DNA_PORT as the device;
  • an equivocation;
  • a replayed receipt;
  • a crash, which the supervisor restarts;
  • collusion of the executor with two verifiers on a failing spec, which is beyond F and is caught by the watcher's challenge;
  • a dispatcher restart;
  • a double bill;
  • a frivolous or late challenge;
  • v1's off-chain and unreproduced claims.

The observer judges these after every step:

  • paid <= emitted + slashed;
  • the books balance (spendable + pending + locked + burned-unpaid + clawed = stakes + emitted);
  • fraud nets worse than honesty (every slashable fraud below zero, every honest signer at or above it);
  • no finalize while challenged, and none once slashed;
  • dust is never minted;
  • no nonce is issued or paid twice;
  • no claim is paid that failed admission;
  • no forged vote is counted;
  • the quorum is safe;
  • the ledger and the MVP agree (slashes, credits, spent keys).

The same seed gives the same ledger digest.

Trace for the Queen runtime (see #8642, #8652): trace_len(seed) and trace_row(seed, i) yield the seeded network's events in actor_events.t27's shape:

  • seq and kind (spawn, restart, exit, down, deliver, pair count);
  • from_pid and to_pid;
  • task_ref;
  • parent_pid and restart_count on spawn and restart;
  • reason_class on exit and down;
  • count on a pair count;
  • the message tag, never a payload.

For seed 1 the test finds a signer's crash and its restart as the next generation, the liar's slash (M_SLASH to the liar's pid), the replayed nonce (the executor's credited claim presented again and refused by the spent set) and a replayed receipt.

Verdicts (t27c lab, master c266397)

  • t27c test-report specs/network/mvp_v2.t27: 12 of 12 pass, 3 invariants, 0 vacuous; 5907 runtime asserts. Per test: 179, 31, 194, 50, 3045, 462, 383, 109, 348, 17, 21, 1068.

  • t27b corpus specs/network (qemu aarch64, --blockers --reference t27c --timeout-ms 60000): mvp_v2.t27 reference pass, t27b pass, 5922 runtime asserts, 0 disagreements, 0 JIT/interpreter mismatches. mvp.t27 still passes with 1103 asserts. t27b test takes 7.7 s under qemu.

  • Seeds: the network tests use run_seed(GATE_BASE_SEED, i), 12 jobs each:

    • all 8 seeds for the invariant sweep;
    • 4 seeds twice for the digest;
    • 3 seeds each for the focused tests;
    • seed 1 for the trace.
  • Digests: the network compares digests only for equality, so a fast mix32 fold of the same preimages gives the same run. the_digest_does_not_steer_the_network runs SHA-256 throughout and checks the same books and the same event trace. The many-seed tests run fast so the interpreter cross-check finishes inside check_budget FILE_FUEL and the asserts are counted (with SHA-256 throughout they were "unknown").

  • Mutants: 15 seeded mutants of the wiring. 14 fail at least one test:

    • finalize ignores the open or the slashed gate;
    • verifier reward not floored;
    • 32-bit key ids for votes or claims;
    • batch ignored;
    • no durable mark;
    • no clawback;
    • challenger bond doubled;
    • share over the burned stake;
    • frivolous stake kept;
    • watcher never files;
    • DNA_PORT accepted;
    • admission order swapped.

    The survivor, n/2 + 1 in place of 2M > N + F inside the network, is equivalent at N 4, F 1 (both give 3), which is why the quorum test walks N 1..9.

  • t27c seal --verify: all hashes MATCH.

Ledger notes (see #8658, not changed here)

  • A double bill gets ledger.t27's OUT_REJECTED_AND_SLASHED with a zero slash in every case (1 to 5 per seed). It is refused and never paid, but it nets zero, not below zero. The fraud invariant therefore covers slashable frauds, and the double bill is judged by "never paid twice".
  • The damaged-identity defect cannot trip here: claims that fail the signature check never reach settle().
  • Observation: settle() judges a lie before the spent set, so a lying receipt presented twice would be slashed twice. The MVP never re-presents a lie, so this does not show up here.

0 hand-written lines outside .t27. The other files are the seal and one ledger row, written with t27b.dump_ledger on the lab. max_not_pass is unchanged.

🤖 Generated with Claude Code

…onomics, with our quorum, replay and key-id rules

specs/network/mvp_v2.t27: the network MVP evolved, v1 unchanged.
- Receipt envelope in tri-net digest_pre order and tag "TRCP", one SHA-256
  block; device_id and executor are 64-bit (two words each). device_id 0 is
  SOFTWARE_SIGNED, a die is its 64-bit FUSE_DNA, never DNA_PORT.
- Admission in tri_receipt_verify order and codes: BAD_SIG, NOT_IN_BATCH,
  BAD_COMPUTE. The batch is a signed Merkle root (merkle_pair_pre).
- VERIFIER_FEE = burned / honest_count out of slashed stake, dust unminted;
  the watcher that upholds a challenge gets the executor's bond.
- Credits pending until the challenge window passes; never final while
  challenged; a slashed job is clawed back and never finalizes.
- Quorum 2M > N + F (tri-bridge), spent (node, nonce) set with a durable
  mark (ledger.t27, node-work-credit.t27), 64-bit key ids.
- The treasurer settles through specs/trinet/ledger.t27 settle().
- trace_len / trace_row: the seeded network in actor_events.t27's shape.

Closes #8648

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag enabled auto-merge (squash) October 10, 2026 15:43
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-10 15:45:16 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 49
PRs with All Checks Green 1
READY 0
FAILING 49
PENDING 0
NO CHECKS YET 0

These columns do not partition: 0 + 49 + 0 + 0 = 49, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=465abf513dc2 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag merged commit 6a7b774 into master Oct 10, 2026
27 of 31 checks passed
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.

network MVP v2: tri-net's receipt envelope and verifier economics, with our quorum and nonce rules

2 participants