sp1_recursion_circuit_v2/
types.rs

1use hashbrown::HashMap;
2use p3_commit::TwoAdicMultiplicativeCoset;
3use p3_field::{AbstractField, TwoAdicField};
4use p3_matrix::Dimensions;
5
6use sp1_recursion_compiler::ir::{Builder, Ext, Felt};
7
8use sp1_recursion_core_v2::DIGEST_SIZE;
9
10use crate::{
11    challenger::CanObserveVariable, hash::FieldHasherVariable, BabyBearFriConfigVariable,
12    CircuitConfig,
13};
14
15/// Reference: [sp1_core::stark::StarkVerifyingKey]
16#[derive(Clone)]
17pub struct VerifyingKeyVariable<C: CircuitConfig<F = SC::Val>, SC: BabyBearFriConfigVariable<C>> {
18    pub commitment: SC::Digest,
19    pub pc_start: Felt<C::F>,
20    pub chip_information: Vec<(String, TwoAdicMultiplicativeCoset<C::F>, Dimensions)>,
21    pub chip_ordering: HashMap<String, usize>,
22}
23
24#[derive(Clone)]
25pub struct FriProofVariable<C: CircuitConfig, H: FieldHasherVariable<C>> {
26    pub commit_phase_commits: Vec<H::Digest>,
27    pub query_proofs: Vec<FriQueryProofVariable<C, H>>,
28    pub final_poly: Ext<C::F, C::EF>,
29    pub pow_witness: Felt<C::F>,
30}
31
32/// Reference: https://github.com/Plonky3/Plonky3/blob/4809fa7bedd9ba8f6f5d3267b1592618e3776c57/fri/src/proof.rs#L32
33#[derive(Clone)]
34pub struct FriCommitPhaseProofStepVariable<C: CircuitConfig, H: FieldHasherVariable<C>> {
35    pub sibling_value: Ext<C::F, C::EF>,
36    pub opening_proof: Vec<H::Digest>,
37}
38
39/// Reference: https://github.com/Plonky3/Plonky3/blob/4809fa7bedd9ba8f6f5d3267b1592618e3776c57/fri/src/proof.rs#L23
40#[derive(Clone)]
41pub struct FriQueryProofVariable<C: CircuitConfig, H: FieldHasherVariable<C>> {
42    pub commit_phase_openings: Vec<FriCommitPhaseProofStepVariable<C, H>>,
43}
44
45/// Reference: https://github.com/Plonky3/Plonky3/blob/4809fa7bedd9ba8f6f5d3267b1592618e3776c57/fri/src/verifier.rs#L22
46#[derive(Clone)]
47pub struct FriChallenges<C: CircuitConfig> {
48    pub query_indices: Vec<Vec<C::Bit>>,
49    pub betas: Vec<Ext<C::F, C::EF>>,
50}
51
52#[derive(Clone)]
53pub struct TwoAdicPcsProofVariable<C: CircuitConfig, H: FieldHasherVariable<C>> {
54    pub fri_proof: FriProofVariable<C, H>,
55    pub query_openings: Vec<Vec<BatchOpeningVariable<C, H>>>,
56}
57
58#[derive(Clone)]
59pub struct BatchOpeningVariable<C: CircuitConfig, H: FieldHasherVariable<C>> {
60    pub opened_values: Vec<Vec<Vec<Felt<C::F>>>>,
61    pub opening_proof: Vec<H::Digest>,
62}
63
64#[derive(Clone)]
65pub struct TwoAdicPcsRoundVariable<C: CircuitConfig, H: FieldHasherVariable<C>> {
66    pub batch_commit: H::Digest,
67    pub domains_points_and_opens: Vec<TwoAdicPcsMatsVariable<C>>,
68}
69
70#[derive(Clone)]
71pub struct TwoAdicPcsMatsVariable<C: CircuitConfig> {
72    pub domain: TwoAdicMultiplicativeCoset<C::F>,
73    pub points: Vec<Ext<C::F, C::EF>>,
74    pub values: Vec<Vec<Ext<C::F, C::EF>>>,
75}
76
77impl<C: CircuitConfig<F = SC::Val>, SC: BabyBearFriConfigVariable<C>> VerifyingKeyVariable<C, SC> {
78    pub fn observe_into<Challenger>(&self, builder: &mut Builder<C>, challenger: &mut Challenger)
79    where
80        Challenger: CanObserveVariable<C, Felt<C::F>> + CanObserveVariable<C, SC::Digest>,
81    {
82        // Observe the commitment.
83        challenger.observe(builder, self.commitment);
84        // Observe the pc_start.
85        challenger.observe(builder, self.pc_start);
86    }
87
88    /// Hash the verifying key + prep domains into a single digest.
89    /// poseidon2( commit[0..8] || pc_start || prep_domains[N].{log_n, .size, .shift, .g})
90    pub fn hash(&self, builder: &mut Builder<C>) -> SC::Digest
91    where
92        C::F: TwoAdicField,
93        SC::Digest: IntoIterator<Item = Felt<C::F>>,
94    {
95        let prep_domains = self.chip_information.iter().map(|(_, domain, _)| domain);
96        let num_inputs = DIGEST_SIZE + 1 + (4 * prep_domains.len());
97        let mut inputs = Vec::with_capacity(num_inputs);
98        inputs.extend(self.commitment);
99        inputs.push(self.pc_start);
100        for domain in prep_domains {
101            inputs.push(builder.eval(C::F::from_canonical_usize(domain.log_n)));
102            let size = 1 << domain.log_n;
103            inputs.push(builder.eval(C::F::from_canonical_usize(size)));
104            let g = C::F::two_adic_generator(domain.log_n);
105            inputs.push(builder.eval(domain.shift));
106            inputs.push(builder.eval(g));
107        }
108
109        SC::hash(builder, &inputs)
110    }
111}