From 796a67eb523bbc742d77797334bf395b6c0601d2 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Tue, 6 Oct 2026 11:51:19 +0000 Subject: [PATCH] proving v2: the harness gains --v2 (case 5: both proof systems and the switch; version 3 and version 2 records refused before, paid from it, an SP1 fresh chain after a system 2 segment), the fast-time file carries the switch; bench/proof-systems: the proof-system watch (run.sh one row per candidate, table.mjs, README) Co-Authored-By: Claude Fable 5.1 --- bench/proof-systems/README.md | 31 ++++++++++++++ bench/proof-systems/run.sh | 55 ++++++++++++++++++++++++ bench/proof-systems/table.mjs | 13 ++++++ infra/fast-time/override-60x.json | 1 + tools/proving-v1/net.mjs | 69 ++++++++++++++++++++++++++++--- 5 files changed, 164 insertions(+), 5 deletions(-) create mode 100644 bench/proof-systems/README.md create mode 100755 bench/proof-systems/run.sh create mode 100644 bench/proof-systems/table.mjs diff --git a/bench/proof-systems/README.md b/bench/proof-systems/README.md new file mode 100644 index 000000000..b51d66029 --- /dev/null +++ b/bench/proof-systems/README.md @@ -0,0 +1,31 @@ +# Proof-system watch + +One fixed shard, every candidate, one row each. The row says what a 12 GB card and a phone verifier would +see; the quarterly run says what moved. + +## The fixed shard + +`proving/fixtures/fees-v1-shards2.json`, shard 0 (the adopted shard size, `S_p`; 2 shards in the block) and +`proving/fixtures/block-338-shard1.json`, shard 0 (an empty shard). The statement is +`igneum_prove_core::shard::shard_statement`; every candidate commits the same `ShardOutput` bytes. + +## The candidates and how each is run + +| Candidate | Binary | How | Recursion | Audit | +|---|---|---|---|---| +| SP1 stock 6.8.1 (Hypercube: SP1 6.x is the Hypercube prover, docs/analysis/proving-methods.md 1.1) | `proving/igneum-prove/target/release/igneum-prove-host` | `--mode compressed --shard 0`, `SP1_PROVER=cpu` on the Mac, `cuda` on PC 2 | yes (compressed, aggregator guest) | yes (KALOS, Cantina, Zellic, Veridise; docs/plans/funding.md 2a) | +| SP1 patched server (the prover-floor agent's v3/v4 build) | the same host, `~/.sp1/bin/sp1-gpu-server` replaced | PC 2 only (`HOME=/opt/igneum-floor/home`); n/a on the Mac (no CUDA) | yes | the server fork is not audited; the guest and verifier are the stock ones | +| SP1 Hypercube separate release | n/a | the stock row is the Hypercube prover; no separate release exists to run | | | +| RISC Zero (proof system 2) | `proving/igneum-prove-r0/target/release/igneum-prove-r0-host` | `--mode compressed --shard 0`, Metal on the Mac, CUDA on PC 2 | yes (succinct receipt; composition for an aggregator) | yes (Veridise, Hexens; funding.md 2a) | +| Jolt | n/a | no guest for our shard, no shipped recursion, no Metal release used here (proving-methods.md route F): n/a until a guest is written | no | no | + +## The row + +`rows/--.json`: `candidate, machine, backend (cpu|cuda|metal), fixture, shard, cycles, +wall_s, prove_s, peak_memory_mib (max RSS on the Mac; nvidia-smi memory.used on a CUDA box), proof_bytes, +verify_s (one core), recursion, audit, verified (by the pinned verifier), command, source`. `node table.mjs` +renders every row into the table below. A cell that was not measured says `n/a` and why. + +## Latest table + +(rendered by `node bench/proof-systems/table.mjs > bench/proof-systems/TABLE.md`) diff --git a/bench/proof-systems/run.sh b/bench/proof-systems/run.sh new file mode 100755 index 000000000..28e68ba51 --- /dev/null +++ b/bench/proof-systems/run.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# The proof-system watch, one machine: proves the fixed shard on every candidate that runs here and writes one row +# each to rows/. Usage: bench/proof-systems/run.sh [--candidates sp1,r0] [--backend cpu|cuda|metal] [--fixture ] [--shard N] +# Run it through the measure lock on the Mac (tools/lock/with-lock.sh measure); on a CUDA box set --backend cuda. +set -uo pipefail +HERE="$(cd "$(dirname "$0")" && pwd)"; ROOT="$(cd "$HERE/../.." && pwd)" +CANDS="sp1,r0"; BACKEND=""; FIXTURE="$ROOT/proving/fixtures/fees-v1-shards2.json"; SHARD=0 +while [ $# -gt 0 ]; do case "$1" in --candidates) CANDS="$2"; shift 2;; --backend) BACKEND="$2"; shift 2;; --fixture) FIXTURE="$2"; shift 2;; --shard) SHARD="$2"; shift 2;; *) echo "unknown $1"; exit 2;; esac; done +MACHINE="$(hostname -s)"; DATE="$(date -u +%Y%m%d-%H%M)"; OUT="$HERE/rows"; mkdir -p "$OUT" +if [ -z "$BACKEND" ]; then if command -v nvidia-smi >/dev/null 2>&1; then BACKEND=cuda; elif [ "$(uname)" = Darwin ]; then BACKEND=metal; else BACKEND=cpu; fi; fi +SP1_HOST="$ROOT/proving/igneum-prove/target/release/igneum-prove-host" +R0_HOST="$ROOT/proving/igneum-prove-r0/target/release/igneum-prove-r0-host" +peak_mib() { # $1 = time log; the Mac's /usr/bin/time -l prints "maximum resident set size" in bytes, Linux's in KB + if [ "$(uname)" = Darwin ]; then awk '/maximum resident set size/ {printf "%d", $1/1048576}' "$1"; else awk '/Maximum resident set size/ {printf "%d", $NF/1024}' "$1"; fi; } +row() { # candidate backend host mode-env verify-mode + local cand="$1" backend="$2" host="$3" env="$4"; local name="$cand" + local dir; dir="$(mktemp -d)"; local res="$dir/results.json"; local tlog="$dir/time.log"; local plog="$dir/prove.log" + if [ ! -x "$host" ]; then printf '{"candidate":"%s","machine":"%s","backend":"%s","fixture":"%s","shard":%s,"na":"host not built: %s","date":"%s"}\n' "$cand" "$MACHINE" "$backend" "$(basename "$FIXTURE")" "$SHARD" "$host" "$DATE" > "$OUT/$DATE-$MACHINE-$cand.json"; echo "row $cand: n/a (no host)"; return; fi + local smi=""; if [ "$backend" = cuda ]; then nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits -l 1 > "$dir/smi.csv" 2>/dev/null & smi=$!; fi + local t0; t0=$(date +%s.%N) + env $env /usr/bin/time -l "$host" "$FIXTURE" --mode compressed --shard "$SHARD" --prover 0xCAfc6e74000000000000000000000000000000c2 --out "$res" > "$plog" 2> "$tlog" + local rc=$?; local wall; wall=$(python3 -c "import time; print(round(time.time() - $t0, 2))") + [ -n "$smi" ] && { kill $smi 2>/dev/null; sleep 1; } + local peak; if [ "$backend" = cuda ] && [ -s "$dir/smi.csv" ]; then peak=$(sort -n "$dir/smi.csv" | tail -1); else peak=$(peak_mib "$tlog"); fi + if [ $rc -ne 0 ] || [ ! -f "$res" ]; then printf '{"candidate":"%s","machine":"%s","backend":"%s","fixture":"%s","shard":%s,"na":"the prove run failed (exit %s): %s","date":"%s"}\n' "$cand" "$MACHINE" "$backend" "$(basename "$FIXTURE")" "$SHARD" "$rc" "$(grep -E 'RESULT|rror' "$plog" "$tlog" | tail -1 | tr -d '"' | cut -c1-200)" "$DATE" > "$OUT/$DATE-$MACHINE-$cand.json"; echo "row $cand: failed"; return; fi + # the verify on one core, three runs + local stmt pf; stmt=$(python3 -c "import json; print(json.load(open('$res'))['statement'])"); pf=$(python3 -c "import json; print(json.load(open('$res'))['proof_file'])") + local vs=""; for i in 1 2 3; do local v0; v0=$(date +%s.%N); env $env "$host" --mode verify --proof "$pf" --statement "$stmt" > "$dir/verify-$i.log" 2>&1; local vrc=$?; vs="$vs$(python3 -c "import time; print(round(time.time() - $v0, 3))"),"; [ $vrc -ne 0 ] && { echo "row $cand: VERIFY FAILED"; break; }; done + python3 - "$res" "$cand" "$MACHINE" "$backend" "$FIXTURE" "$SHARD" "$wall" "$peak" "${vs%,}" "$vrc" "$DATE" "$env" "$OUT" <<'PY' +import json, sys +res, cand, machine, backend, fixture, shard, wall, peak, vs, vrc, date, env, out = sys.argv[1:] +r = json.load(open(res)) +vl = [float(x) for x in vs.split(',') if x] +row = { + 'candidate': cand, 'machine': machine, 'backend': backend, 'fixture': fixture.split('/')[-1], 'shard': int(shard), 'date': date, + 'cycles': r.get('cycles'), 'wall_s': float(wall), 'prove_s': r.get('compressed_prove_seconds'), 'peak_memory_mib': int(peak) if str(peak).isdigit() else None, + 'proof_bytes': r.get('compressed_proof_bytes'), 'verify_s': min(vl) if vl else None, 'verify_runs': vl, 'verified': vrc == '0' and bool(vl), + 'recursion': cand in ('sp1', 'sp1-patched', 'r0'), 'audit': cand in ('sp1', 'r0'), 'proof_system': r.get('proof_system', 1), 'image_or_program_id': r.get('image_id') or r.get('program_id'), + 'command': f"{env} {sys.argv[0]} {fixture} --mode compressed --shard {shard}", 'source': 'bench/proof-systems/run.sh', +} +json.dump(row, open(f"{out}/{date}-{machine}-{cand}.json", 'w'), indent=1) +print(f"row {cand}: prove {row['prove_s']} s, wall {row['wall_s']} s, peak {row['peak_memory_mib']} MiB, proof {row['proof_bytes']} B, verify {row['verify_s']} s, verified {row['verified']}") +PY + rm -rf "$dir" +} +for c in ${CANDS//,/ }; do + case "$c" in + sp1) if [ "$BACKEND" = cuda ]; then row sp1 cuda "$SP1_HOST" "SP1_PROVER=cuda RUST_LOG=off"; else row sp1 cpu "$SP1_HOST" "SP1_PROVER=cpu RUST_LOG=off"; fi ;; + sp1-patched) if [ "$BACKEND" = cuda ] && [ -d /opt/igneum-floor/home ]; then row sp1-patched cuda "$SP1_HOST" "HOME=/opt/igneum-floor/home SP1_PROVER=cuda RUST_LOG=off"; else printf '{"candidate":"sp1-patched","machine":"%s","backend":"%s","na":"the patched server exists only on PC 2 (/opt/igneum-floor/home)","date":"%s"}\n' "$MACHINE" "$BACKEND" "$DATE" > "$OUT/$DATE-$MACHINE-sp1-patched.json"; echo "row sp1-patched: n/a"; fi ;; + r0) if [ "$BACKEND" = cuda ]; then row r0 cuda "$R0_HOST" "RISC0_PROVER=local RUST_LOG=off"; elif [ "$BACKEND" = metal ]; then row r0 metal "$R0_HOST" "RISC0_PROVER=local RUST_LOG=off"; else row r0 cpu "$R0_HOST" "RISC0_PROVER=local RUST_LOG=off"; fi ;; + jolt) printf '{"candidate":"jolt","machine":"%s","backend":"%s","na":"no guest for our shard statement and no shipped recursion (proving-methods.md route F)","date":"%s"}\n' "$MACHINE" "$BACKEND" "$DATE" > "$OUT/$DATE-$MACHINE-jolt.json"; echo "row jolt: n/a" ;; + *) echo "unknown candidate $c" ;; + esac +done +echo "rows in $OUT" diff --git a/bench/proof-systems/table.mjs b/bench/proof-systems/table.mjs new file mode 100644 index 000000000..965a3d8aa --- /dev/null +++ b/bench/proof-systems/table.mjs @@ -0,0 +1,13 @@ +// Renders every row in rows/ into one markdown table (the latest row per candidate and machine first). +import { readdirSync, readFileSync } from 'node:fs'; +const dir = new URL('./rows/', import.meta.url).pathname; +const rows = readdirSync(dir).filter(f => f.endsWith('.json')).map(f => ({ file: f, ...JSON.parse(readFileSync(dir + f, 'utf8')) })).sort((a, b) => (b.date || '').localeCompare(a.date || '')); +const latest = new Map(); +for (const r of rows) { const k = `${r.candidate}@${r.machine}@${r.backend}`; if (!latest.has(k)) latest.set(k, r); } +const fmt = (v, d = 1) => v === null || v === undefined ? 'n/a' : typeof v === 'number' ? v.toFixed(d) : String(v); +console.log('| Candidate | Machine, backend | Fixture | Cycles | Prove s | Wall s | Peak memory MiB | Proof bytes | Verify s (one core) | Recursion | Audit | Verified | Date |'); +console.log('|---|---|---|---|---|---|---|---|---|---|---|---|---|'); +for (const r of latest.values()) { + if (r.na) { console.log(`| ${r.candidate} | ${r.machine}, ${r.backend || 'n/a'} | n/a: ${r.na} | | | | | | | | | | ${r.date} |`); continue; } + console.log(`| ${r.candidate} | ${r.machine}, ${r.backend} | ${r.fixture} shard ${r.shard} | ${fmt(r.cycles, 0)} | ${fmt(r.prove_s)} | ${fmt(r.wall_s)} | ${fmt(r.peak_memory_mib, 0)} | ${fmt(r.proof_bytes, 0)} | ${fmt(r.verify_s, 3)} | ${r.recursion ? 'yes' : 'no'} | ${r.audit ? 'yes' : 'no'} | ${r.verified ? 'yes' : 'NO'} | ${r.date} |`); +} diff --git a/infra/fast-time/override-60x.json b/infra/fast-time/override-60x.json index 08f56e9ee..3aee760ba 100644 --- a/infra/fast-time/override-60x.json +++ b/infra/fast-time/override-60x.json @@ -59,6 +59,7 @@ "proving_v1_segment_blocks": 8, "proving_v1_unproven_daa": 10, "proving_v1_fresh_rule_daa": 0, + "proving_v2_activation_daa": 18446744073709551615, "proving_v1_aggregator_share_bps": 1000, "fees": {"pgas": {"version": 1, "cycles_per_pgas": 1000, "intrinsic_pgas_per_tx": 300, "modexp_base": 10, "modexp_per_byte_numer": 1, "modexp_per_byte_denom": 10}, "block_proving_gas_limit": 120000, "shard_proving_gas_budget": 30000, "min_execution_base_fee_wei": 100000000000, "min_proving_base_fee_wei": 10000000000000, "initial_execution_base_fee_wei": 100000000000, "initial_proving_base_fee_wei": 10000000000000, "base_fee_change_denominator": 8} } diff --git a/tools/proving-v1/net.mjs b/tools/proving-v1/net.mjs index df25458bb..7dc8e792e 100644 --- a/tools/proving-v1/net.mjs +++ b/tools/proving-v1/net.mjs @@ -41,6 +41,11 @@ const V0 = 60, V1 = flag('--v1', 120), SEG = flag('--segment', 4), UNPROVEN = fl // its known-failed line; with --fresh-rule 0 a fresh record after a PENDING segment is accepted (the new rule) and // case 2's refusal after a PROVEN one still stands const FRESH_RULE = process.argv.includes('--fresh-rule') ? Number(process.argv[process.argv.indexOf('--fresh-rule') + 1]) : null; +// --v2 : proof system 2's switch (6 October 2026). Every node gets fake RISC Zero ids (IGNEUM_PROOF_PROGRAM_IDS_V2) +// and trust for system 2; case 5 signs version 2 shard records and version 3 segment records: refused before the +// switch, paid from it (a fresh chain at the system change), and an SP1 record fresh again after a system 2 segment. +const V2 = process.argv.includes('--v2') ? Number(process.argv[process.argv.indexOf('--v2') + 1]) : null; +const V2_SHARD_ID = '0x' + '52'.repeat(32), V2_AGG_ID = '0x' + 'a7'.repeat(32); const started = []; const t0 = Date.now(); const since = () => ((Date.now() - t0) / 1000).toFixed(1); @@ -61,6 +66,7 @@ let overrideText = readFileSync(FILE, 'utf8') .replace(/"proving_v1_unproven_daa":\s*\d+/, `"proving_v1_unproven_daa": ${UNPROVEN}`) .replace(/"proving_v1_aggregator_share_bps":\s*\d+/, `"proving_v1_aggregator_share_bps": ${SHARE_BPS}`) .replace(/"proving_v1_fresh_rule_daa":\s*\d+/, FRESH_RULE === null ? '"proving_v1_fresh_rule_daa": 18446744073709551615' : `"proving_v1_fresh_rule_daa": ${FRESH_RULE}`) + .replace(/"proving_v2_activation_daa":\s*\d+/, V2 === null ? '"proving_v2_activation_daa": 18446744073709551615' : `"proving_v2_activation_daa": ${V2}`) .replace(/"skip_proof_of_work":\s*(true|false)/, '"skip_proof_of_work": true'); for (const re of [/"skip_proof_of_work": true/, new RegExp(`"proving_v1_activation_daa": ${V1}`), new RegExp(`"proving_v1_segment_blocks": ${SEG}`), new RegExp(`"proving_v1_unproven_daa": ${UNPROVEN}`)]) if (!re.test(overrideText)) throw new Error(`override edit failed: ${re}`); writeFileSync(override, overrideText); @@ -125,9 +131,9 @@ async function waitExecuted(n, number) { throw new Error(`block ${number} not executed in 300 s`); } // signs a segment record over the given public values with v0's key; the proof bytes are a placeholder (trust mode) -function signSegment(first, last, hash, pv, tag) { +function signSegment(first, last, hash, pv, tag, system = 1) { const proof = Buffer.from(`igneum-proving-v1-harness-${tag}-${first}-${last}`); - const sg = run(MINER, ['sign-segment-record', 'v0', CHAIN_NAME, String(first), String(last), hash, PAYOUT, pv, sha256(proof)]); + const sg = run(MINER, ['sign-segment-record', 'v0', CHAIN_NAME, String(first), String(last), hash, PAYOUT, pv, sha256(proof), ...(system >= 2 ? ['--system', String(system)] : [])]); if (sg.code !== 0) throw new Error(`sign-segment-record failed: ${sg.out}`); const signed = JSON.parse(sg.out.trim().split('\n').pop()); return { record: signed.record, proof: '0x' + proof.toString('hex'), keyHash: signed.keyHash, statement: signed.statement }; @@ -143,9 +149,10 @@ async function waitSegmentPaid(n, first, secs = 240) { } try { - const n0 = await new Node(0, [], { IGNEUM_PROOF_VERIFY: 'trust' }).start(); - const n1 = await new Node(1, [`127.0.0.1:${n0.p2pPort}`], { IGNEUM_PROOF_VERIFY: 'trust' }).start(); - const n2 = await new Node(2, [`127.0.0.1:${n0.p2pPort}`, `127.0.0.1:${n1.p2pPort}`], { IGNEUM_PROOF_VERIFY: 'trust' }).start(); + const nodeEnv = { IGNEUM_PROOF_VERIFY: 'trust', IGNEUM_PROOF_VERIFY_V2: 'trust', IGNEUM_PROOF_PROGRAM_IDS_V2: `${V2_SHARD_ID},${V2_AGG_ID}` }; + const n0 = await new Node(0, [], nodeEnv).start(); + const n1 = await new Node(1, [`127.0.0.1:${n0.p2pPort}`], nodeEnv).start(); + const n2 = await new Node(2, [`127.0.0.1:${n0.p2pPort}`, `127.0.0.1:${n1.p2pPort}`], nodeEnv).start(); const nodes = [n0, n1, n2]; log(`node 0 says: ${n0.grepLog(/proving v1/).join(' | ') || '(no proving v1 line)'}`); nodes.forEach((n, i) => miner(['vmine', n.grpc, String(SECS), '--label', `v${i}`, '--share', String(1 / 3), '--bps', '1', ...(i === 0 ? ['--evm-address', funded.address] : [])], `vmine-v${i}`)); @@ -250,6 +257,58 @@ try { check('a v1 shard is paid 90% of its block share (one shard a block here)', w && BigInt(w.shardWei) === BigInt(w.poolCreditWei) - BigInt(w.poolCreditWei) / 10n, w && { number: w.number, shardWei: w.shardWei, credit: w.poolCreditWei }); const before = work.find(x => hexn(x.number) < S); if (before) check('a pre-v1 shard keeps the whole share', BigInt(before.shardWei) === BigInt(before.poolCreditWei), { number: before.number }); + + // ---- case 5: proof system 2 (the slot), only with --v2 + if (V2 !== null) { + const st5 = await n0.eth('igneum_getProvingStatus'); + check('the node reports both proof systems and the v2 switch', st5.v1.proofSystems && st5.v1.proofSystems['2'].shardProgramId === V2_SHARD_ID && st5.v1.proofSystems['2'].aggregatorId === V2_AGG_ID && hexn(st5.v1.v2ActivationDaa) === V2, st5.v1.proofSystems); + const tipBefore = hexn(await n0.eth('eth_blockNumber')); + const segB = [S + Math.floor((tipBefore - SEG - S) / SEG) * SEG, 0]; segB[1] = segB[0] + SEG - 1; + const stmtB = await n0.eth('igneum_getSegmentStatement', ['0x' + segB[0].toString(16), 2]); + check('the statement for system 2 names the RISC Zero ids and says not admissible before the switch', stmtB.proofSystem === 2 && stmtB.shardProgramId === V2_SHARD_ID && stmtB.systemAdmissible === false, { proofSystem: stmtB.proofSystem, shardProgramId: stmtB.shardProgramId, admissible: stmtB.systemAdmissible }); + const lastHashB = stmtB.blocks[stmtB.blocks.length - 1].hash; + const early = signSegment(segB[0], segB[1], lastHashB, stmtB.publicValuesFresh, 'v2-early', 2); + const subEarly5 = await n0.eth('igneum_submitSegmentRecord', [{ record: early.record, proof: early.proof }]); + check('known-failed: a version 3 segment record is refused before the v2 switch', subEarly5.accepted === false && /not admissible before DAA/.test(subEarly5.reason), subEarly5); + // a version 2 shard record before the switch + const sh = await n0.eth('igneum_getShardStatement', ['0x' + segB[1].toString(16), 0, PAYOUT]); + const shardProof = Buffer.from(`igneum-proving-v2-harness-shard-${segB[1]}`); + const sr = run(MINER, ['sign-record', 'v0', CHAIN_NAME, sh.hash, String(segB[1]), '0', PAYOUT, sh.statement, sha256(shardProof), '--system', '2']); + const srj = JSON.parse(sr.out.trim().split('\n').pop()); + const subShardEarly = await n0.eth('igneum_submitProofRecord', [{ record: srj.record, proof: '0x' + shardProof.toString('hex') }]); + check('known-failed: a version 2 shard record is refused before the v2 switch', subShardEarly.accepted === false && /not admissible before DAA/.test(subShardEarly.reason), subShardEarly); + await waitDaa(n0, V2 + 1, 'past the v2 switch'); + // the newest executed segment now, a fresh chain under system 2 (its previous is pending: the fresh rule, or unproven) + const tipNow = hexn(await n0.eth('eth_blockNumber')); + const segY = [S + Math.floor((tipNow - SEG - S) / SEG) * SEG, 0]; segY[1] = segY[0] + SEG - 1; + const stmtY = await n0.eth('igneum_getSegmentStatement', ['0x' + segY[0].toString(16), 2]); + check('from the switch the statement for system 2 is admissible', stmtY.systemAdmissible === true && stmtY.status.status === 'pending', { admissible: stmtY.systemAdmissible, status: stmtY.status }); + const lastHashY = stmtY.blocks[stmtY.blocks.length - 1].hash; + const recY = signSegment(segY[0], segY[1], lastHashY, stmtY.publicValuesFresh, 'v2', 2); + const subY = await n1.eth('igneum_submitSegmentRecord', [{ record: recY.record, proof: recY.proof }]); + check('known-finished: a version 3 segment record is accepted from the switch', subY.accepted === true, subY); + const paidY = await waitSegmentPaid(n0, segY[0]); + check('the system 2 segment is paid with chain_len N', hexn(paidY.paid.chainLen) === SEG && paidY.carried.some(c => c.valid), paidY.paid); + const shY = await n0.eth('igneum_getShardStatement', ['0x' + segY[1].toString(16), 0, PAYOUT]); + const shardProofY = Buffer.from(`igneum-proving-v2-harness-shard-${segY[1]}`); + const srY = run(MINER, ['sign-record', 'v0', CHAIN_NAME, shY.hash, String(segY[1]), '0', PAYOUT, shY.statement, sha256(shardProofY), '--system', '2']); + const srYj = JSON.parse(srY.out.trim().split('\n').pop()); + const subShardY = await n0.eth('igneum_submitProofRecord', [{ record: srYj.record, proof: '0x' + shardProofY.toString('hex') }]); + check('a version 2 shard record is accepted from the switch', subShardY.accepted === true, subShardY); + // the next segment under SP1: fresh at the system change although the previous segment is proven + const segZ = [segY[0] + SEG, segY[1] + SEG]; + await waitDaa(n0, 0, 'now'); + let stmtZ; + for (let i = 0; i < 60; i++) { stmtZ = await n0.eth('igneum_getSegmentStatement', ['0x' + segZ[0].toString(16), 1]); if (stmtZ.executed) break; await sleep(1000); } + check('the SP1 statement after a system 2 segment names a different-system previous', stmtZ.executed && stmtZ.previous && stmtZ.previous.proofSystem === 2 && stmtZ.previous.sameSystem === false, stmtZ.previous); + const lastHashZ = stmtZ.blocks[stmtZ.blocks.length - 1].hash; + const recZ = signSegment(segZ[0], segZ[1], lastHashZ, stmtZ.publicValuesFresh, 'sp1-after-v2', 1); + const subZ = await n2.eth('igneum_submitSegmentRecord', [{ record: recZ.record, proof: recZ.proof }]); + check('an SP1 fresh-chain record is accepted after a proven system 2 segment (the chain restarts at the system change)', subZ.accepted === true, subZ); + const paidZ = await waitSegmentPaid(n0, segZ[0]); + check('the SP1 segment after the system change is paid with chain_len N', hexn(paidZ.paid.chainLen) === SEG, paidZ.paid); + step('case5', { v2: V2, before: segB, v2segment: segY, sp1after: segZ }); + } report.ok = report.checks.every(c => c.ok); log(`RESULT proving v1 harness: ${report.ok ? 'PASSED' : 'FAILED'} (${report.checks.length} checks) in ${since()} s`); } catch (e) {