plonk_wasm/arkworks/
pasta_fq.rs1use crate::arkworks::bigint_256::{self, WasmBigInteger256};
2use ark_ff::{
3 fields::{Field, PrimeField},
4 FftField, One, UniformRand, Zero,
5};
6use ark_poly::{EvaluationDomain, Radix2EvaluationDomain as Domain};
7use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
8use core::cmp::Ordering::{Equal, Greater, Less};
9use mina_curves::pasta::{
10 fields::{fft::FpParameters, fq::FqParameters as Fq_params},
11 Fq,
12};
13use num_bigint::BigUint;
14use rand::rngs::StdRng;
15use wasm_bindgen::{
16 convert::{FromWasmAbi, IntoWasmAbi, OptionFromWasmAbi, OptionIntoWasmAbi},
17 prelude::*,
18};
19
20#[repr(C)]
21#[derive(Clone, Copy, Debug)]
22pub struct WasmPastaFq(pub Fq);
23
24impl crate::wasm_flat_vector::FlatVectorElem for WasmPastaFq {
25 const FLATTENED_SIZE: usize = core::mem::size_of::<Fq>();
26 fn flatten(self) -> Vec<u8> {
27 let mut bytes: Vec<u8> = Vec::with_capacity(Self::FLATTENED_SIZE);
28 self.0.serialize_compressed(&mut bytes).unwrap();
29 bytes
30 }
31 fn unflatten(flat: Vec<u8>) -> Self {
32 WasmPastaFq(Fq::deserialize_compressed(flat.as_slice()).unwrap())
33 }
34}
35
36impl From<Fq> for WasmPastaFq {
37 fn from(x: Fq) -> Self {
38 WasmPastaFq(x)
39 }
40}
41
42impl From<WasmPastaFq> for Fq {
43 fn from(x: WasmPastaFq) -> Self {
44 x.0
45 }
46}
47
48impl<'a> From<&'a WasmPastaFq> for &'a Fq {
49 fn from(x: &'a WasmPastaFq) -> Self {
50 &x.0
51 }
52}
53
54impl wasm_bindgen::describe::WasmDescribe for WasmPastaFq {
55 fn describe() {
56 <Vec<u8> as wasm_bindgen::describe::WasmDescribe>::describe()
57 }
58}
59
60impl FromWasmAbi for WasmPastaFq {
61 type Abi = <Vec<u8> as FromWasmAbi>::Abi;
62 unsafe fn from_abi(js: Self::Abi) -> Self {
63 let bytes: Vec<u8> = FromWasmAbi::from_abi(js);
64 WasmPastaFq(Fq::deserialize_compressed(bytes.as_slice()).unwrap())
65 }
66}
67
68impl IntoWasmAbi for WasmPastaFq {
69 type Abi = <Vec<u8> as FromWasmAbi>::Abi;
70 fn into_abi(self) -> Self::Abi {
71 let mut bytes: Vec<u8> = vec![];
72 self.0.serialize_compressed(&mut bytes).unwrap();
73 bytes.into_abi()
74 }
75}
76
77impl OptionIntoWasmAbi for WasmPastaFq {
78 fn none() -> Self::Abi {
79 <Vec<u8> as OptionIntoWasmAbi>::none()
80 }
81}
82
83impl OptionFromWasmAbi for WasmPastaFq {
84 fn is_none(abi: &Self::Abi) -> bool {
85 <Vec<u8> as OptionFromWasmAbi>::is_none(abi)
86 }
87}
88
89#[wasm_bindgen]
90pub fn caml_pasta_fq_size_in_bits() -> isize {
91 Fq_params::MODULUS_BITS as isize
92}
93
94#[wasm_bindgen]
95pub fn caml_pasta_fq_size() -> WasmBigInteger256 {
96 WasmBigInteger256(Fq_params::MODULUS)
97}
98
99#[wasm_bindgen]
100pub fn caml_pasta_fq_add(x: WasmPastaFq, y: WasmPastaFq) -> WasmPastaFq {
101 WasmPastaFq(x.0 + y.0)
102}
103
104#[wasm_bindgen]
105pub fn caml_pasta_fq_sub(x: WasmPastaFq, y: WasmPastaFq) -> WasmPastaFq {
106 WasmPastaFq(x.0 - y.0)
107}
108
109#[wasm_bindgen]
110pub fn caml_pasta_fq_negate(x: WasmPastaFq) -> WasmPastaFq {
111 WasmPastaFq(-x.0)
112}
113
114#[wasm_bindgen]
115pub fn caml_pasta_fq_mul(x: WasmPastaFq, y: WasmPastaFq) -> WasmPastaFq {
116 WasmPastaFq(x.0 * y.0)
117}
118
119#[wasm_bindgen]
120pub fn caml_pasta_fq_div(x: WasmPastaFq, y: WasmPastaFq) -> WasmPastaFq {
121 WasmPastaFq(x.0 / y.0)
122}
123
124#[wasm_bindgen]
125pub fn caml_pasta_fq_inv(x: WasmPastaFq) -> Option<WasmPastaFq> {
126 x.0.inverse().map(WasmPastaFq)
127}
128
129#[wasm_bindgen]
130pub fn caml_pasta_fq_square(x: WasmPastaFq) -> WasmPastaFq {
131 WasmPastaFq(x.0.square())
132}
133
134#[wasm_bindgen]
135pub fn caml_pasta_fq_is_square(x: WasmPastaFq) -> bool {
136 let s = x.0.pow(Fq_params::MODULUS_MINUS_ONE_DIV_TWO);
137 s.is_zero() || s.is_one()
138}
139
140#[wasm_bindgen]
141pub fn caml_pasta_fq_sqrt(x: WasmPastaFq) -> Option<WasmPastaFq> {
142 x.0.sqrt().map(WasmPastaFq)
143}
144
145#[wasm_bindgen]
146pub fn caml_pasta_fq_of_int(i: i32) -> WasmPastaFq {
147 WasmPastaFq(Fq::from(i as u64))
148}
149
150#[wasm_bindgen]
151pub fn caml_pasta_fq_to_string(x: WasmPastaFq) -> String {
152 bigint_256::to_biguint(&x.0.into_bigint()).to_string()
153}
154
155#[wasm_bindgen]
156pub fn caml_pasta_fq_of_string(s: String) -> Result<WasmPastaFq, JsValue> {
157 let biguint = BigUint::parse_bytes(s.as_bytes(), 10)
158 .ok_or(JsValue::from_str("caml_pasta_fq_of_string"))?;
159
160 match Fq::from_bigint(bigint_256::of_biguint(&biguint)) {
161 Some(x) => Ok(x.into()),
162 None => Err(JsValue::from_str("caml_pasta_fq_of_string")),
163 }
164}
165
166#[wasm_bindgen]
167pub fn caml_pasta_fq_print(x: WasmPastaFq) {
168 println!("{}", bigint_256::to_biguint(&(x.0.into_bigint())));
169}
170
171#[wasm_bindgen]
172pub fn caml_pasta_fq_compare(x: WasmPastaFq, y: WasmPastaFq) -> i32 {
173 match x.0.cmp(&y.0) {
174 Less => -1,
175 Equal => 0,
176 Greater => 1,
177 }
178}
179
180#[wasm_bindgen]
181pub fn caml_pasta_fq_equal(x: WasmPastaFq, y: WasmPastaFq) -> bool {
182 x.0 == y.0
183}
184
185#[wasm_bindgen]
186pub fn caml_pasta_fq_random() -> WasmPastaFq {
187 WasmPastaFq(UniformRand::rand(&mut rand::thread_rng()))
188}
189
190#[wasm_bindgen]
191pub fn caml_pasta_fq_rng(i: i32) -> WasmPastaFq {
192 let i: u64 = (i as u32).into();
194 let mut rng: StdRng = rand::SeedableRng::seed_from_u64(i);
195 WasmPastaFq(UniformRand::rand(&mut rng))
196}
197
198#[wasm_bindgen]
199pub fn caml_pasta_fq_to_bigint(x: WasmPastaFq) -> WasmBigInteger256 {
200 WasmBigInteger256(x.0.into_bigint())
201}
202
203#[wasm_bindgen]
204pub fn caml_pasta_fq_of_bigint(x: WasmBigInteger256) -> Result<WasmPastaFq, JsValue> {
205 match Fq::from_bigint(x.0) {
206 Some(x) => Ok(x.into()),
207 None => Err(JsValue::from_str("caml_pasta_fq_of_bigint")),
208 }
209}
210
211#[wasm_bindgen]
212pub fn caml_pasta_fq_two_adic_root_of_unity() -> WasmPastaFq {
213 WasmPastaFq(<Fq as FftField>::TWO_ADIC_ROOT_OF_UNITY)
214}
215
216#[wasm_bindgen]
217pub fn caml_pasta_fq_domain_generator(log2_size: i32) -> WasmPastaFq {
218 match Domain::new(1 << log2_size) {
219 Some(x) => WasmPastaFq(x.group_gen),
220 None => panic!("caml_pasta_fq_domain_generator"),
221 }
222}
223
224#[wasm_bindgen]
225pub fn caml_pasta_fq_to_bytes(x: WasmPastaFq) -> Vec<u8> {
226 let len = core::mem::size_of::<Fq>();
227 let mut str: Vec<u8> = vec![0; len];
228 str.resize(len, 0);
229 let str_as_fq: *mut Fq = str.as_mut_ptr().cast::<Fq>();
230 unsafe {
231 *str_as_fq = x.0;
232 }
233 str
234}
235
236#[wasm_bindgen]
237pub fn caml_pasta_fq_of_bytes(x: &[u8]) -> WasmPastaFq {
238 let len = core::mem::size_of::<Fq>();
239 if x.len() != len {
240 panic!("caml_pasta_fq_of_bytes");
241 };
242 let x = unsafe { *(x.as_ptr() as *const Fq) };
243 WasmPastaFq(x)
244}
245
246#[wasm_bindgen]
247pub fn caml_pasta_fq_deep_copy(x: WasmPastaFq) -> WasmPastaFq {
248 x
249}