pub struct CircuitM4 {
pub main: EmbeddedCircuit,
pub chips: Vec<(EmbeddedCircuit, usize)>,
}Expand description
A circuit composed of chips, as the circuits that generate their witnesses.
main is the entry point: it calls chips, but no chip ID names it, so nothing calls it. The
chips have an ID equal to their index in chips.
Fields§
§main: EmbeddedCircuitThe entry point, which runs once.
chips: Vec<(EmbeddedCircuit, usize)>The chips, indexed by chip ID, each paired with its number of active instances.
A chip runs once per call that reaches it, and those instances are the active ones: only they have their own chip calls enforced. The instances past them pad the count up to a power of two.
The count is denormalized — it says what the call graph already says, and
Self::recompute_instances derives it, along with the instance each call claims.
Self::validate holds the two to each other.
Implementations§
Source§impl CircuitM4
impl CircuitM4
Sourcepub fn validate(&self) -> Result<(), CircuitM4Error>
pub fn validate(&self) -> Result<(), CircuitM4Error>
Checks that this system can be populated in one pass over the chips, in ID order.
Specifically checks that:
- every chip call names a chip of this system, passes no more operands than that chip has inout values, and reads only committed words of its own caller;
- the chips are in topological order, each calling only chips with a higher ID, so every caller of a chip is populated before the chip itself;
- each chip’s declared active-instance count is the number of invocations that reach it, no
chip is left uncalled, and no count outgrows a
usize; - each call names the callee instance the call graph gives it.
A system that passes here lowers to one that passes
ConstraintSystemM4::validate, which
requires the same ordering and additionally validates each chip’s compiled constraint
system — the one thing here the compiler rather than this check keeps well-formed. Nothing
downstream therefore has to run the lowered check to know its preconditions hold.
Sourcepub fn recompute_instances(&mut self)
pub fn recompute_instances(&mut self)
Gives each call the callee instances it invokes, and each chip the count of the ones it is left with.
A chip is invoked once per call site naming it, per active instance of the caller, and a
call site’s invocations are consecutive instances of the callee: the caller’s instance i
invokes the call’s first_instance plus i. Main runs once, so
each of its call sites claims a single instance.
This is what Self::validate checks the declared counts and instances against, so a
system whose call sites have just been written or rewritten passes it here rather than
counting by hand.
A count that outgrows a usize saturates rather than wrapping, so it stays too large for
the invocations that reach the chip and Self::validate reports it.
§Panics
Panics if a chip call names a chip this system does not have. Chips out of topological
order are not detected here: a call to a lower ID counts against a total already written
back, and Self::validate is what rejects the result.
Sourcepub fn to_constraint_system(&self) -> ConstraintSystemM4
pub fn to_constraint_system(&self) -> ConstraintSystemM4
Lowers this system to the constraint-system form the proving protocol consumes.
Each circuit contributes its compiled constraint system; the chip calls and the active-instance counts carry over unchanged.
Sourcepub fn generate_witness<F>(
&self,
fill_main: F,
) -> Result<WitnessM4, PopulateM4Error>where
F: FnOnce(&mut WitnessFiller<'_>),
pub fn generate_witness<F>(
&self,
fill_main: F,
) -> Result<WitnessM4, PopulateM4Error>where
F: FnOnce(&mut WitnessFiller<'_>),
Generates the witness for a whole system from the main circuit’s inputs.
fill_main assigns the witness inputs of the main circuit; every other value in the system
is derived from them. Each chip’s table holds one instance per invocation that reaches it,
each at the row the invoking call names. The instance count is rounded up to a power of two
by repeating the last invocation, which satisfies the chip because the invocation it copies
does.
§Panics
Panics if the system does not pass Self::validate, which covers both the ordering this
walks the chips in and the well-formedness of the operands it evaluates.
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for CircuitM4
impl !UnwindSafe for CircuitM4
impl Freeze for CircuitM4
impl Send for CircuitM4
impl Sync for CircuitM4
impl Unpin for CircuitM4
impl UnsafeUnpin for CircuitM4
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<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