V6-10: the repin note with every row read back (three deterministic builds, the id read-back on two boxes, the old and new fee mode compressed proofs VERIFIED under the new pair, the node equality replay, the RPC flag class)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-08 19:58:48 +00:00
parent 3d60a74498
commit 5144e87c18
2 changed files with 45 additions and 0 deletions

View file

@ -0,0 +1,44 @@
# V6-10: source, ELF and wire format pinned together (review B, 8 October 2026)
The finding: the ELF manifest was pinned_at 2026-10-05 while the fee split (D4) and the FixtureEnv flag changed the guest input; four matching hashes prove the files are the committed ones, not that the committed ELF was built from the current source and input layout. Closure asked: a deterministic rebuild and repin, a versioned guest input format, genuine compressed proofs with the new host under the old and the new fee modes, equality with the node's native state and receipt outputs, tests for fee rounding, aborts, duplicate payments and the succession window; activation never from a passing native test alone.
## 1. The versioned guest input format (in code, branch p22-stage-2, 7604fcf5d)
`ShardInput.format` and `AggInput.format` are the first field of every guest input. `GUEST_INPUT_FORMAT` is 3 (1: proving v0; 2: the D4 proving payment flag and the P22 stage 1 inputs commitment; 3: the stage 2 carried fixtures). `shard_statement` and `aggregate` call `check_input_format` before anything else, so a host and a guest built from different layouts refuse each other at the first field instead of proving garbage (before this, the mismatch read as "public values are 0 bytes, expected 392" from a guest that panicked on bincode: run76 on build-3, 20:44 UK, the stage 1 ELF fed a stage 2 input). Every host site stamps the format. `igneum-prove-pin` writes `source_commit` (IGNEUM_PIN_SOURCE_COMMIT or git HEAD) and `guest_input_format` into the manifest and carries the `prior` pair of a key succession over unless `--no-prior`.
## 2. The deterministic rebuild and repin (build-1, 20:35 to 20:5x UK)
| Build | Tree | Target dir | Shard ELF sha256 | Aggregator ELF sha256 |
|---|---|---|---|---|
| A | 75547f2a5 plus the uncommitted format tag (overlay) | target | 0ce9e351…b712f04 | 3ef25e3f…a29516 |
| B | the same, rebuilt into a clean target dir two minutes later | target-det | 0ce9e351…b712f04 | 3ef25e3f…a29516 |
| C | c45db4420, the committed tree, the elf output dir removed first (20:47 UK) | target | 0ce9e351…b712f04 | 3ef25e3f…a29516 |
The verifying keys matched byte for byte across A and B (program vk 0dbb6605…, aggregator vk 074eb906…). The pinned manifest is C's, with `source_commit` c45db4420 and `guest_input_format` 3. Program ids: shard 0x51cd8cba314a32b60fac393949a4571714da6d6656717d286011601b2a163fe7, aggregator 0x05b395ec238f67406084f8a449d400f64c87dc62151daebf66695864727ded8a, the same from A, B and C; the vks matched across all three. Committed as 7d38077df (the pin, its manifest and elf/prior). The prior pair carried in the manifest is the live pair 0x2b1a81cb… / 0x474678f3… (the 17:58 UK re-pin's current pair, 0x282dcfce… / 0x3fd721e8…, is superseded by this pin because stage 2 changed the public values again; the node lane places the new pair on the 2.0.2 tree after the D1 freeze).
## 3. Genuine compressed proofs with the new host, both fee modes
| Row | Fixture | Mode | Box | Result |
|---|---|---|---|---|
| old fee mode | fixtures/fees-v1-shards2.json (the whole charge burns) | compressed, shard 0 | build-3, CPU, 20:51 to 20:53 UK | VERIFIED: setup matches the manifest, execute 4,720,511 cycles, prove 111.1 s, proof 1,272,961 bytes, verify 0.035 s; statement 0xe1c82681b9891306d248d8a7b482aa5ade55f2f8d451b892dd6ed070bc091de1, proof sha256 0xa2bbabb10aff5084988fb822c059cf23f58fb627fca59aaef976898cf50b2135 (run86) |
| new fee mode | fixtures/d4-block-149-payment-on.json: block 149 of a fast-time chain mined by the D4 node 930b6322 with proving_payment_activation_daa 0 (build-8, 20:51 UK), cut by the exporter on build-2 | compressed, shard 0 | build-2, CPU, 20:56 to 20:58 UK | VERIFIED: setup matches the manifest, execute 175,044 cycles, prove 68.5 s, proof 1,272,961 bytes, verify 0.079 s; statement 0x51e5217007366c0264ab967d3c1bfb9a51c2def600e0b8b8d658adf38248e58f, proof sha256 0x76ed880959bcfcc52d1a7e0bbd7c5313a4aa05d18f65e321cee4620d5ddc0a1b (run88) |
A hand-flagged copy of fees-v1-shards2 with the flag on was tried first and withdrawn (c45db4420): its plan's shard roots were the old mode's, and a fixture whose expected values come from the host itself is not the node-equality row. The limit of the new-mode row, stated: block 149 carries no transactions (pgas 0), so the split moved no wei in state; the mode is on by the node's params (the daemon wires `proving_payment_activation_daa` into the exec service at start, `kaspad/src/daemon.rs`), and the split's arithmetic is covered by the host test of section 5 (90 percent of every executed transaction's charge to the pool escrow on fees-v1-shards2, 11 transactions). A row with transactions in the new mode needs a funded account on the fast-time chain and is owed with the D4 merge onto the 2.0.2 line. Found on the way (the class): the exec RPC read a segment's `provingPaymentToPool` as "some transaction paid", false on an empty block with the mode on, so a fixture cut from such a block ran the guest in the old mode; fixed on the node branch proving-payment-flag (the record carries the mode it was metered in, `ChainBlockRecord.proving_payment_to_pool`, serde default, the RPC falls back to the charges for records written before the field).
## 4. Equality with the node's native state and receipt outputs
`igneum-prove-export` replays every exported segment through `execute_block` and compares each state root with the node's `stateRoot`; a mismatch is fatal. The D4 node's export through the exporter is that row for the new fee mode: 149 segments replayed on build-2, every state root equal to the node's, final root 0x561134497bd3311a601040f06849f09ea9940de298b0487647a07b52cd93f61d (run87, 20:54 UK); the three fixtures cut from blocks 147 to 149 each read node_state_root equal to post_state_root. The old mode's equality is the existing fixtures' `node_state_root` (every fixture under proving/fixtures carries it and the native test asserts it).
## 5. Tests (host suite, green on build-2, run69, 20:39 UK)
| Case | Test |
|---|---|
| another input format refused before anything else, both guests; this format passes | `v6_10_another_guest_input_format_is_refused_before_anything_else` |
| fee rounding: pool plus burn equals the charge for 2,000 charges and the u128 edge, the odd wei to the burn, off burns all | `v6_10_the_proving_payment_rounds_its_odd_wei_to_the_burn_and_always_sums_to_the_charge` |
| duplicate payments: a second record for the same (block, shard), a paid-before record and an invalid record pay nothing inside the guest's derivation | `v6_10_a_duplicate_a_paid_before_and_an_invalid_carried_record_pay_nothing_inside_the_guest` |
| aborts: a reverting transaction's charge still divides (the executor's over-budget and revert branches both call `proving_payment_split`) | `the_proving_payment_flag_moves_90_percent_of_the_charge_to_the_pool` (existing) |
| the succession window | the node suite's `succession_*` tests and the fast-time case `--succession 240 --window 120` (docs/spec/proving-enforcement.md section 3a) |
## 6. Activation
The rebuilt host read back the pinned ids on build-2 and build-3 (`--mode id`, 20:49 UK: shard 0x51cd8cba…, aggregator 0x05b395ec…, pinned 2026-10-08T19:47:57Z on igneum-build-1), and the compressed prove on build-3 printed "setup matches the manifest" (SP1's key setup derived the manifest's program id) before proving. Never from a passing native test alone: the new pair activates as a key succession (`proving_key_succession_daa` with its window) on the line the shipper names, after the compressed proofs of section 3 verify under the embedded pair on a box (`--mode id` read back from the rebuilt host, then `--mode compressed` VERIFIED lines), and after the fast-time succession case passes on a node embedding this pair as next. A manifest timestamp alone is never read as a binary mismatch either way.

View file

@ -43,3 +43,4 @@ docs/design/app-audit-2026-10-08.md
docs/ledger-public-pre-2.0.md
# 8 October 2026: the Devnet 3 proving pipeline record (the fleet lane: box names, the operations record, the external review quoted)
docs/analysis/proving-pipeline-2026-10-08.md
docs/analysis/v6-10-guest-repin-2026-10-08.md