pub struct SsaCycle<S: PixSpec> {
id: SsaId<S::Pseudonym>,
builder: Mutex<SsaBuilder<S>>,
parts: Box<[Mutex<SsaPartBuilder<S>>]>,
useful_shares: AtomicU64,
recovered_polynomials: AtomicU32,
invalid_shares: AtomicU64,
target_useful_shares: u64,
}Expand description
All post-commitment state of one SSA cycle, held as a single unit.
§Why one entry per cycle rather than one per polynomial
The accumulator and every part builder are produced by the same call — see
CommitmentProgress — needed by the same code path, and dead at the same moment. Splitting
them across caches previously required holding three lifetimes in lockstep by hand, and getting
that wrong was H8: the part builders were keyed per polynomial with an idle timer, so the
clock measured “time since a share for this polynomial arrived”. Commitments land in a cycle’s
opening moments while shares arrive polynomial-major across all of it, so any polynomial late in
the emission order had its builder reclaimed before its first share — unrecoverably, since the
commitment cannot be retransmitted.
Keyed by SsaId, the idle timer measures “time since the cycle was active”, which is the
property that actually matters and is correct at any line rate.
§Locking
One mutex per part, plus one for the accumulator — never one around the whole cycle. A single cycle-wide lock would serialise every share of a Session behind one mutex. Callers take the part lock and the accumulator lock in that order, and never hold both.
Fields§
§id: SsaId<S::Pseudonym>§builder: Mutex<SsaBuilder<S>>§parts: Box<[Mutex<SsaPartBuilder<S>>]>Part builders indexed by PolynomialIndex; length is always num_polys.
Shares that advanced reconstruction: new, distinct, and below their part’s threshold when they arrived. Duplicates, surplus shares and shares absorbed by a failed part are excluded, so this is the numerator of a progress ratio rather than a received-packet count.
recovered_polynomials: AtomicU32Parts whose constant term has been reconstructed and opened its commitment.
Shares that failed verification, aggregated across every peer that relayed for this cycle.
A failure is charged once per offending share, not once per polynomial: a part reports its
failure exactly once and absorbs everything after it as
AddShareOutcome::Absorbed.
num_polys × poly_threshold — the useful-share count that constitutes full recovery.
Fixed at construction, and must equal the dimensions negotiated at session establishment: the consumer treats a mismatch as a protocol violation rather than as drift.
Implementations§
Source§impl<S: PixSpec> SsaCycle<S>
impl<S: PixSpec> SsaCycle<S>
Sourcepub fn new(
id: SsaId<S::Pseudonym>,
builder: SsaBuilder<S>,
parts: Vec<SsaPartBuilder<S>>,
) -> Result<Self, S::Pseudonym>
pub fn new( id: SsaId<S::Pseudonym>, builder: SsaBuilder<S>, parts: Vec<SsaPartBuilder<S>>, ) -> Result<Self, S::Pseudonym>
Assembles a cycle from the accumulator and the full set of part builders.
parts arrives in arbitrary order — it is drained from a HashMap — so each builder is
placed by its own polynomial index rather than by iteration order. A missing or duplicated
index is rejected here, which is what makes part safe to index by an
untrusted value later. Each builder is also checked to belong to id, so a part cannot be
filed under a cycle it does not describe.
Records a share that advanced reconstruction.
Sourcepub fn record_completed_part(&self)
pub fn record_completed_part(&self)
Records a polynomial part that reconstructed and opened its commitment.
Records a share that failed verification, returning the cycle’s total afterwards.
Sourcepub fn progress(&self) -> SsaRecoveryProgress<S::Pseudonym>
pub fn progress(&self) -> SsaRecoveryProgress<S::Pseudonym>
Absolute recovery progress for this cycle.
Sourcepub fn part(
&self,
poly_index: PolynomialIndex,
) -> Option<&Mutex<SsaPartBuilder<S>>>
pub fn part( &self, poly_index: PolynomialIndex, ) -> Option<&Mutex<SsaPartBuilder<S>>>
The part builder for one polynomial, or None if the index is out of range.
The index originates from a peer-supplied share, so this is a checked lookup and must stay one.
Sourcepub fn builder(&self) -> &Mutex<SsaBuilder<S>>
pub fn builder(&self) -> &Mutex<SsaBuilder<S>>
The accumulator that sums recovered parts into the SSA scalar.
Auto Trait Implementations§
impl<S> !Freeze for SsaCycle<S>
impl<S> !RefUnwindSafe for SsaCycle<S>
impl<S> Send for SsaCycle<S>
impl<S> Sync for SsaCycle<S>
impl<S> Unpin for SsaCycle<S>
impl<S> UnsafeUnpin for SsaCycle<S>where
<S as PixSpec>::Pseudonym: UnsafeUnpin,
<<S as PixSpec>::Curve as CurveArithmetic>::ProjectivePoint: UnsafeUnpin,
<<S as PixSpec>::Curve as CurveArithmetic>::Scalar: UnsafeUnpin,
impl<S> UnwindSafe for SsaCycle<S>where
<S as PixSpec>::Pseudonym: UnwindSafe,
<<S as PixSpec>::Curve as CurveArithmetic>::ProjectivePoint: UnwindSafe,
<<S as PixSpec>::Curve as CurveArithmetic>::Scalar: UnwindSafe,
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§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 more