From 498beeea96fbcbdbf4035b505c687c448ffd6930 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Thu, 8 Oct 2026 21:51:52 +0000 Subject: [PATCH] Cache-history case: the verdict reads SP1 verifies (calls minus context refusals); a context refusal is a cheap pre-check, never cached, re-read at every carrier (read from the 22:34 UK run: paid once, the invalid bytes answered from the cache, the real proof verified once) Co-Authored-By: Claude Fable 5.1 --- infra/fast-time/proving-cache-history.mjs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/infra/fast-time/proving-cache-history.mjs b/infra/fast-time/proving-cache-history.mjs index 2934bd5d6..1a82e4a10 100644 --- a/infra/fast-time/proving-cache-history.mjs +++ b/infra/fast-time/proving-cache-history.mjs @@ -15,10 +15,10 @@ // node infra/fast-time/proving-cache-history.mjs --prove-bin // [--before 90] [--after 120] [--slot 0] [--out ] // -// Verdict: (1) block n shard 0 paid exactly once, to PAYOUT; (2) H1's verifies.run grew by exactly 2 over the run (the -// real proof once, the invalid bytes once) and verifies.cacheAnswers by at least 2; (3) the context refusal of phase 1 -// and the invalid refusal of phase 3 both read in H1's log; (4) the second use of the invalid bytes produced a refusal -// with no new verify. +// Verdict: (1) block n shard 0 paid exactly once, to PAYOUT; (2) H1 ran the SP1 verifier exactly twice over the run (the real +// proof once, the invalid bytes once): the context refusal of phase 1 is a pre-check (the statement differs) that runs no +// verifier and is never cached, re-read at every carrier; (3) the context refusal and the invalid refusal both read in H1's +// log; (4) the second use of the invalid bytes is answered from the cache with no new verify (cacheAnswers at least 1). import { spawn, spawnSync } from 'node:child_process'; import { mkdirSync, rmSync, writeFileSync, readFileSync, openSync, existsSync, appendFileSync } from 'node:fs'; import { createHash, randomBytes } from 'node:crypto'; @@ -136,7 +136,7 @@ async function rejoin(label) { for (let k = 0; k < 120; k++) { if (await sameTip(A, H1)) { log(`${label}: A is on H1's tip (${k * 5} s)`); return true; } await sleep(5000); } log(`${label}: A did not rejoin H1's tip in 600 s`); return false; } -async function verifies(node) { const s = await node.exec('igneum_getProvingStatus', []); return s.verifies || { run: 0, cacheAnswers: 0 }; } +async function verifies(node) { const s = await node.exec('igneum_getProvingStatus', []); return s.verifies || { calls: 0, sp1: 0, contextRefusals: 0, cacheAnswers: 0 }; } const refusals = (node) => (node.logText().match(/a carried proof record's proof does not verify: [^\n]*/g) || []); async function submitVia(node, name, record, proof) { let out; @@ -233,15 +233,16 @@ try { log(`phase 3: H1 verifies after 3a ${JSON.stringify(v3a)}, after 3b ${JSON.stringify(v3b)}; refusals ${ref3a} then ${ref3b}`); // the verdict const paidOnce = (o2.paid || []).length === 1 && (o1.paid || []).length === 0; - const runs = Number(v3b.run) - Number(v0.run); + const runs = Number(v3b.sp1) - Number(v0.sp1); // SP1 verifies: the real proof once (phase 2), the invalid bytes once (3a); the context refusal of phase 1 runs no verifier const cache = Number(v3b.cacheAnswers) - Number(v0.cacheAnswers); + const contextCheap = Number(v1.contextRefusals) - Number(v0.contextRefusals) >= 1 && Number(v1.sp1) === Number(v0.sp1); const contextRefused = result.phases.context.refusals.length >= 1; - const invalidRefusedTwiceNoVerify = ref3b > ref3a && Number(v3b.run) === Number(v3a.run); - const pass = paidOnce && runs === 2 && cache >= 2 && contextRefused && invalidRefusedTwiceNoVerify; - result.verdict = { paidOnce, verifiesRun: runs, cacheAnswers: cache, contextRefused, invalidRefusedTwiceNoVerify, pass }; + const invalidRefusedTwiceNoVerify = ref3b > ref3a && Number(v3b.sp1) === Number(v3a.sp1); + const pass = paidOnce && runs === 2 && cache >= 1 && contextRefused && contextCheap && invalidRefusedTwiceNoVerify; + result.verdict = { paidOnce, sp1Verifies: runs, cacheAnswers: cache, contextRefused, contextCheap, invalidRefusedTwiceNoVerify, pass }; result.endedAt = new Date().toISOString(); writeFileSync(OUT, JSON.stringify(result, null, 2)); - log(`RESULT ${pass ? 'PASS' : 'FAIL'}: paid once=${paidOnce}; SP1 verifies run=${runs} (expect 2); cache answers=${cache} (expect >= 2); context refusal read=${contextRefused}; invalid refused again without a verify=${invalidRefusedTwiceNoVerify}; ${OUT}`); + log(`RESULT ${pass ? 'PASS' : 'FAIL'}: paid once=${paidOnce}; SP1 verifies=${runs} (expect 2: the real proof once, the invalid bytes once); context refusal read=${contextRefused} and cheap (no verifier)=${contextCheap}; cache answers=${cache} (expect >= 1); invalid refused again without a verify=${invalidRefusedTwiceNoVerify}; ${OUT}`); await stopAll(); process.exit(pass ? 0 : 1); } catch (e) {