mina_tree/proofs/public_input/
messages.rs

1use std::str::FromStr;
2
3use crate::proofs::{
4    to_field_elements::ToFieldElements,
5    transaction::{checked_hash2, InnerCurve, PlonkVerificationKeyEvals},
6    witness::Witness,
7    VerifierIndex,
8};
9use ark_ec::short_weierstrass_jacobian::GroupAffine;
10use ark_ff::{BigInteger256, PrimeField};
11use mina_curves::pasta::{Fp, Fq, Pallas};
12use poly_commitment::PolyComm;
13
14use poseidon::hash::hash_fields;
15
16impl<'a> From<&'a VerifierIndex<Fq>> for PlonkVerificationKeyEvals<Fp> {
17    fn from(verifier_index: &'a VerifierIndex<Fq>) -> Self {
18        let to_curve = |v: &PolyComm<Pallas>| InnerCurve::of_affine(v.elems[0]);
19
20        Self {
21            sigma: verifier_index.sigma_comm.each_ref().map(to_curve),
22            coefficients: verifier_index.coefficients_comm.each_ref().map(to_curve),
23            generic: to_curve(&verifier_index.generic_comm),
24            psm: to_curve(&verifier_index.psm_comm),
25            complete_add: to_curve(&verifier_index.complete_add_comm),
26            mul: to_curve(&verifier_index.mul_comm),
27            emul: to_curve(&verifier_index.emul_comm),
28            endomul_scalar: to_curve(&verifier_index.endomul_scalar_comm),
29        }
30    }
31}
32
33/// Value of `Dummy.Ipa.Step.sg`
34/// TODO: Compute it instead of hardcoded values
35pub fn dummy_ipa_step_sg() -> (Fq, Fq) {
36    let fst = Fq::from_str(
37        "7157847628472818669877981787153253278122158060570991904823379281596325861730",
38    )
39    .unwrap();
40    let snd = Fq::from_str(
41        "9959746677904483136261451107528553963316638248277760417056251351537540061100",
42    )
43    .unwrap();
44
45    (fst, snd)
46}
47
48#[derive(Clone, Debug)]
49pub struct MessagesForNextWrapProof {
50    pub challenge_polynomial_commitment: InnerCurve<Fq>,
51    pub old_bulletproof_challenges: Vec<[Fq; 15]>,
52}
53
54impl MessagesForNextWrapProof {
55    /// Implementation of `hash_messages_for_next_wrap_proof`
56    /// <https://github.com/MinaProtocol/mina/blob/32a91613c388a71f875581ad72276e762242f802/src/lib/pickles/wrap_hack.ml#L50>
57    pub fn hash(&self) -> [u64; 4] {
58        let fields: Vec<Fq> = self.to_fields();
59        let field: Fq = hash_fields(&fields);
60
61        let bigint: BigInteger256 = field.into_repr();
62        bigint.to_64x4()
63    }
64
65    pub fn hash_checked(&self, w: &mut Witness<Fq>) -> [u64; 4] {
66        let fields: Vec<Fq> = self.to_fields();
67        let field: Fq = checked_hash2(&fields, w);
68
69        let bigint: BigInteger256 = field.into_repr();
70        bigint.to_64x4()
71    }
72
73    // TODO: De-duplicate with above
74    pub fn hash_checked3(&self, w: &mut Witness<Fq>) -> [u64; 4] {
75        let fields: Vec<Fq> = self.to_fields();
76        let field: Fq = crate::proofs::transaction::checked_hash3(&fields, w);
77
78        let bigint: BigInteger256 = field.into_repr();
79        bigint.to_64x4()
80    }
81
82    /// Implementation of `to_field_elements`
83    /// <https://github.com/MinaProtocol/mina/blob/32a91613c388a71f875581ad72276e762242f802/src/lib/pickles/composition_types/composition_types.ml#L356>
84    fn to_fields(&self) -> Vec<Fq> {
85        const NFIELDS: usize = 32;
86
87        let mut fields = Vec::with_capacity(NFIELDS);
88
89        let padding = 2usize
90            .checked_sub(self.old_bulletproof_challenges.len())
91            .expect("old_bulletproof_challenges must be of length <= 2");
92
93        for _ in 0..padding {
94            fields.extend_from_slice(&Self::dummy_padding());
95        }
96
97        for challenges in &self.old_bulletproof_challenges {
98            fields.extend_from_slice(challenges);
99        }
100
101        let GroupAffine { x, y, .. } = self.challenge_polynomial_commitment.to_affine();
102        fields.extend([x, y]);
103
104        assert_eq!(fields.len(), NFIELDS);
105
106        fields
107    }
108
109    /// Value of `Dummy.Ipa.Wrap.challenges_computed` here:
110    /// <https://github.com/MinaProtocol/mina/blob/32a91613c388a71f875581ad72276e762242f802/src/lib/pickles/wrap_hack.ml#L37>
111    ///
112    /// Those are constants but they are computed once at runtime in Mina.
113    /// TODO: Compute them instead of hardcoded values
114    pub fn dummy_padding() -> [Fq; 15] {
115        let f = |s| Fq::from_str(s).unwrap();
116
117        [
118            f("7048930911355605315581096707847688535149125545610393399193999502037687877674"),
119            f("5945064094191074331354717685811267396540107129706976521474145740173204364019"),
120            f("20315491820009986698838977727629973056499886675589920515484193128018854963801"),
121            f("375929229548289966749422550601268097380795636681684498450629863247980915833"),
122            f("19682218496321100578766622300447982536359891434050417209656101638029891689955"),
123            f("516598185966802396400068849903674663130928531697254466925429658676832606723"),
124            f("23729760760563685146228624125180554011222918208600079938584869191222807389336"),
125            f("11155777282048225577422475738306432747575091690354122761439079853293714987855"),
126            f("24977767586983413450834833875715786066408803952857478894197349635213480783870"),
127            f("2813347787496113574506936084777563965225649411532015639663405402448028142689"),
128            f("22626141769059119580550800305467929090916842064220293932303261732461616709448"),
129            f("18748107085456859495495117012311103043200881556220793307463332157672741458218"),
130            f("22196219950929618042921320796106738233125483954115679355597636800196070731081"),
131            f("13054421325261400802177761929986025883530654947859503505174678618288142017333"),
132            f("4799483385651443229337780097631636300491234601736019220096005875687579936102"),
133        ]
134    }
135}
136
137#[derive(Clone, Debug)]
138pub struct MessagesForNextStepProof<'a, AppState: ToFieldElements<Fp>> {
139    pub app_state: &'a AppState,
140    pub dlog_plonk_index: &'a PlonkVerificationKeyEvals<Fp>,
141    pub challenge_polynomial_commitments: Vec<InnerCurve<Fp>>,
142    pub old_bulletproof_challenges: Vec<[Fp; 16]>,
143}
144
145impl<AppState> MessagesForNextStepProof<'_, AppState>
146where
147    AppState: ToFieldElements<Fp>,
148{
149    /// Implementation of `hash_messages_for_next_step_proof`
150    /// <https://github.com/MinaProtocol/mina/blob/32a91613c388a71f875581ad72276e762242f802/src/lib/pickles/common.ml#L33>
151    pub fn hash(&self) -> [u64; 4] {
152        let fields: Vec<Fp> = self.to_fields();
153        let field: Fp = hash_fields(&fields);
154
155        let bigint: BigInteger256 = field.into_repr();
156        bigint.to_64x4()
157    }
158
159    /// Implementation of `to_field_elements`
160    /// <https://github.com/MinaProtocol/mina/blob/32a91613c388a71f875581ad72276e762242f802/src/lib/pickles/composition_types/composition_types.ml#L493>
161    fn to_fields(&self) -> Vec<Fp> {
162        const NFIELDS: usize = 93; // TODO: This is bigger with transactions
163
164        let mut fields = Vec::with_capacity(NFIELDS);
165
166        // Self::dlog_plonk_index
167        // Refactor with `src/account/account.rs`, this is the same code
168        {
169            let PlonkVerificationKeyEvals {
170                sigma,
171                coefficients,
172                generic,
173                psm,
174                complete_add,
175                mul,
176                emul,
177                endomul_scalar,
178            } = &self.dlog_plonk_index;
179
180            for GroupAffine { x, y, .. } in sigma.iter().map(InnerCurve::to_affine) {
181                fields.extend([x, y]);
182            }
183
184            for GroupAffine { x, y, .. } in coefficients.iter().map(InnerCurve::to_affine) {
185                fields.extend([x, y]);
186            }
187
188            let GroupAffine { x, y, .. } = generic.to_affine();
189            fields.extend([x, y]);
190
191            let GroupAffine { x, y, .. } = psm.to_affine();
192            fields.extend([x, y]);
193
194            let GroupAffine { x, y, .. } = complete_add.to_affine();
195            fields.extend([x, y]);
196
197            let GroupAffine { x, y, .. } = mul.to_affine();
198            fields.extend([x, y]);
199
200            let GroupAffine { x, y, .. } = emul.to_affine();
201            fields.extend([x, y]);
202
203            let GroupAffine { x, y, .. } = endomul_scalar.to_affine();
204            fields.extend([x, y]);
205        }
206
207        self.app_state.to_field_elements(&mut fields);
208
209        // Self::challenge_polynomial_commitments and Self::old_bulletproof_challenges
210        let commitments = &self.challenge_polynomial_commitments;
211        let old_challenges = &self.old_bulletproof_challenges;
212        for (commitments, old) in commitments.iter().zip(old_challenges) {
213            let GroupAffine { x, y, .. } = commitments.to_affine();
214            fields.extend([x, y]);
215            fields.extend_from_slice(old);
216        }
217
218        // assert!(fields.len() >= NFIELDS);
219
220        fields
221    }
222}