pub struct BuyerLedgers { /* private fields */ }Expand description
The voucher ledger of each lane’s current pool, shared by every concurrent pull on it.
Keyed by LaneKey ({pool_id, signer, provider}) so the ledger a pull issues through
is pinned to the exact lane it read: a stale or rotated pool can neither collide with nor
evict a different lane’s live ledger. Cardinality stays bounded without that hazard — a
rotated pool’s ledger is dropped by Self::get_or_seed the moment no pull still holds
it (Arc::strong_count == 1), so at most one live lane per provider lingers, plus any
whose pulls are still in flight. That is the buyer store’s bound, made safe against a
stale key (#1145 review): the earlier provider-only key evicted the live ledger on ANY
pool-id mismatch, which is exactly the collision this type exists to prevent.
Implementations§
Source§impl BuyerLedgers
impl BuyerLedgers
Sourcepub fn get_or_seed(&self, key: LaneKey, seed: Cumulative) -> Arc<PoolLedger> ⓘ
pub fn get_or_seed(&self, key: LaneKey, seed: Cumulative) -> Arc<PoolLedger> ⓘ
The ledger to issue this pull’s vouchers through: the live one for key, or a fresh
one seeded from seed if there is none.
seed is the lane’s persisted cumulative and the only state a fresh ledger inherits.
A hash chain draws its own secret when it opens and is never reopened across a restart
(ADR 003 §Resumption folds), so there is nothing else here for a caller to supply and
nothing for a stale row to contradict.
An existing entry for the SAME lane wins over seed, and that precedence is the
whole point. seed comes from the persisted row that open_or_reuse_pool read; a
concurrent pull holding the live ledger may already have issued vouchers the row does
not carry yet (it is written on redeem, not on issue). Re-seeding from the row would
rewind the watermark and re-create the collision this type exists to prevent.
A DIFFERENT lane addresses a DIFFERENT entry — a rotated or stale pool can neither
read nor evict this lane’s ledger. The provider’s other lanes are pruned here, but
only those no pull still holds (Arc::strong_count == 1), so a rotation cannot throw
away a ledger a concurrent pull is issuing through.
Sourcepub fn pool_committed(&self, pool_id: PoolId) -> U256
pub fn pool_committed(&self, pool_id: PoolId) -> U256
The pool’s total committed spend: the sum, across every live lane whose
LaneKey::pool_id matches pool_id, of that lane’s committed voucher
amount.
This is the whole-pool spend the node’s ranged-drive loop gates on
(#1506). One buyer pool backs a voucher lane per provider, and the loop
assembles a blob across those providers as a sequence of lanes drawing on
the SAME deposit. Each lane’s live ledger stays in the map for the whole
assembly (a new provider’s lane never evicts another provider’s), so
summing them here — including the run currently issuing vouchers, which
seeded its own live ledger via Self::get_or_seed — yields the exact
cumulative spend against the shared deposit. The live ledgers are the
authoritative in-memory watermarks (a persisted row lags, written on
redeem, not on issue), so a solvency gate reading this never under-counts
a still-in-flight voucher.
Sourcepub fn forget(&self, key: LaneKey)
pub fn forget(&self, key: LaneKey)
Drop key’s ledger — the lane was retired, so no further voucher can be signed
against it.
Keyed by the exact lane, so a concurrent open that already rotated the provider onto a NEW pool is untouched: its ledger lives under a different key and is not thrown away.
Trait Implementations§
Source§impl Debug for BuyerLedgers
impl Debug for BuyerLedgers
Auto Trait Implementations§
impl !Freeze for BuyerLedgers
impl RefUnwindSafe for BuyerLedgers
impl Send for BuyerLedgers
impl Sync for BuyerLedgers
impl Unpin for BuyerLedgers
impl UnsafeUnpin for BuyerLedgers
impl UnwindSafe for BuyerLedgers
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request