fud ledger N13: every build since 10db4b61 dies on a kept 0.3.17 datadir (BlockRewardData.silent under serde(default), which bincode ignores); the v1-row read in the virtual-state store

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-labs 2026-10-07 12:03:20 +00:00
parent 7940596577
commit 4e9c92a4da

View file

@ -2445,6 +2445,14 @@ Per tier: a home machine runs one node and never holds its own exec port, so the
Fix on release-0.3.20-node (the third commit, on top of 6a3432a3): in `rpc::serve_watched` a bind failure is a retry every poll with one line a minute ("exec RPC listener cannot bind (...); retrying every N ms, the node runs without its exec RPC meanwhile") and no death counted, never an exit; a death after a successful bind keeps the rebind-once-then-exit rule. Gate: `a_held_port_is_retried_and_never_counted_as_a_death` beside the watchdog's own test, known failed first on the old rule (a held port reached the exit hook inside two polls), then the listener binding the moment the port frees. Owed: the harnesses set distinct exec ports per node so a bind failure is never part of a gate's shape.
### N13. Every build since 10db4b61 dies at start on a kept 0.3.17 datadir: `BlockRewardData.silent` under `#[serde(default)]`, which bincode ignores, reads the virtual-state row short (p12-vast on pool-1's kept datadir, 7 October 2026, 13:56 UK)
The fleet lane started 6a3432a3 on a second datadir, pool-1's kept 0.3.17 copy (the one the cases' relay node reads under 6615571c without complaint), and it died 1.2 s after "Data directory": `thread 'main' panicked at consensus/src/model/stores/virtual_state.rs:250:58: called Result::unwrap() on an Err value: DeserializationError(Io(Kind(UnexpectedEof)))`. The cause is one field: 10db4b61 (vote-or-burn and the signing bonus, the 0.3.16 feature line) added `silent: bool` to `kaspa_consensus_core::coinbase::BlockRewardData` with `#[serde(default)]`, and the virtual-state row (`VirtualState.mergeset_rewards: BlockHashMap<BlockRewardData>`, bincode under `[prefix || 1]`) written by any build before it carries three fields per reward; bincode is not self-describing and never applies a serde default, so the new layout reads the old row short. Every build from 10db4b61 on (dc141409, 8097d600, 6b94c823, 6a3432a3, 09124180) dies the same way on every kept 0.3.17 datadir; no canary saw it because every canary wiped, and the fallback pin's own gates (wiped networks) could not either.
Per tier: a one-box roll keeps datadirs, so the roll would have killed every standing box, hand and hub at the first restart on the new binary (alive for a second, then the panic, the app blind to it); a home machine that updated in place the same; a fresh install unaffected; nothing on chain affected, the node simply never started.
Fix on release-0.3.20-node (the fourth commit): the virtual-state store reads the live row in the current layout first (a datadir already on the line keeps reading first-try) and on a deserialization error decodes it as a mirror of the v1 layout (`IgneumV1VirtualState`, rewards of three fields), converts with `silent: false` (no block of that row was judged silent; the next virtual update recomputes it) and rewrites it under the same key in the current layout, with one info line; the version suffix is unchanged. Gate: `a_virtual_state_row_from_before_the_silence_field_is_read_and_rewritten` (a v1 row on a temp DB; the current layout reads it short first, the known-failed shape; the store reads, converts and rewrites; a second open reads first-try), and the fleet's kept-datadir start on p12-vast's second datadir on the fixed binary. The rule this adds for every node cut from now: a kept-datadir restart gate on a standing box's datadir copy beside the wiped canary, and no persisted struct gains a field under `#[serde(default)]` without a versioned read (bincode does not default).
## Status updates, 5 October 2026 (ledger sweep, night of 4 to 5 October)
`docs/review/ledger-sweep-2026-10-05.md` holds the runs, the commands and the running table. Every Open, Proposed, Unmeasured or pending entry was read against its experiment line; the status lines above carry the evidence inline, marked "Sweep (5 October 2026)" where a note was added and "Was:" where the status changed. Items owned by the other two night branches (F23, F24, G12, X18, the flood memory growth; the base-fee floor, testnet parameters, G13, G14, public text) were left to them.