Expand description
The live voucher ledger for each buyer lane’s current pool.
One PoolLedger per LaneKey is a CORRECTNESS requirement, not a
cache. The contract it exists to satisfy: a pull that seeds its own voucher
state from ctx.prior_* shares that watermark with every other pull on the
lane, so N concurrent pulls with N ledgers all sign the next cumulative voucher
from the same baseline and collide — the node accepts exactly one and rejects
the rest as an amount regression. open_progressive_pull therefore takes the
CHANNEL’s Arc<PoolLedger>, never a per-pull one.
Both node pull paths built a FRESH ledger per pull and so broke that contract (#1145
review). It is reachable at the defaults, on an ordinary node doing nothing unusual: the
cache engine coalesces in-flight pulls by hash (cache::engine::inflight), so two
misses for different blobs run concurrent NodeOrigin::fetch calls, and on a
tens-of-nodes network both routinely rank the same provider first. Both then take the
lane-reuse fast path, read the same prior watermark, and collide.
What made that fatal rather than merely wasteful is that an amount regression is a
terminal verdict: the losing pull’s collision wedges the lane until the pool’s deposit is
reclaimed at close (see crate::buyer_channel).
Structs§
- Buyer
Ledgers - The voucher ledger of each lane’s current pool, shared by every concurrent pull on it.