Read rep weights for a tally as a single consistent snapshot (#5167) * Read rep weights for a tally as a single consistent snapshot The election ballot read each voting rep's weight with a separate locked lookup, so a tally over N reps cost N lock acquisitions and could interleave with ledger updates that touch several reps at once. The online weight total summed per-rep reads the same way. Add a batched rep_weights::get and ledger::weights that read all requested reps under one lock, make the ballot's weight query take a span of reps, and use it from the election and from online_reps::calculate_online. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Apply a representative and balance change as one rep weight update move_add_sub implemented a block that changes representative and balance at once as a move followed by a separate add or sub, each taking the rep_weights mutex on its own. Between the two steps the cache held an intermediate state, with the balance difference missing from or left behind on one of the two reps, and a batch read could observe it. Compute both new weights up front, write both to the store, and update both cache entries together with the committed and unused totals under one lock. move becomes the equal-amount case of the same operation. rep_weights_move_add_sub_snapshot and weights_snapshot_send_change observe the intermediate state with the previous implementation and pass with this one. The rep_weights unit tests are renamed and documented consistently and assert the stored and cached weights alongside the entry counts. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Check rep weight accounting through every block type and rollback No test asserted the committed and unused weight totals while blocks were processed and rolled back, and a receive into an epoch-opened account, whose previous representative is the zero account, had no weight assertion in either direction. weights_all_block_types drives legacy send, open, receive and change, state send, open, receive and send with a representative change, a plain representative change, an epoch upgrade, an epoch open and a receive into it through the ledger, then rolls every block back. After each step the cached and stored weights are compared with a model of each account's representative and balance, the committed total with the sum of balances and the unused total with what became pending, and a ledger rebuilt from the store is checked the same way. rep_weights_append_from covers the startup merge directly. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Guarantee the rep weight snapshot tests observe the update The snapshot tests released the writer after the reader's first read and stopped the reader once the writer was done, so a schedule that pauses the reader right after the release lets the writer finish unobserved and the test pass on a single read. Make the writer wait after every update, block and rollback until the reader has taken another snapshot, so every state the writer produces is observed. The iteration counts drop to a hundred rounds or blocks, which keeps the handshake cheap and the tests short. Add deterministic counterparts that need no scheduling luck. A nano::test::hooked_backend wraps the store backend and runs a callback before every point access, and a ledger store can be built on it. rep_weights_move_add_sub_mid_update and weights_snapshot_mid_update batch-read the cache from that callback, which runs inside the update before the cache lock is taken, exactly where a concurrent reader could interleave. Both fail deterministically against the former split implementation, together with the two unequal-amount snapshot tests, and pass against the current one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * Read the cached tally of an incoming fork as one weight snapshot election::publish summed the vote cache weight behind a fork arriving at a full ballot with one ledger.weight call per voter, the per-rep pattern the batched ledger.weights replaced on the rest of the tally path. Collect the voters and read their weights in one batched call, so a weight moving between two of them while the sum is taken is counted once. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
__________
Type: commit
Hash: e9642068151d9a487b851a433caab1ac272359a1
Created: yesterday
__________
gr0v1ty/nano-node:e9642068151d9a487b851a433caab1ac272359a1
| Test Case | Status | Duration | Median Deviation | Log | Graph |
|---|