sp1_recursion_circuit/machine/
witness.rs1use 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 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}