mina_tree/proofs/public_input/
prepared_statement.rs1use ark_ff::{BigInteger256, Zero};
2use mina_curves::pasta::{Fp, Fq};
3use mina_p2p_messages::v2::{
4    CompositionTypesBranchDataStableV1, PicklesBaseProofsVerifiedStableV1,
5};
6
7use crate::proofs::{
8    field::{CircuitVar, FieldWitness},
9    step::{FeatureFlags, OptFlag, Packed},
10    to_field_elements::ToFieldElements,
11    util::{four_u64_to_field, two_u64_to_field},
12};
13
14#[derive(Clone, Debug)]
15pub struct Plonk<F: FieldWitness> {
16    pub alpha: [u64; 2],
17    pub beta: [u64; 2],
18    pub gamma: [u64; 2],
19    pub zeta: [u64; 2],
20    pub zeta_to_srs_length: F::Shifting,
21    pub zeta_to_domain_size: F::Shifting,
22    pub perm: F::Shifting,
23    pub lookup: Option<[u64; 2]>,
24    pub feature_flags: FeatureFlags<bool>,
25}
26
27#[derive(Clone, Debug)]
28pub struct DeferredValues<F: FieldWitness> {
29    pub plonk: Plonk<F>,
30    pub combined_inner_product: F::Shifting,
31    pub b: F::Shifting,
32    pub xi: [u64; 2],
33    pub bulletproof_challenges: Vec<F>,
34    pub branch_data: CompositionTypesBranchDataStableV1,
35}
36
37#[derive(Clone, Debug)]
38pub struct ProofState {
39    pub deferred_values: DeferredValues<Fp>,
40    pub sponge_digest_before_evaluations: [u64; 4],
41    pub messages_for_next_wrap_proof: [u64; 4],
42}
43
44#[derive(Debug)]
45pub struct PreparedStatement {
46    pub proof_state: ProofState,
47    pub messages_for_next_step_proof: [u64; 4],
48}
49
50impl PreparedStatement {
51    pub fn to_public_input(&self, npublic_input: usize) -> anyhow::Result<Vec<Fq>> {
54        let PreparedStatement {
55            proof_state:
56                ProofState {
57                    deferred_values:
58                        DeferredValues {
59                            plonk:
60                                Plonk {
61                                    alpha,
62                                    beta,
63                                    gamma,
64                                    zeta,
65                                    zeta_to_srs_length,
66                                    zeta_to_domain_size,
67                                    perm,
68                                    lookup,
69                                    feature_flags,
70                                },
71                            combined_inner_product,
72                            b,
73                            xi,
74                            bulletproof_challenges,
75                            branch_data:
76                                CompositionTypesBranchDataStableV1 {
77                                    proofs_verified,
78                                    domain_log2,
79                                },
80                        },
81                    sponge_digest_before_evaluations,
82                    messages_for_next_wrap_proof,
83                },
84            messages_for_next_step_proof,
85        } = &self;
86
87        let mut fields: Vec<Fq> = Vec::with_capacity(npublic_input);
91
92        let to_fq = |fp: Fp| -> Fq {
93            let bigint: BigInteger256 = fp.into();
94            Fq::from(bigint) };
96
97        {
99            fields.push(to_fq(combined_inner_product.shifted));
100            fields.push(to_fq(b.shifted));
101            fields.push(to_fq(zeta_to_srs_length.shifted));
102            fields.push(to_fq(zeta_to_domain_size.shifted));
103            fields.push(to_fq(perm.shifted));
104        }
105
106        {
108            fields.push(two_u64_to_field(beta));
109            fields.push(two_u64_to_field(gamma));
110        }
111
112        {
114            fields.push(two_u64_to_field(alpha));
115            fields.push(two_u64_to_field(zeta));
116            fields.push(two_u64_to_field(xi));
117        }
118
119        {
121            fields.push(four_u64_to_field(sponge_digest_before_evaluations)?);
122            fields.push(four_u64_to_field(messages_for_next_wrap_proof)?);
123            fields.push(four_u64_to_field(messages_for_next_step_proof)?);
124        }
125
126        fields.extend(bulletproof_challenges.iter().copied().map(to_fq));
127
128        {
130            let proofs_verified = match proofs_verified {
132                PicklesBaseProofsVerifiedStableV1::N0 => 0b00,
133                PicklesBaseProofsVerifiedStableV1::N1 => 0b10,
134                PicklesBaseProofsVerifiedStableV1::N2 => 0b11,
135            };
136            let domain_log2: u8 = domain_log2.0.into();
138            let domain_log2: u64 = domain_log2 as u64;
139            let branch_data: u64 = (domain_log2 << 2) | proofs_verified;
140
141            fields.push(Fq::from(branch_data));
142        }
143
144        let lookup_value = lookup.as_ref().map(two_u64_to_field);
145
146        feature_flags.to_field_elements(&mut fields);
147
148        let FeatureFlags {
149            range_check0,
150            range_check1,
151            foreign_field_add: _,
152            foreign_field_mul,
153            xor,
154            rot,
155            lookup,
156            runtime_tables: _,
157        } = feature_flags;
158
159        let uses_lookup = [
161            range_check0,
162            range_check1,
163            foreign_field_mul,
164            xor,
165            rot,
166            lookup,
167        ]
168        .iter()
169        .any(|b| **b);
170
171        uses_lookup.to_field_elements(&mut fields);
172
173        if uses_lookup {
174            fields.push(lookup_value.unwrap_or(Fq::zero()));
175        } else {
176            fields.push(Fq::zero());
177        }
178
179        assert_eq!(fields.len(), npublic_input);
180
181        Ok(fields)
182    }
183
184    pub fn to_public_input_cvar(
185        &self,
186        hack_feature_flags: OptFlag,
187        npublic_input: usize,
188    ) -> anyhow::Result<Vec<Packed>> {
189        let PreparedStatement {
190            proof_state:
191                ProofState {
192                    deferred_values:
193                        DeferredValues {
194                            plonk:
195                                Plonk {
196                                    alpha,
197                                    beta,
198                                    gamma,
199                                    zeta,
200                                    zeta_to_srs_length,
201                                    zeta_to_domain_size,
202                                    perm,
203                                    lookup: _,
204                                    feature_flags: _,
205                                },
206                            combined_inner_product,
207                            b,
208                            xi,
209                            bulletproof_challenges,
210                            branch_data:
211                                CompositionTypesBranchDataStableV1 {
212                                    proofs_verified,
213                                    domain_log2,
214                                },
215                        },
216                    sponge_digest_before_evaluations,
217                    messages_for_next_wrap_proof,
218                },
219            messages_for_next_step_proof,
220        } = &self;
221
222        let mut fields: Vec<Packed> = Vec::with_capacity(npublic_input);
226
227        let to_fq = |fp: Fp| -> Fq {
228            let bigint: BigInteger256 = fp.into();
229            Fq::from(bigint) };
231
232        let var = |x| Packed::Field(CircuitVar::Var(x));
233        let bits = |n, x| Packed::PackedBits(CircuitVar::Var(x), n);
234
235        {
237            fields.push(var(to_fq(combined_inner_product.shifted)));
238            fields.push(var(to_fq(b.shifted)));
239            fields.push(var(to_fq(zeta_to_srs_length.shifted)));
240            fields.push(var(to_fq(zeta_to_domain_size.shifted)));
241            fields.push(var(to_fq(perm.shifted)));
242        }
243
244        {
246            fields.push(bits(128, two_u64_to_field(beta)));
247            fields.push(bits(128, two_u64_to_field(gamma)));
248        }
249
250        {
252            fields.push(bits(128, two_u64_to_field(alpha)));
253            fields.push(bits(128, two_u64_to_field(zeta)));
254            fields.push(bits(128, two_u64_to_field(xi)));
255        }
256
257        {
259            fields.push(bits(
260                255,
261                four_u64_to_field(sponge_digest_before_evaluations)?,
262            ));
263            fields.push(bits(255, four_u64_to_field(messages_for_next_wrap_proof)?));
264            fields.push(bits(255, four_u64_to_field(messages_for_next_step_proof)?));
265        }
266
267        fields.extend(
268            bulletproof_challenges
269                .iter()
270                .copied()
271                .map(|v| bits(128, to_fq(v))),
272        );
273
274        {
276            let proofs_verified = match proofs_verified {
278                PicklesBaseProofsVerifiedStableV1::N0 => 0b00,
279                PicklesBaseProofsVerifiedStableV1::N1 => 0b10,
280                PicklesBaseProofsVerifiedStableV1::N2 => 0b11,
281            };
282            let domain_log2: u8 = domain_log2.0.into();
284            let domain_log2: u64 = domain_log2 as u64;
285            let branch_data: u64 = (domain_log2 << 2) | proofs_verified;
286
287            fields.push(bits(10, Fq::from(branch_data)));
288        }
289
290        let zero = Fq::zero();
292        let circuit_var = match hack_feature_flags {
293            OptFlag::Yes => todo!(),
294            OptFlag::No => CircuitVar::Constant,
295            OptFlag::Maybe => CircuitVar::Var,
296        };
297        while fields.len() < npublic_input - 1 {
298            fields.push(Packed::PackedBits(circuit_var(zero), 1));
299        }
300        fields.push(Packed::PackedBits(circuit_var(zero), 128));
301
302        Ok(fields)
303    }
304}