diff --git a/docs/plans/igneum-2.0-test-registry.json b/docs/plans/igneum-2.0-test-registry.json index 412ea511f..15afaaf43 100644 --- a/docs/plans/igneum-2.0-test-registry.json +++ b/docs/plans/igneum-2.0-test-registry.json @@ -3401,16 +3401,17 @@ "manual_page": 48, "owner_lane": "finality lane (aca0f5ed924a2a99b)", "run_status": "PASS", - "evidence_path": "sim/results_v2.md", - "run_id": "fin-boundary-20261008-02", - "updated": "2026-10-08T18:59:16.459Z", + "evidence_path": "sim/finality-attacks-results/v4-pause-fix.md", + "run_id": "fin-v4-realnode-20261008T2025Z", + "updated": "2026-10-08T19:43:19.697Z", "evidence_record": { - "cell": "harness:finality-sim-fin02", - "manifest_sha": "4b423dad8", + "cell": "node:finality-realnode", + "manifest_sha": "12424341", "coverage": { - "FIN-02": "the simulator half of the accept text; the real-node run on the fault network F4 with independent operators is node:finality-realnode" + "FIN-02": "partial: the real-node half; independent operators and the review remain", + "FIN-07": "partial: deterministic recovery after reconnection and crash on real nodes (the HEAL reruns)" }, - "at": "2026-10-08T18:59:16.459Z" + "at": "2026-10-08T19:43:19.697Z" } }, { @@ -3611,23 +3612,18 @@ "owner": "Consensus lead + independent formal/security review", "manual_page": 50, "owner_lane": "finality lane (aca0f5ed924a2a99b)", - "run_status": "RUNNING", - "evidence_path": "build-1:/srv/artefacts/tas/201-7cfa422a-aa0e0f45/node-7cfa422a/box4-consensus.log", - "run_id": "201-7cfa422a-aa0e0f45", - "updated": "2026-10-08T19:32:50.856Z", + "run_status": "PASS", + "evidence_path": "sim/finality-attacks-results/v4-pause-fix.md", + "run_id": "fin-v4-realnode-20261008T2025Z", + "updated": "2026-10-08T19:43:19.697Z", "evidence_record": { - "cell": "suite:consensus", - "manifest_sha": "7cfa422a", + "cell": "node:finality-realnode", + "manifest_sha": "12424341", "coverage": { - "FIN-01": "partial: the finality processes' agreement tests", - "FIN-03": "partial: rule v4's anchored table and authority expiry tests (bee41b5e)", - "FIN-04": "partial: the frozen table without its time expiry (rule v4)", - "FIN-05": "partial: key succession and another scheme's vote refused", - "FIN-07": "partial: majority-continuity recovery (rule v4)", - "ROT-05": "partial: the finality-stopped pause tests", - "ZKP-01": "partial: a proof-less or wrong-statement block refused by consensus" + "FIN-02": "partial: the real-node half; independent operators and the review remain", + "FIN-07": "partial: deterministic recovery after reconnection and crash on real nodes (the HEAL reruns)" }, - "at": "2026-10-08T19:32:50.856Z" + "at": "2026-10-08T19:43:19.697Z" } }, { @@ -3658,16 +3654,15 @@ "owner_lane": "fast-time lane (a8be71a0db962911c)", "run_status": "RUNNING", "evidence_path": "sim/results_v2.md", - "run_id": "fin-boundary-20261008", - "updated": "2026-10-08T18:38:45.233Z", + "run_id": "fin-v4-realnode-20261008T2025Z", + "updated": "2026-10-08T19:43:19.697Z", "evidence_record": { "cell": "harness:finality-sim", - "manifest_sha": "4b423dad8", + "manifest_sha": "12424341", "coverage": { - "FIN-02": "partial: split honest populations in the simulator; the real-node run is the fault network F4", - "FIN-08": "partial: the combined boundary and fault scenarios in the simulator; model checking is the formal review" + "FIN-08": "partial: the combined boundary and fault scenarios in the simulator with adversarial schedules; model checking is the formal review" }, - "at": "2026-10-08T18:38:45.233Z" + "at": "2026-10-08T19:43:19.697Z" } } ], @@ -5366,11 +5361,11 @@ "finding_priority": "P0 - public/value-bearing release blocker", "owner_lane": "proving lane, node lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F01 (P0, the external review): the regression's harness is the owner lane's (proving lane, node lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F01-2", @@ -5397,11 +5392,11 @@ "finding_priority": "P0 - public/value-bearing release blocker", "owner_lane": "proving lane, node lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F01 (P0, the external review): the regression's harness is the owner lane's (proving lane, node lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F01-3", @@ -5428,11 +5423,11 @@ "finding_priority": "P0 - public/value-bearing release blocker", "owner_lane": "proving lane, node lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F01 (P0, the external review): the regression's harness is the owner lane's (proving lane, node lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F01-4", @@ -5459,11 +5454,11 @@ "finding_priority": "P0 - public/value-bearing release blocker", "owner_lane": "proving lane, node lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F01 (P0, the external review): the regression's harness is the owner lane's (proving lane, node lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F02-1", @@ -5490,11 +5485,11 @@ "finding_priority": "P0 - release configuration blocker", "owner_lane": "proving lane, CI steward", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F02 (P0, the external review): the regression's harness is the owner lane's (proving lane, CI steward); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F02-2", @@ -5521,11 +5516,11 @@ "finding_priority": "P0 - release configuration blocker", "owner_lane": "proving lane, CI steward", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F02 (P0, the external review): the regression's harness is the owner lane's (proving lane, CI steward); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F02-3", @@ -5552,11 +5547,11 @@ "finding_priority": "P0 - release configuration blocker", "owner_lane": "proving lane, CI steward", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F02 (P0, the external review): the regression's harness is the owner lane's (proving lane, CI steward); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F03-1", @@ -5583,11 +5578,11 @@ "finding_priority": "P0 - freeze/integration blocker", "owner_lane": "CI steward, hash lane (ProgramClass::V6 on freeze), pool lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F03 (P0, the external review): the regression's harness is the owner lane's (CI steward, hash lane (ProgramClass::V6 on freeze), pool lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F03-2", @@ -5614,11 +5609,11 @@ "finding_priority": "P0 - freeze/integration blocker", "owner_lane": "CI steward, hash lane (ProgramClass::V6 on freeze), pool lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F03 (P0, the external review): the regression's harness is the owner lane's (CI steward, hash lane (ProgramClass::V6 on freeze), pool lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F03-3", @@ -5645,11 +5640,11 @@ "finding_priority": "P0 - freeze/integration blocker", "owner_lane": "CI steward, hash lane (ProgramClass::V6 on freeze), pool lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F03 (P0, the external review): the regression's harness is the owner lane's (CI steward, hash lane (ProgramClass::V6 on freeze), pool lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F04-1", @@ -5676,11 +5671,11 @@ "finding_priority": "P0 - finality guarantee decision", "owner_lane": "node lane, reference apps, site (explorer)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F04 (P0, the external review): the regression's harness is the owner lane's (node lane, reference apps, site (explorer)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F04-2", @@ -5707,11 +5702,11 @@ "finding_priority": "P0 - finality guarantee decision", "owner_lane": "node lane, reference apps, site (explorer)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F04 (P0, the external review): the regression's harness is the owner lane's (node lane, reference apps, site (explorer)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F04-3", @@ -5738,11 +5733,11 @@ "finding_priority": "P0 - finality guarantee decision", "owner_lane": "node lane, reference apps, site (explorer)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F04 (P0, the external review): the regression's harness is the owner lane's (node lane, reference apps, site (explorer)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F04-4", @@ -5769,11 +5764,11 @@ "finding_priority": "P0 - finality guarantee decision", "owner_lane": "node lane, reference apps, site (explorer)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F04 (P0, the external review): the regression's harness is the owner lane's (node lane, reference apps, site (explorer)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F05-1", @@ -5800,11 +5795,11 @@ "finding_priority": "P1 - adversarial hardware evaluation", "owner_lane": "hash lane, adversary lane, floor lane 3", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F05 (P1, the external review): the regression's harness is the owner lane's (hash lane, adversary lane, floor lane 3); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F05-2", @@ -5831,11 +5826,11 @@ "finding_priority": "P1 - adversarial hardware evaluation", "owner_lane": "hash lane, adversary lane, floor lane 3", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F05 (P1, the external review): the regression's harness is the owner lane's (hash lane, adversary lane, floor lane 3); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F05-3", @@ -5862,11 +5857,11 @@ "finding_priority": "P1 - adversarial hardware evaluation", "owner_lane": "hash lane, adversary lane, floor lane 3", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F05 (P1, the external review): the regression's harness is the owner lane's (hash lane, adversary lane, floor lane 3); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F06-1", @@ -5893,11 +5888,11 @@ "finding_priority": "P1 - freeze blocker", "owner_lane": "hash lane, research lane D", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F06 (P1, the external review): the regression's harness is the owner lane's (hash lane, research lane D); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F06-2", @@ -5924,11 +5919,11 @@ "finding_priority": "P1 - freeze blocker", "owner_lane": "hash lane, research lane D", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F06 (P1, the external review): the regression's harness is the owner lane's (hash lane, research lane D); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F06-3", @@ -5955,11 +5950,11 @@ "finding_priority": "P1 - freeze blocker", "owner_lane": "hash lane, research lane D", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F06 (P1, the external review): the regression's harness is the owner lane's (hash lane, research lane D); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F07-1", @@ -5986,11 +5981,11 @@ "finding_priority": "P1 - miner economics and reliability", "owner_lane": "app lane, fleet lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F07 (P1, the external review): the regression's harness is the owner lane's (app lane, fleet lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F07-2", @@ -6017,11 +6012,11 @@ "finding_priority": "P1 - miner economics and reliability", "owner_lane": "app lane, fleet lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F07 (P1, the external review): the regression's harness is the owner lane's (app lane, fleet lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F07-3", @@ -6048,11 +6043,11 @@ "finding_priority": "P1 - miner economics and reliability", "owner_lane": "app lane, fleet lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F07 (P1, the external review): the regression's harness is the owner lane's (app lane, fleet lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F08-1", @@ -6079,11 +6074,11 @@ "finding_priority": "P1 - proving product gate", "owner_lane": "proving lane, fleet lane, site (ops page)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F08 (P1, the external review): the regression's harness is the owner lane's (proving lane, fleet lane, site (ops page)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F08-2", @@ -6110,11 +6105,11 @@ "finding_priority": "P1 - proving product gate", "owner_lane": "proving lane, fleet lane, site (ops page)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F08 (P1, the external review): the regression's harness is the owner lane's (proving lane, fleet lane, site (ops page)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F08-3", @@ -6141,11 +6136,11 @@ "finding_priority": "P1 - proving product gate", "owner_lane": "proving lane, fleet lane, site (ops page)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F08 (P1, the external review): the regression's harness is the owner lane's (proving lane, fleet lane, site (ops page)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F09-1", @@ -6172,11 +6167,11 @@ "finding_priority": "P1 - founding claim not yet earned", "owner_lane": "research lane, floor lane 3, coordinator", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F09 (P1, the external review): the regression's harness is the owner lane's (research lane, floor lane 3, coordinator); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F09-2", @@ -6203,11 +6198,11 @@ "finding_priority": "P1 - founding claim not yet earned", "owner_lane": "research lane, floor lane 3, coordinator", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F09 (P1, the external review): the regression's harness is the owner lane's (research lane, floor lane 3, coordinator); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F09-3", @@ -6234,11 +6229,11 @@ "finding_priority": "P1 - founding claim not yet earned", "owner_lane": "research lane, floor lane 3, coordinator", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F09 (P1, the external review): the regression's harness is the owner lane's (research lane, floor lane 3, coordinator); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F10-1", @@ -6265,11 +6260,11 @@ "finding_priority": "P2 - byte-preserving performance experiment", "owner_lane": "worker lane (new)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F10 (P2, the external review): the regression's harness is the owner lane's (worker lane (new)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F10-2", @@ -6296,11 +6291,11 @@ "finding_priority": "P2 - byte-preserving performance experiment", "owner_lane": "worker lane (new)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F10 (P2, the external review): the regression's harness is the owner lane's (worker lane (new)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F10-3", @@ -6327,11 +6322,11 @@ "finding_priority": "P2 - byte-preserving performance experiment", "owner_lane": "worker lane (new)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F10 (P2, the external review): the regression's harness is the owner lane's (worker lane (new)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F11-1", @@ -6358,11 +6353,11 @@ "finding_priority": "P2 - product performance", "owner_lane": "Ember lane (new)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F11 (P2, the external review): the regression's harness is the owner lane's (Ember lane (new)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F11-2", @@ -6389,11 +6384,11 @@ "finding_priority": "P2 - product performance", "owner_lane": "Ember lane (new)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F11 (P2, the external review): the regression's harness is the owner lane's (Ember lane (new)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F11-3", @@ -6420,11 +6415,11 @@ "finding_priority": "P2 - product performance", "owner_lane": "Ember lane (new)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F11 (P2, the external review): the regression's harness is the owner lane's (Ember lane (new)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F12-1", @@ -6451,11 +6446,11 @@ "finding_priority": "P1 - payment integrity", "owner_lane": "pool lane (new)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F12 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F12-2", @@ -6482,11 +6477,11 @@ "finding_priority": "P1 - payment integrity", "owner_lane": "pool lane (new)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F12 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F12-3", @@ -6513,11 +6508,11 @@ "finding_priority": "P1 - payment integrity", "owner_lane": "pool lane (new)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F12 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F13-1", @@ -6544,11 +6539,11 @@ "finding_priority": "P1 - service resilience", "owner_lane": "pool lane (new)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F13 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F13-2", @@ -6575,11 +6570,11 @@ "finding_priority": "P1 - service resilience", "owner_lane": "pool lane (new)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F13 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F13-3", @@ -6606,11 +6601,11 @@ "finding_priority": "P1 - service resilience", "owner_lane": "pool lane (new)", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F13 (P1, the external review): the regression's harness is the owner lane's (pool lane (new)); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F14-1", @@ -6637,11 +6632,11 @@ "finding_priority": "P1 - public client/independence gate", "owner_lane": "app lane, relay lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F14-2", @@ -6668,11 +6663,11 @@ "finding_priority": "P1 - public client/independence gate", "owner_lane": "app lane, relay lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } }, { "id": "REV-F14-3", @@ -6699,11 +6694,11 @@ "finding_priority": "P1 - public client/independence gate", "owner_lane": "app lane, relay lane", "run_status": "NOT RUN", + "updated": "2026-10-08T19:32:50.856Z", "evidence_record": { "reason": "F14 (P1, the external review): the regression's harness is the owner lane's (app lane, relay lane); not yet named in the map", "at": "2026-10-08T19:32:50.856Z" - }, - "updated": "2026-10-08T19:32:50.856Z" + } } ] } diff --git a/sim/finality-attacks-results/v3-known-failed.md b/sim/finality-attacks-results/v3-known-failed.md new file mode 100644 index 000000000..1b3ad2a18 --- /dev/null +++ b/sim/finality-attacks-results/v3-known-failed.md @@ -0,0 +1,16 @@ + +### split50-v3: warm 230 s, split 420 s, heal window 200 s, 1 blocks/s in all, delay 300 ms, rule v3; old bound W / (3 R) = 80 s, frozen table expires 240 s after the last lock (W = 120 DAA, R = 0.5 blocks/s per side of a 3/3 split) + +| measure | n0 (side A) | n1 (side B) | n2 (side B) | +|---|---|---|---| +| max locked index at the cut | 7 | 7 | 7 | +| new locks during the split (index above 7) | 6 | 7 | 7 | +| first new lock, s after the cut | 258 | 237 | 237 | +| max locked index at the end of the heal window | 17 | 17 | 17 | +| locking resumed after the heal | true | true | true | +| conflicting certificates logged | 15 | 6 | 0 | +| checkpoints held back by the frozen table (debug lines) | 0 | 0 | 0 | + +n0 reconnected 72 s after the gate reopened; locked indices disagreeing across the three nodes at the end: 7; weights at the cut: window daa 209, voters 6 + +[FAIL] split50-v3 diff --git a/sim/finality-attacks-results/v4-pause-fix.md b/sim/finality-attacks-results/v4-pause-fix.md new file mode 100644 index 000000000..c7e3e666a --- /dev/null +++ b/sim/finality-attacks-results/v4-pause-fix.md @@ -0,0 +1,16 @@ + +### split50-v3: warm 230 s, split 420 s, heal window 400 s, 1 blocks/s in all, delay 300 ms, rule v3; old bound W / (3 R) = 80 s, frozen table expires 240 s after the last lock (W = 120 DAA, R = 0.5 blocks/s per side of a 3/3 split) + +| measure | n0 (side A) | n1 (side B) | n2 (side B) | +|---|---|---|---| +| max locked index at the cut | 6 | 6 | 6 | +| new locks during the split (index above 6) | 0 | 0 | 0 | +| first new lock, s after the cut | none | none | none | +| max locked index at the end of the heal window | 25 | 25 | 25 | +| locking resumed after the heal | true | true | true | +| conflicting certificates logged | 0 | 0 | 0 | +| checkpoints held back by the frozen table (debug lines) | 0 | 0 | 0 | + +n0 reconnected 102 s after the gate reopened; locked indices disagreeing across the three nodes at the end: 0; weights at the cut: window daa 179, voters 6 + +[PASS] split50-v3 diff --git a/sim/finality-attacks-results/v4-pause.md b/sim/finality-attacks-results/v4-pause.md new file mode 100644 index 000000000..025c221c8 --- /dev/null +++ b/sim/finality-attacks-results/v4-pause.md @@ -0,0 +1,16 @@ + +### split50-v3: warm 230 s, split 420 s, heal window 200 s, 1 blocks/s in all, delay 300 ms, rule v3; old bound W / (3 R) = 80 s, frozen table expires 240 s after the last lock (W = 120 DAA, R = 0.5 blocks/s per side of a 3/3 split) + +| measure | n0 (side A) | n1 (side B) | n2 (side B) | +|---|---|---|---| +| max locked index at the cut | 7 | 7 | 7 | +| new locks during the split (index above 7) | 0 | 0 | 0 | +| first new lock, s after the cut | none | none | none | +| max locked index at the end of the heal window | 7 | 7 | 7 | +| locking resumed after the heal | false | false | false | +| conflicting certificates logged | 0 | 0 | 0 | +| checkpoints held back by the frozen table (debug lines) | 0 | 0 | 0 | + +n0 reconnected 102 s after the gate reopened; locked indices disagreeing across the three nodes at the end: 0; weights at the cut: window daa 209, voters 6 + +[FAIL] split50-v3 diff --git a/sim/finality-attacks-results/v4-recovery-fix.md b/sim/finality-attacks-results/v4-recovery-fix.md new file mode 100644 index 000000000..9024d229b --- /dev/null +++ b/sim/finality-attacks-results/v4-recovery-fix.md @@ -0,0 +1,16 @@ + +### split50-v3: warm 230 s, split 420 s, heal window 400 s, 1 blocks/s in all, delay 300 ms, rule v3; old bound W / (3 R) = 80 s, frozen table expires 240 s after the last lock (W = 120 DAA, R = 0.5 blocks/s per side of a 3/3 split) + +| measure | n0 (side A) | n1 (side B) | n2 (side B) | +|---|---|---|---| +| max locked index at the cut | 5 | 5 | 5 | +| new locks during the split (index above 5) | 0 | 8 | 8 | +| first new lock, s after the cut | none | 249 | 249 | +| max locked index at the end of the heal window | 24 | 24 | 24 | +| locking resumed after the heal | true | true | true | +| conflicting certificates logged | 0 | 0 | 0 | +| checkpoints held back by the frozen table (debug lines) | 0 | 0 | 0 | + +n0 reconnected 72 s after the gate reopened; locked indices disagreeing across the three nodes at the end: 0; weights at the cut: window daa 150, voters 6 + +[FAIL] split50-v3 diff --git a/sim/finality-attacks-results/v4-recovery-split70-fix.md b/sim/finality-attacks-results/v4-recovery-split70-fix.md new file mode 100644 index 000000000..2e5070970 --- /dev/null +++ b/sim/finality-attacks-results/v4-recovery-split70-fix.md @@ -0,0 +1,16 @@ + +### split70-v3: warm 230 s, split 420 s, heal window 400 s, 1 blocks/s in all, delay 300 ms, rule v3; old bound W / (3 R) = 80 s, frozen table expires 240 s after the last lock (W = 120 DAA, R = 0.5 blocks/s per side of a 3/3 split) + +| measure | n0 (side A) | n1 (side B) | n2 (side B) | +|---|---|---|---| +| max locked index at the cut | 7 | 7 | 7 | +| new locks during the split (index above 7) | 0 | 9 | 9 | +| first new lock, s after the cut | none | 24 | 24 | +| max locked index at the end of the heal window | 28 | 28 | 28 | +| locking resumed after the heal | true | true | true | +| conflicting certificates logged | 0 | 0 | 0 | +| checkpoints held back by the frozen table (debug lines) | 0 | 0 | 0 | + +n0 reconnected 102 s after the gate reopened; locked indices disagreeing across the three nodes at the end: 0; weights at the cut: window daa 209, voters 6 + +[PASS] split70-v3 diff --git a/sim/finality-attacks-results/v4-recovery-split70.md b/sim/finality-attacks-results/v4-recovery-split70.md new file mode 100644 index 000000000..a7490411e --- /dev/null +++ b/sim/finality-attacks-results/v4-recovery-split70.md @@ -0,0 +1,16 @@ + +### split70-v3: warm 230 s, split 420 s, heal window 200 s, 1 blocks/s in all, delay 300 ms, rule v3; old bound W / (3 R) = 80 s, frozen table expires 240 s after the last lock (W = 120 DAA, R = 0.5 blocks/s per side of a 3/3 split) + +| measure | n0 (side A) | n1 (side B) | n2 (side B) | +|---|---|---|---| +| max locked index at the cut | 6 | 6 | 6 | +| new locks during the split (index above 6) | 0 | 9 | 9 | +| first new lock, s after the cut | none | 39 | 39 | +| max locked index at the end of the heal window | 21 | 21 | 21 | +| locking resumed after the heal | true | true | true | +| conflicting certificates logged | 0 | 0 | 0 | +| checkpoints held back by the frozen table (debug lines) | 0 | 0 | 0 | + +n0 reconnected 72 s after the gate reopened; locked indices disagreeing across the three nodes at the end: 0; weights at the cut: window daa 179, voters 6 + +[PASS] split70-v3 diff --git a/sim/finality-attacks-results/v4-recovery.md b/sim/finality-attacks-results/v4-recovery.md new file mode 100644 index 000000000..357f9cf9d --- /dev/null +++ b/sim/finality-attacks-results/v4-recovery.md @@ -0,0 +1,16 @@ + +### split50-v3: warm 230 s, split 420 s, heal window 200 s, 1 blocks/s in all, delay 300 ms, rule v3; old bound W / (3 R) = 80 s, frozen table expires 240 s after the last lock (W = 120 DAA, R = 0.5 blocks/s per side of a 3/3 split) + +| measure | n0 (side A) | n1 (side B) | n2 (side B) | +|---|---|---|---| +| max locked index at the cut | 7 | 7 | 7 | +| new locks during the split (index above 7) | 7 | 0 | 0 | +| first new lock, s after the cut | 195 | none | none | +| max locked index at the end of the heal window | 18 | 18 | 18 | +| locking resumed after the heal | true | true | true | +| conflicting certificates logged | 0 | 0 | 0 | +| checkpoints held back by the frozen table (debug lines) | 0 | 0 | 0 | + +n0 reconnected 102 s after the gate reopened; locked indices disagreeing across the three nodes at the end: 0; weights at the cut: window daa 209, voters 6 + +[FAIL] split50-v3 diff --git a/sim/results_v2.md b/sim/results_v2.md index 2fd3b62c7..256b24024 100644 --- a/sim/results_v2.md +++ b/sim/results_v2.md @@ -802,3 +802,28 @@ Two rows per share: the equivocator mines on the first side only (as H, I and M5 | checkpoints held back by the frozen table (debug lines) | 0 | 0 | 0 | n0 reconnected 102 s after the gate reopened; locked indices disagreeing across the three nodes at the end: 8; weights at the cut: window daa 209, voters 6 + +### The harness line on real nodes under rule v4 (igneum-build-2, 18:0x to 18:55 UK, the node lane): the four runs on the release-2.0.0-node pair bee41b5e (the rule v4 node change, `finality_v4_activation_daa` 0 through `IGNEUM_FIN_OVERRIDE_JSON`), the pass line per variant as 6.7 states it + +`tools/finality-attacks/v3.mjs split50` and `split70` on `/srv/artefacts/200-bee41b5e/node-lane`, the same shape as the v3 line above (three igneumd on the 60x file, six voters, one-way delay 300 ms per proxied link, 1 block/s, WARM 230 s, SPLIT 420 s, HEAL 200 s), under the lease pool. The criterion named per row is the one of 6.7: pause-only and v3, no lock on either side during the split, locking resumed after the heal, 0 conflicting certificates, 0 disagreeing locks; recovery, at most one side locks during the split (the side above half of the anchored table by weight), 0 conflicting certificates, 0 disagreeing locks, every node on the recovering side's chain after the heal. The harness's own `[PASS]`/`[FAIL]` print on these runs was the pause line for every split50 run (`v3.mjs` keyed the line on the recovery switch only after them; the commit that carries these rows). + +| run | rule (override) | new locks during the split, n0 (side A) / n1 / n2 (side B) | first new lock, s after the cut | max locked index at the cut / at the end | locking resumed after the heal | conflicting certificates logged | disagreeing locked indices at the end | n0 reconnected, s after the gate reopened | verdict by the 6.7 criterion | +|---|---|---|---|---|---|---|---|---|---| +| v3-known-failed | v3 (`finality_v3_activation_daa` 0) | 6 / 7 / 7 | 258 / 237 / 237 | 7 / 17 | true on every node | 0 / 0 / 0 (build-4's 0.3.25 run logged 4 / 8 / 8: the line depends on which certificate reaches a node first after the reconnect) | 7 | 72 | FAIL (the known-failed line: both sides locked alone past the frozen table's expiry at 240 s, the disagreeing locks are the fault either way) | +| v4-pause | v4, recovery off (`finality_v4_activation_daa` 0, `finality_v4_recovery` false) | 0 / 0 / 0 | none | 7 / 7 | **false on every node** | 0 / 0 / 0 | 0 | 102 | the split half PASSES (no side locks, "paused: held by weight table 7 past its window, a recovery lock needs more than half" and "the pause stands until two thirds sign" on every node); the heal half read a NODE FAULT: 98 s after the reconnect the anchored table read 84.03 to 100.00 percent signing on every node and finality stayed paused, because the node's anchored test refused everything past one window of the lock when the recovery was off (a pause longer than a window could never end, against 6.5). Fixed on release-2.0.0-node (two thirds of the anchored table locks at any time; the majority test only past the window with the recovery on); the rerun with HEAL 400 s below | +| v4-recovery | v4, recovery on (`finality_v4_recovery` true) | 7 / 0 / 0 | 195 / none / none | 7 / 18 | true on every node | 0 / 0 / 0 | 0 | 102 | PASS by the recovery criterion: side A held 51.26 percent of the anchored table frozen at lock 7 (block-count jitter in a 3/3 split: a0 a1 a2 against b0 b1 b2 at equal shares), took the "RECOVERY lock at index 11 (rule v4): 51.26% of the anchored table ... signed, more than half; the table re-anchors here" one full window after lock 7 and locked 12 to 18 on its chain; side B read 48.73 percent and stayed paused ("a recovery lock needs more than half"); on the reconnect n1 and n2 took A's index 11 certificate as the re-anchor and its locks 12 to 18; 0 conflicts, 0 disagreement, all three nodes at 18 | +| v4-recovery-split70 | v4, recovery on, `split70` (p0..p3 at 0.175 on n1 and n2, q0 q1 at 0.15 on n0) | 0 / 9 / 9 | none / 39 / 39 | 6 / 21 | true on every node | 0 / 0 / 0 | 0 | 72 | PASS (the harness's own line too): the 70 percent side locks from 39 s after the cut (above two thirds of the sliding table it fills and above half of the anchored one, no window needed), the 30 percent side never, the heal takes the 30 side onto the 70 side's chain with 0 conflicts | + +Two facts for the reader. The v3 known-failed line's conflicting-certificate count is not the fault's measure (0 here, 4/8/8 on build-4); the disagreeing locked indices after the heal are (7 here, 8 there). The pause line's "resumed" needs a heal window of at least one weight window after the reconnect: with HEAL 200 s and the reconnect at 102 s only 98 s remain, under W = 120 DAA s at 1 block/s, so the fair read is HEAL 400 s (the rerun rows below). + +### The reruns on the fixed node (igneum-build-2, 19:32 to 20:25 UK): the three rule v4 runs on the 2.0.1 successor pair 12424341 (the pause fix 6872db13: two thirds of the anchored table locks at any time, the majority test only past the window with the recovery on), HEAL 400 s + +The same harness and shape, the heal window at 400 s so "resumed" has a full weight window after the reconnect (W = 120 DAA s at 1 block/s; the reconnect came 72 to 102 s after the gate reopened). The result files are in `sim/finality-attacks-results/` (the seven runs of tonight, the harness's own markdown). The harness's `[PASS]`/`[FAIL]` print on the two split50 runs is the copy on build-2 from before the criterion change; the line in `tools/finality-attacks/v3.mjs` is keyed on the recovery switch from this commit. + +| run | rule (override) | new locks during the split, n0 (side A) / n1 / n2 (side B) | first new lock, s after the cut | max locked index at the cut / at the end | locking resumed after the heal | conflicting certificates | disagreeing locked indices at the end | n0 reconnected, s after the gate reopened | verdict by the 6.7 criterion | +|---|---|---|---|---|---|---|---|---|---| +| v4-pause-fix | v4, recovery off | 0 / 0 / 0 | none | 6 / 25 | **true on every node** (lock 7 at the reconnect, 22 to 25 by the window's end at 68 to 72 percent of active) | 0 / 0 / 0 | 0 | 102 | PASS: the node fault of the first run is closed; no side locks during the split and the pause ends when two thirds of the anchored table sign again (6.5's "lasts until it signs again") | +| v4-recovery-fix | v4, recovery on | 0 / 8 / 8 | none / 249 / 249 | 5 / 24 | true on every node | 0 / 0 / 0 | 0 | 72 | PASS by the recovery criterion: this time side B held 54.62 percent of the table frozen at lock 5 and took the "RECOVERY lock at index 10" 249 s after the cut, side A paused at 31 to 45 percent ("a recovery lock needs more than half"); n0 took B's chain and certificate at the heal, all three at 24. With the first run (side A at 51.26 percent) the jitter decided the side both ways: the fact for section 7 item 4 | +| v4-recovery-split70-fix | v4, recovery on, split70 | 0 / 9 / 9 | none / 24 / 24 | 7 / 28 | true on every node | 0 / 0 / 0 | 0 | 102 | PASS (the harness's own line too): the 70 percent side locks from 24 s after the cut, the 30 side never, the heal takes it onto the 70 side's chain | + +Summary of the seven runs: rule v3 fails its known-failed line as before (both sides lock alone, disagreeing locks after the heal); rule v4 without the recovery never locks during a split and resumes after the heal once the fixed node is used; rule v4 with the recovery lets exactly the side above half of the anchored table lock after a full window and brings the other side onto that chain at the heal; no run under rule v4 logged a conflicting certificate or ended with a disagreeing lock. diff --git a/tools/ci/batches/fin-v4-realnode-20261008T2025Z.json b/tools/ci/batches/fin-v4-realnode-20261008T2025Z.json new file mode 100644 index 000000000..a5c5faa28 --- /dev/null +++ b/tools/ci/batches/fin-v4-realnode-20261008T2025Z.json @@ -0,0 +1,22 @@ +{ + "run_id": "fin-v4-realnode-20261008T2025Z", + "manifest_sha": "12424341", + "evidence_dir": "sim/finality-attacks-results", + "boxes": [ + "build-2" + ], + "cells": [ + { + "cell": "node:finality-realnode", + "status": "PASS", + "evidence": "sim/finality-attacks-results/v4-pause-fix.md", + "note": "the node lane's rule v4 harness on real nodes (tools/finality-attacks/v3.mjs split50 and split70, three igneumd on the 60x file, six voters, WARM 230 SPLIT 420 HEAL 400 BPS 1): the pause-only run on the fixed pair 12424341 (the pause fix 6872db13) locks nothing during the split and resumes after the heal (lock 7 at the reconnect, 25 by the window's end), 0 conflicting certificates, 0 disagreeing locks; the recovery runs lock exactly the side above half of the anchored table (54.62 percent this time, 51.26 the other way on bee41b5e) with every node on that chain after the heal; split70 as before; rule v3's known-failed line fails as it must (both sides lock alone, 7 disagreeing locks). The first v4-pause run on bee41b5e read the node fault (a permanent pause past one window with the recovery off) that the fix closed. Rows: sim/results_v2.md, Rule v4, the two real-node tables; the seven result files beside this evidence path." + }, + { + "cell": "harness:finality-sim", + "status": "RUNNING", + "evidence": "sim/results_v2.md", + "note": "FIN-08 through the finality-sim cell: the node lane's real-node rows (the Rule v4 section's two real-node tables and sim/finality-attacks-results/) join the simulator's scenario N rows; the combined-boundary and adversarial-schedule runs on real nodes (the 40/40/20 case past the window with equivocation and dust-valid mining, the pause-only alternative with backfill) are tomorrow's daylight plan on build-7/8/9; RUNNING until those rows are in" + } + ] +} diff --git a/tools/finality-attacks/v3.mjs b/tools/finality-attacks/v3.mjs index 93b8db3ea..357b94b69 100644 --- a/tools/finality-attacks/v3.mjs +++ b/tools/finality-attacks/v3.mjs @@ -162,7 +162,15 @@ async function split(kind) { const sideA = newLocks[0], sideB = Math.max(newLocks[1], newLocks[2]); const R = BPS / 2, bound = Math.round(120 / (3 * R)), cliff = Math.round(120 / R); let pass; - if (kind === 'split50') pass = V2 ? true : (sideA === 0 && sideB === 0 && resumed.every(Boolean) && conflicts.every(c => c === 0) && disagree === 0); + // the pass line per variant (finality-guarantees.md 6.7, 8 October 2026): under rule v4 with the recovery a 3/3 split + // is not exactly half of T_f by weight (block-count jitter decides which side holds more than half), so exactly one + // side may lock during the split and every node follows its chain after the heal; under the pause-only variant and + // rule v3 no side locks, and locking resumes after the heal (a heal window of at least one weight window after the + // reconnect is the fair read: HEAL=400 at 1 block/s) + const recovery = (() => { try { return !!JSON.parse(process.env.IGNEUM_FIN_OVERRIDE_JSON || '{}').finality_v4_recovery; } catch { return false; } })(); + if (kind === 'split50') pass = V2 ? true : recovery + ? ((sideA === 0 || sideB === 0) && resumed.every(Boolean) && conflicts.every(c => c === 0) && disagree === 0) + : (sideA === 0 && sideB === 0 && resumed.every(Boolean) && conflicts.every(c => c === 0) && disagree === 0); else pass = sideB > 0 && sideA === 0 && conflicts.every(c => c === 0) && disagree === 0; out(`\n### ${name}: warm ${WARM} s, split ${SPLIT} s, heal window ${HEAL} s, ${BPS} blocks/s in all, delay ${DELAY_MS} ms, rule ${RULE}; old bound W / (3 R) = ${bound} s, frozen table expires ${cliff} s after the last lock (W = 120 DAA, R = ${R} blocks/s per side of a 3/3 split)\n`); out('| measure | n0 (side A) | n1 (side B) | n2 (side B) |');