mina_tree/proofs/public_input/
scalar_challenge.rs1use std::array::IntoIter;
2
3use ark_ff::{BigInteger256, Field};
4
5use crate::proofs::{field::FieldWitness, transaction::endos};
6
7#[derive(Clone, Debug)]
8pub struct ScalarChallenge {
9 pub inner: [u64; 2],
10}
11
12impl<F: FieldWitness> From<F> for ScalarChallenge {
13 fn from(value: F) -> Self {
14 let bigint: BigInteger256 = value.into();
15 let bigint = bigint.to_64x4();
16 Self::new(bigint[0], bigint[1])
17 }
18}
19
20impl From<[u64; 2]> for ScalarChallenge {
21 fn from(value: [u64; 2]) -> Self {
22 Self::new(value[0], value[1])
23 }
24}
25
26impl From<Vec<u64>> for ScalarChallenge {
27 fn from(value: Vec<u64>) -> Self {
28 Self::new(value[0], value[1])
29 }
30}
31
32struct ScalarChallengeBitsIterator {
33 inner: IntoIter<bool, 128>,
34}
35
36impl Iterator for ScalarChallengeBitsIterator {
37 type Item = (bool, bool);
38
39 fn next(&mut self) -> Option<Self::Item> {
40 let second = self.inner.next()?;
41 let first = self.inner.next()?;
42 Some((first, second))
43 }
44}
45
46impl ScalarChallenge {
47 pub fn new(a: u64, b: u64) -> Self {
48 Self { inner: [a, b] }
49 }
50
51 pub fn dummy() -> Self {
52 Self::new(1, 1)
53 }
54
55 fn iter_bits(&self) -> ScalarChallengeBitsIterator {
56 let a: u128 = self.inner[0] as u128;
57 let b: u128 = self.inner[1] as u128;
58 let num: u128 = (a | (b << 64)).reverse_bits();
59
60 let mut bits = [false; 128];
61 for (index, bit) in bits.iter_mut().enumerate() {
62 *bit = ((num >> index) & 1) != 0;
63 }
64
65 ScalarChallengeBitsIterator {
66 inner: bits.into_iter(),
67 }
68 }
69
70 pub fn to_field<F>(&self, endo: &F) -> F
73 where
74 F: Field + From<i32>,
75 {
76 let mut a: F = 2.into();
77 let mut b: F = 2.into();
78 let one: F = 1.into();
79 let neg_one: F = -one;
80
81 for (first, second) in self.iter_bits() {
82 let s = if first { one } else { neg_one };
83
84 a += a;
85 b += b;
86
87 if second {
88 a += s;
89 } else {
90 b += s;
91 }
92 }
93
94 (a * endo) + b
95 }
96
97 pub fn array_to_fields<F: FieldWitness, const N: usize>(array: &[F; N]) -> [F; N] {
98 let (_, endo) = endos::<F::Scalar>();
99 array.each_ref().map(|v| Self::from(*v).to_field(&endo))
100 }
101
102 pub fn limbs_to_field<F: FieldWitness>(limbs: &[u64; 2]) -> F {
103 let (_, endo) = endos::<F::Scalar>();
104 Self::from(*limbs).to_field(&endo)
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use crate::util::FpExt;
111
112 use super::*;
113
114 use mina_curves::pasta::{Fp, Fq};
115
116 #[cfg(target_family = "wasm")]
117 use wasm_bindgen_test::wasm_bindgen_test as test;
118
119 #[test]
120 fn test_fp_challenges() {
121 #[rustfmt::skip]
122 let scalar_challenges = [
123 ScalarChallenge::new(-6073566958339139610i64 as u64, -2081966045668129095i64 as u64),
124 ScalarChallenge::new(-7959424372843801919i64 as u64,4324727692349798413i64 as u64),
125 ScalarChallenge::new(5281407247363008654i64 as u64,-341126770839524452i64 as u64),
126 ScalarChallenge::new(-8793505104561934341i64 as u64,1149061412269814663i64 as u64),
127 ScalarChallenge::new(-6319682980234921909i64 as u64,-2993470668064492538i64 as u64),
128 ScalarChallenge::new(-4632520420895617322i64 as u64,-1043277042477928353i64 as u64),
129 ScalarChallenge::new(-6520172058534332359i64 as u64,-6056327257651418415i64 as u64),
130 ScalarChallenge::new(2243596438622148941i64 as u64,2765464070332650197i64 as u64),
131 ScalarChallenge::new(2003371658010473514i64 as u64,-4740690826649485901i64 as u64),
132 ScalarChallenge::new(4360179541971010175i64 as u64,-1774460476906845353i64 as u64),
133 ScalarChallenge::new(1218693385180536706i64 as u64,7371465240007863116i64 as u64),
134 ScalarChallenge::new(-4074108557518982675i64 as u64,-1941843029663935209i64 as u64),
135 ScalarChallenge::new(-443524479034963553i64 as u64,-6709701916849696870i64 as u64),
136 ScalarChallenge::new(-8471733636946508646i64 as u64,-7855667751781032417i64 as u64),
137 ScalarChallenge::new(-4458439752495496649i64 as u64,5085686095541820097i64 as u64),
138 ScalarChallenge::new(7895667244538374865i64 as u64,-7599583809327744882i64 as u64),
139 ];
140
141 let (_, endo) = crate::proofs::transaction::endos::<Fq>();
142
143 let challenges: Vec<_> = scalar_challenges
144 .iter()
145 .rev()
146 .map(|s| s.to_field(&endo).to_decimal())
147 .collect();
148
149 const OCAML_RESULTS: &[&str] = &[
150 "7064008822864728398858417698649153554618393735019982159700213736571223036821",
151 "21281073930096202884976340572605376014917627927607000098124963387126671667405",
152 "20034221077127088921131022285724504665904750595809121027858777196941115095595",
153 "18497339512896533967070595151637618702096421683793996188803218728257093313954",
154 "26091707259541979535386026279646546924481219402460945255985587200333895442426",
155 "26000802478877378291818950871303958371690312575800175603275158984631747112314",
156 "3542775955255721718735057551619208290322691095579511881465771193916627523656",
157 "26082193213255146858325625064941365409422644280364303832412501842706109482352",
158 "14045706980484410694469015017617110793948725477238650483822693423475791735584",
159 "19471582594431150457263082825199126200392919902939760347730982393598455884567",
160 "1326396224493213224809637465524487722432218763470273737330947122279510339127",
161 "17485742224041066720858261709734580297392897788368828400728418930917070940077",
162 "11369682275649236437578679786208728227049581168916414391705587421204991504471",
163 "5558430160842950378525019782179979114837605858253956740879954326712738838869",
164 "17514922848108718369845316737207968652832912751889238861905018424256428652733",
165 "11088960946452242729814251490831984807138805895197664788816609458265399565988",
166 ];
167
168 assert_eq!(challenges, OCAML_RESULTS);
169 }
170
171 #[test]
172 fn test_fq_challenges() {
173 #[rustfmt::skip]
174 let scalar_challenges = [
175 ScalarChallenge::new(7486980280913238963i64 as u64,4173194488927267133i64 as u64),
176 ScalarChallenge::new(-8437921285878338178i64 as u64,-2241273202573544127i64 as u64),
177 ScalarChallenge::new(7651331705457292674i64 as u64,-3583141513394030281i64 as u64),
178 ScalarChallenge::new(-3464302417307075879i64 as u64,-436261906098457727i64 as u64),
179 ScalarChallenge::new(8255044994932440761i64 as u64,5640094314955753085i64 as u64),
180 ScalarChallenge::new(-2513734760972484960i64 as u64,1161566061253204655i64 as u64),
181 ScalarChallenge::new(7525998242613288472i64 as u64,3436443803216159028i64 as u64),
182 ScalarChallenge::new(6809231383204761158i64 as u64,-1877195934091894696i64 as u64),
183 ScalarChallenge::new(-2746520749286704399i64 as u64,-3783224604272248786i64 as u64),
184 ScalarChallenge::new(-36686536733916892i64 as u64,-7835584350097226223i64 as u64),
185 ScalarChallenge::new(-487486487490201322i64 as u64,2756145684490201109i64 as u64),
186 ScalarChallenge::new(-2928903316653004982i64 as u64,346819656816504982i64 as u64),
187 ScalarChallenge::new(-6510054999844554738i64 as u64,5242613218253829938i64 as u64),
188 ScalarChallenge::new(-9192160905410203809i64 as u64,9069127704639200224i64 as u64),
189 ScalarChallenge::new(-1805085648820294365i64 as u64,4705625510417283644i64 as u64),
190 ];
191
192 let (_, endo) = crate::proofs::transaction::endos::<Fp>();
193
194 let challenges: Vec<_> = scalar_challenges
195 .iter()
196 .map(|s| s.to_field(&endo).to_decimal())
197 .collect();
198
199 const OCAML_RESULTS: &[&str] = &[
200 "18930573265662216159442494814184247548231007813972071269603851935535469568681",
201 "13262618632343563854609319990042165233884668386778849308201250967495466297892",
202 "3280133380740312520798484208652485449441154026649408650609268816997503996596",
203 "5974304366701279384657274575561097681967365179758505920855016184604375547845",
204 "3661423464518527108104215048163162714022670481055215775284279432335542360947",
205 "28186039308015693212526267835091480366420716733534501029059512929488448172803",
206 "2928242866467619037394221722592602237395615492823915494722307192257841920053",
207 "7996242790950647686981276345325562931441969146107262270102737887450525547679",
208 "21300612581975001967226090647975097001166598554510871181982133469971233105666",
209 "20608125931317303080428446946426401578478104508733856541747380631345253223759",
210 "20544136014497620836884335380316800592936676638960436539103183677666423950244",
211 "18427567011408397204090055018472561464711254957456387310196545464234121256500",
212 "17571157148266047799767015777008435938200309464425419775013145733714886071865",
213 "9174651000781852149559362347943707955252174789399970369305126738373271491014",
214 "2598585929268909637848366187420073930931414900720607825745008437243507445619",
215 ];
216
217 assert_eq!(challenges, OCAML_RESULTS);
218 }
219}