p3_circle/proof.rs
1use alloc::vec::Vec;
2
3use p3_commit::Mmcs;
4use p3_field::Field;
5use serde::{Deserialize, Serialize};
6
7#[derive(Serialize, Deserialize, Clone)]
8#[serde(bound(
9 serialize = "Witness: Serialize, InputProof: Serialize",
10 deserialize = "Witness: Deserialize<'de>, InputProof: Deserialize<'de>"
11))]
12pub struct CircleFriProof<F: Field, M: Mmcs<F>, Witness, InputProof> {
13 pub commit_phase_commits: Vec<M::Commitment>,
14 pub commit_pow_witnesses: Vec<Witness>,
15 /// Openings of the input commitments at every query index, sharing one proof
16 /// per committed tree.
17 pub input_openings: InputProof,
18 /// For each commit phase commitment, the openings of the commit phase codeword
19 /// at every queried location, all authenticated by one shared proof per round.
20 pub commit_phase_openings: Vec<CircleCommitPhaseMultiStep<F, M>>,
21 // This could become Vec<FC::Challenge> if this library was generalized to support non-constant
22 // final polynomials.
23 pub final_poly: F,
24 pub pow_witness: Witness,
25}
26
27/// All queries' openings of one commit-phase codeword, sharing one proof.
28///
29/// The per-query equivalent shipped one full authentication path per query;
30/// queries into the same tree overlap heavily, so shared sibling digests are
31/// deduplicated by the multiproof.
32#[derive(Debug, Serialize, Deserialize, Clone)]
33#[serde(bound = "")]
34pub struct CircleCommitPhaseMultiStep<F: Field, M: Mmcs<F>> {
35 /// The log2 of the folding arity used for this round.
36 ///
37 /// The schedule is a protocol-wide constant, so it lives once per round
38 /// rather than once per query.
39 pub log_arity: u8,
40 /// For each query, the openings of the commit phase codeword at the sibling
41 /// locations. For arity k, each entry contains k-1 sibling values.
42 pub sibling_values: Vec<Vec<F>>,
43 /// One shared proof authenticating every query's row in this round's tree.
44 pub opening_proof: M::MultiProof,
45}
46
47impl<F: Field, M: Mmcs<F>> CircleCommitPhaseMultiStep<F, M> {
48 /// Convert `log_arity` to `usize` and enforce the protocol bounds.
49 ///
50 /// Returns `None` when `log_arity` is zero or exceeds `max_log_arity`.
51 #[inline]
52 pub(crate) fn checked_log_arity(&self, max_log_arity: usize) -> Option<usize> {
53 let log_arity = self.log_arity as usize;
54 (1..=max_log_arity)
55 .contains(&log_arity)
56 .then_some(log_arity)
57 }
58}