Skip to main content

SsaCycle

Struct SsaCycle 

Source
pub struct SsaCycle<S: PixSpec> {
    id: SsaId<S::Pseudonym>,
    builder: Mutex<SsaBuilder<S>>,
    parts: Box<[Mutex<SsaPartBuilder<S>>]>,
    counters: Arc<RecoveryCounters>,
    surplus_budget: SurplusBudget,
}
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.

§counters: Arc<RecoveryCounters>

Shared payment, liveness, completed-part, and fault counters. They remain reachable from RecoveredSsaTail after the heavyweight cycle is released.

§surplus_budget: SurplusBudget

Per-polynomial surplus accounting shared with the compact post-recovery tail.

Implementations§

Source§

impl<S: PixSpec> SsaCycle<S>

Source

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.

Source

pub fn num_polys(&self) -> usize

Number of polynomials this cycle is composed of.

Source

pub fn record_useful_share(&self)

Records a share that advanced reconstruction — both a useful share and a share seen.

shares_seen first, so that in program order the counters never pass through a state where useful_shares leads. SsaRecoveryProgress::shares_seen promises to be at least useful_shares, and a consumer computing the surplus as the difference would otherwise underflow a u64 on the intermediate state. The two are separate Relaxed atomics, so this alone does not settle what another thread observes — progress clamps for that — but it removes the window rather than only papering over it.

Source

pub fn record_surplus_share(&self)

Records a share that arrived for an already-reconstructed polynomial.

Liveness only: the surplus a conforming Entry emits advances nothing, but it is still evidence that the Entry is serving this cycle, which is what the Exit’s egress gate and recovery-idle deadline are asking about.

Source

pub fn record_completed_part(&self)

Records a polynomial part that reconstructed and opened its commitment.

Source

pub fn record_invalid_share(&self) -> u64

Records a share that failed verification, returning the cycle’s total afterwards.

Source

pub fn progress(&self) -> SsaRecoveryProgress<S::Pseudonym>

Absolute recovery progress for this cycle.

The two share counters are independent Relaxed atomics, so a reader can observe them in either order regardless of the order they were written in. useful_shares is loaded first and shares_seen clamped up to it, which is what actually makes SsaRecoveryProgress::shares_seen’s “always at least useful_shares” a contract rather than a description: a consumer deriving the surplus as the difference cannot underflow. The clamp is engaged only for the instant a concurrent record_useful_share is mid-flight, and overstates shares_seen by at most the number of such writers.

Source

pub fn credit_surplus(&self, poly_index: PolynomialIndex) -> Option<bool>

Consumes one negotiated surplus slot for poly_index.

Called only after SsaPartBuilder::add_share has decoded and validated the share as a post-reconstruction candidate. None means the untrusted polynomial index is out of range; Some(false) means the Entry has exhausted this polynomial’s own budget.

Source

pub(crate) fn recovered_tail(&self) -> RecoveredSsaTail

Produces the compact state that survives full recovery while buffered SURBs drain.

Source

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.

Source

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>
where <S as PixSpec>::Pseudonym: Unpin, <<S as PixSpec>::Curve as CurveArithmetic>::ProjectivePoint: Unpin, <<S as PixSpec>::Curve as CurveArithmetic>::Scalar: Unpin,

§

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> FutureExt for T

§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more