Skip to main content

sp1_recursion_circuit/machine/
witness.rs

1use crate::{
2    hash::FieldHasher,
3    machine::{
4        MerkleProofVariable, SP1CompressWithVKeyWitnessValues, SP1CompressWithVKeyWitnessVariable,
5        SP1MerkleProofWitnessValues, SP1MerkleProofWitnessVariable, SP1ShapedWitnessVariable,
6    },
7};
8use slop_algebra::AbstractField;
9use slop_challenger::{DuplexChallenger, IopCtx};
10use slop_symmetric::Hash;
11use sp1_primitives::{SP1Field, SP1GlobalContext, SP1Perm};
12use std::{borrow::Borrow, marker::PhantomData};
13
14use super::{
15    InnerVal, SP1DeferredWitnessValues, SP1DeferredWitnessVariable, SP1NormalizeWitnessValues,
16    SP1RecursionWitnessVariable, SP1ShapedWitnessValues,
17};
18use crate::{
19    basefold::RecursiveBasefoldVerifier,
20    challenger::DuplexChallengerVariable,
21    hash::FieldHasherVariable,
22    jagged::RecursivePcsImpl,
23    shard::{MachineVerifyingKeyVariable, ShardProofVariable},
24    witness::{WitnessWriter, Witnessable},
25    CircuitConfig, SP1FieldConfigVariable,
26};
27use sp1_hypercube::{MachineVerifyingKey, MerkleProof, SP1PcsProofInner, ShardProof, Word};
28use sp1_recursion_compiler::{
29    config::InnerConfig,
30    ir::{Builder, Felt},
31};
32
33impl<C: CircuitConfig, T: Witnessable<C>> Witnessable<C> for Word<T> {
34    type WitnessVariable = Word<T::WitnessVariable>;
35
36    fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
37        Word(self.0.read(builder))
38    }
39
40    fn write(&self, witness: &mut impl WitnessWriter<C>) {
41        self.0.write(witness);
42    }
43}
44
45impl<C> Witnessable<C> for DuplexChallenger<SP1Field, SP1Perm, 16, 8>
46where
47    C: CircuitConfig,
48{
49    type WitnessVariable = DuplexChallengerVariable<C>;
50
51    fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
52        let sponge_state = self.sponge_state.read(builder);
53        let input_buffer = self.input_buffer.read(builder);
54        let output_buffer = self.output_buffer.read(builder);
55        DuplexChallengerVariable { sponge_state, input_buffer, output_buffer, marker: PhantomData }
56    }
57
58    fn write(&self, witness: &mut impl WitnessWriter<C>) {
59        self.sponge_state.write(witness);
60        self.input_buffer.write(witness);
61        self.output_buffer.write(witness);
62    }
63}
64
65impl<C, F, W, const DIGEST_ELEMENTS: usize> Witnessable<C> for Hash<F, W, DIGEST_ELEMENTS>
66where
67    C: CircuitConfig,
68    W: Witnessable<C>,
69{
70    type WitnessVariable = [W::WitnessVariable; DIGEST_ELEMENTS];
71
72    fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
73        let array: &[W; DIGEST_ELEMENTS] = self.borrow();
74        array.read(builder)
75    }
76
77    fn write(&self, witness: &mut impl WitnessWriter<C>) {
78        let array: &[W; DIGEST_ELEMENTS] = self.borrow();
79        array.write(witness);
80    }
81}
82
83pub type JC<C, SC> = RecursivePcsImpl<C, SC, RecursiveBasefoldVerifier<C, SC>>;
84
85impl Witnessable<InnerConfig> for SP1NormalizeWitnessValues<SP1GlobalContext, SP1PcsProofInner> {
86    type WitnessVariable = SP1RecursionWitnessVariable<InnerConfig, SP1GlobalContext>;
87
88    fn read(&self, builder: &mut Builder<InnerConfig>) -> Self::WitnessVariable {
89        let vk = self.vk.read(builder);
90        let shard_proofs = self.shard_proofs.read(builder);
91        let reconstruct_deferred_digest = self.reconstruct_deferred_digest.read(builder);
92        let is_complete = InnerVal::from_bool(self.is_complete).read(builder);
93        let vk_root = self.vk_root.read(builder);
94        let num_deferred_proofs = self.num_deferred_proofs.read(builder);
95        SP1RecursionWitnessVariable {
96            vk,
97            shard_proofs,
98            is_complete,
99            reconstruct_deferred_digest,
100            vk_root,
101            num_deferred_proofs,
102        }
103    }
104
105    fn write(&self, witness: &mut impl WitnessWriter<InnerConfig>) {
106        self.vk.write(witness);
107        self.shard_proofs.write(witness);
108        self.reconstruct_deferred_digest.write(witness);
109        self.is_complete.write(witness);
110        self.vk_root.write(witness);
111        self.num_deferred_proofs.write(witness);
112    }
113}
114
115impl<GC: IopCtx + SP1FieldConfigVariable<C>, C: CircuitConfig, Proof> Witnessable<C>
116    for SP1ShapedWitnessValues<GC, Proof>
117where
118    MachineVerifyingKey<GC>: Witnessable<C, WitnessVariable = MachineVerifyingKeyVariable<C, GC>>,
119    ShardProof<GC, Proof>: Witnessable<C, WitnessVariable = ShardProofVariable<C, GC>>,
120{
121    type WitnessVariable = SP1ShapedWitnessVariable<C, GC>;
122
123    fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
124        let vks_and_proofs = self.vks_and_proofs.read(builder);
125        let is_complete = InnerVal::from_bool(self.is_complete).read(builder);
126
127        SP1ShapedWitnessVariable { vks_and_proofs, is_complete }
128    }
129
130    fn write(&self, witness: &mut impl WitnessWriter<C>) {
131        self.vks_and_proofs.write(witness);
132        InnerVal::from_bool(self.is_complete).write(witness);
133    }
134}
135
136impl<C> Witnessable<C> for SP1DeferredWitnessValues<SP1GlobalContext, SP1PcsProofInner>
137where
138    C: CircuitConfig<Bit = Felt<InnerVal>>,
139{
140    type WitnessVariable = SP1DeferredWitnessVariable<C, SP1GlobalContext>;
141
142    fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
143        let vks_and_proofs = self.vks_and_proofs.read(builder);
144        let vk_merkle_data = self.vk_merkle_data.read(builder);
145        let start_reconstruct_deferred_digest =
146            self.start_reconstruct_deferred_digest.read(builder);
147        let sp1_vk_digest = self.sp1_vk_digest.read(builder);
148        let end_pc = self.end_pc.read(builder);
149        let proof_nonce = self.proof_nonce.read(builder);
150        let deferred_proof_index = self.deferred_proof_index.read(builder);
151
152        SP1DeferredWitnessVariable {
153            vks_and_proofs,
154            vk_merkle_data,
155            start_reconstruct_deferred_digest,
156            sp1_vk_digest,
157            end_pc,
158            proof_nonce,
159            deferred_proof_index,
160        }
161    }
162
163    fn write(&self, witness: &mut impl WitnessWriter<C>) {
164        self.vks_and_proofs.write(witness);
165        self.vk_merkle_data.write(witness);
166        self.start_reconstruct_deferred_digest.write(witness);
167        self.sp1_vk_digest.write(witness);
168        self.end_pc.write(witness);
169        self.proof_nonce.write(witness);
170        self.deferred_proof_index.write(witness);
171    }
172}
173
174impl<C: CircuitConfig, HV: FieldHasherVariable<C>> Witnessable<C> for MerkleProof<HV>
175where
176    HV::Digest: Witnessable<C, WitnessVariable = HV::DigestVariable>,
177{
178    type WitnessVariable = MerkleProofVariable<C, HV>;
179
180    fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
181        let mut bits = vec![];
182        let mut index = self.index;
183        for _ in 0..self.path.len() {
184            bits.push(index % 2 == 1);
185            index >>= 1;
186        }
187        bits.reverse();
188        let index_bits = bits.read(builder);
189        let path = self.path.read(builder);
190
191        MerkleProofVariable { index: index_bits, path }
192    }
193
194    fn write(&self, witness: &mut impl WitnessWriter<C>) {
195        let mut index = self.index;
196        let mut bits: Vec<bool> = vec![];
197        for _ in 0..self.path.len() {
198            bits.push(index % 2 == 1);
199            index >>= 1;
200        }
201        bits.reverse();
202        for bit in bits.iter() {
203            bit.write(witness);
204        }
205        self.path.write(witness);
206    }
207}
208
209impl<C: CircuitConfig, SC: SP1FieldConfigVariable<C>> Witnessable<C>
210    for SP1MerkleProofWitnessValues<SC>
211where
212    // This trait bound is redundant, but Rust-Analyzer is not able to infer it.
213    SC: FieldHasher<F = SP1Field>,
214    <SC as IopCtx>::Digest: Witnessable<C, WitnessVariable = SC::DigestVariable>,
215{
216    type WitnessVariable = SP1MerkleProofWitnessVariable<C, SC>;
217
218    fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
219        SP1MerkleProofWitnessVariable {
220            vk_merkle_proofs: self.vk_merkle_proofs.read(builder),
221            values: self.values.read(builder),
222            root: self.root.read(builder),
223        }
224    }
225
226    fn write(&self, witness: &mut impl WitnessWriter<C>) {
227        self.vk_merkle_proofs.write(witness);
228        self.values.write(witness);
229        self.root.write(witness);
230    }
231}
232
233impl<C: CircuitConfig, Proof> Witnessable<C> for SP1CompressWithVKeyWitnessValues<Proof>
234where
235    <SP1GlobalContext as IopCtx>::Digest: Witnessable<
236        C,
237        WitnessVariable = <SP1GlobalContext as FieldHasherVariable<C>>::DigestVariable,
238    >,
239    MachineVerifyingKey<SP1GlobalContext>:
240        Witnessable<C, WitnessVariable = MachineVerifyingKeyVariable<C, SP1GlobalContext>>,
241    ShardProof<SP1GlobalContext, Proof>:
242        Witnessable<C, WitnessVariable = ShardProofVariable<C, SP1GlobalContext>>,
243    SP1GlobalContext: SP1FieldConfigVariable<C>,
244{
245    type WitnessVariable = SP1CompressWithVKeyWitnessVariable<C, SP1GlobalContext>;
246
247    fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
248        SP1CompressWithVKeyWitnessVariable {
249            compress_var: self.compress_val.read(builder),
250            merkle_var: self.merkle_val.read(builder),
251        }
252    }
253
254    fn write(&self, witness: &mut impl WitnessWriter<C>) {
255        self.compress_val.write(witness);
256        self.merkle_val.write(witness);
257    }
258}