pub struct MergeVerifierChannel<'a, F, C>where
F: Field,
C: IOPVerifierChannel<F>,{ /* private fields */ }Expand description
A verifier channel decorator that merges one round’s oracles into one combined oracle.
§Overview
An interaction round is the run of oracle receipts between two challenge samples.
Committing each oracle separately costs one commitment per oracle. One Merkle tree per oracle, for example.
This decorator buffers a round’s oracles instead. It commits them together as one larger oracle. That cuts the cost to one commitment per round.
§Merging
A round’s oracles are sorted from largest to smallest. They are laid out end to end.
Every oracle’s size is a power of two.
Write the sizes as 2^n_1, 2^n_2, ..., 2^n_k.
Sort them so n_1 >= n_2 >= ... >= n_k.
The combined oracle’s size is 2^N.
N is the smallest exponent that covers the total.
combined oracle, size 2^N:
[ oracle 1 (2^n_1) | oracle 2 (2^n_2) | ... | oracle k (2^n_k) | unused padding ]
offset 0 offset 2^n_1 total size 2^NSorting largest to smallest makes this layout exact.
Every earlier oracle is at least as large as the current one. So their combined space is a whole multiple of the current oracle’s size. The current oracle therefore starts on a boundary of its own size. Its position is then a whole number of its-own-size blocks. That whole number is its block index.
A round of a single oracle needs no combining. It is forwarded unchanged, at zero cost.
A round is witness-dependent as soon as any of its oracles is.
A commitment is masked as a whole, never partly. So a structural oracle sharing a round with a witness-carrying one is masked too.
§Timing
A round’s oracles are committed the moment its last oracle arrives.
The OracleSchedule says where each round ends, so no challenge sample is needed to find
the boundary.
A real Fiat-Shamir transcript can therefore absorb the commitment before the next challenge.
§Opening
A constituent oracle’s claim is an inner product. It pairs the oracle’s data with a transparent polynomial.
That claim becomes a claim about the combined oracle too. Extend the transparent polynomial with an equality check. The check is one over the constituent’s own block, zero elsewhere.
extended transparent(x) = original transparent(low bits of x) * is_this_block(high bits of x)The check is zero outside the constituent’s own block. So the combined inner product only ever sees this oracle’s own data. It equals the original claim exactly.
Implementations§
Source§impl<'a, F, C> MergeVerifierChannel<'a, F, C>where
F: Field,
C: IOPVerifierChannel<F>,
impl<'a, F, C> MergeVerifierChannel<'a, F, C>where
F: Field,
C: IOPVerifierChannel<F>,
Sourcepub fn new(inner: C, schedule: &'a OracleSchedule) -> Self
pub fn new(inner: C, schedule: &'a OracleSchedule) -> Self
Creates a new merging verifier channel over an underlying channel.
§Arguments
inner— the channel every combined oracle is committed to, already configured withschedule.merged_specs().schedule— every oracle this channel’s caller will pass through, grouped into rounds.
§Panics
Panics if inner is not configured with schedule.merged_specs().
Sourcepub fn into_inner(self) -> C
pub fn into_inner(self) -> C
Trait Implementations§
Source§impl<'a, F, C> IOPVerifierChannel<F> for MergeVerifierChannel<'a, F, C>where
F: Field,
C: IOPVerifierChannel<F>,
impl<'a, F, C> IOPVerifierChannel<F> for MergeVerifierChannel<'a, F, C>where
F: Field,
C: IOPVerifierChannel<F>,
type Oracle = MergeOracle
Source§fn remaining_oracle_specs(&self) -> &[OracleSpec]
fn remaining_oracle_specs(&self) -> &[OracleSpec]
Source§impl<F, C> IPVerifierChannel<F> for MergeVerifierChannel<'_, F, C>where
F: Field,
C: IOPVerifierChannel<F>,
impl<F, C> IPVerifierChannel<F> for MergeVerifierChannel<'_, F, C>where
F: Field,
C: IOPVerifierChannel<F>,
Source§type Elem = <C as IPVerifierChannel<F>>::Elem
type Elem = <C as IPVerifierChannel<F>>::Elem
Source§fn recv_one(&mut self) -> Result<Self::Elem, Error>
fn recv_one(&mut self) -> Result<Self::Elem, Error>
Source§fn recv_many(&mut self, n: usize) -> Result<Vec<Self::Elem>, Error>
fn recv_many(&mut self, n: usize) -> Result<Vec<Self::Elem>, Error>
n field elements from the prover.Source§fn recv_array<const N: usize>(&mut self) -> Result<[Self::Elem; N], Error>
fn recv_array<const N: usize>(&mut self) -> Result<[Self::Elem; N], Error>
Source§fn recv_public_claim(&mut self) -> Result<Self::Elem, Error>
fn recv_public_claim(&mut self) -> Result<Self::Elem, Error>
Source§fn observe_one(&mut self, val: F) -> Self::Elem
fn observe_one(&mut self, val: F) -> Self::Elem
Source§fn observe_many(&mut self, vals: &[F]) -> Vec<Self::Elem>
fn observe_many(&mut self, vals: &[F]) -> Vec<Self::Elem>
Source§impl<F, C> WordIPVerifierChannel<F> for MergeVerifierChannel<'_, F, C>
impl<F, C> WordIPVerifierChannel<F> for MergeVerifierChannel<'_, F, C>
Source§type Word = <C as WordIPVerifierChannel<F>>::Word
type Word = <C as WordIPVerifierChannel<F>>::Word
Source§fn observe_words(&mut self, words: &[Word]) -> Vec<Self::Word>
fn observe_words(&mut self, words: &[Word]) -> Vec<Self::Word>
Auto Trait Implementations§
impl<'a, F, C> Freeze for MergeVerifierChannel<'a, F, C>where
C: Freeze,
impl<'a, F, C> RefUnwindSafe for MergeVerifierChannel<'a, F, C>
impl<'a, F, C> Send for MergeVerifierChannel<'a, F, C>
impl<'a, F, C> Sync for MergeVerifierChannel<'a, F, C>
impl<'a, F, C> Unpin for MergeVerifierChannel<'a, F, C>
impl<'a, F, C> UnsafeUnpin for MergeVerifierChannel<'a, F, C>where
C: UnsafeUnpin,
impl<'a, F, C> UnwindSafe for MergeVerifierChannel<'a, F, C>
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