plonk_wasm/arkworks/
bigint_256.rs

1use ark_ff::{BigInt, BigInteger as ark_BigInteger, BigInteger256};
2use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Write};
3use core::{
4    cmp::Ordering::{Equal, Greater, Less},
5    convert::TryInto,
6};
7use num_bigint::BigUint;
8use wasm_bindgen::{
9    convert::{FromWasmAbi, IntoWasmAbi},
10    prelude::*,
11};
12
13//
14// Handy constants
15//
16
17const BIGINT256_NUM_BITS: i32 = 256;
18const BIGINT256_LIMB_BITS: i32 = 64;
19const BIGINT256_LIMB_BYTES: i32 = BIGINT256_LIMB_BITS / 8;
20const BIGINT256_NUM_LIMBS: i32 =
21    (BIGINT256_NUM_BITS + BIGINT256_LIMB_BITS - 1) / BIGINT256_LIMB_BITS;
22const BIGINT256_NUM_BYTES: usize = (BIGINT256_NUM_LIMBS as usize) * 8;
23
24pub struct WasmBigInteger256(pub BigInteger256);
25
26impl wasm_bindgen::describe::WasmDescribe for WasmBigInteger256 {
27    fn describe() {
28        <Vec<u8> as wasm_bindgen::describe::WasmDescribe>::describe()
29    }
30}
31
32impl FromWasmAbi for WasmBigInteger256 {
33    type Abi = <Vec<u8> as FromWasmAbi>::Abi;
34    unsafe fn from_abi(js: Self::Abi) -> Self {
35        let bytes: Vec<u8> = FromWasmAbi::from_abi(js);
36        // TODO this used FromBytes before arkworks 0.4.2, check serialization is consistent after update
37        WasmBigInteger256(BigInteger256::deserialize_compressed(bytes.as_slice()).unwrap())
38    }
39}
40
41impl IntoWasmAbi for WasmBigInteger256 {
42    type Abi = <Vec<u8> as FromWasmAbi>::Abi;
43    fn into_abi(self) -> Self::Abi {
44        let mut bytes: Vec<u8> = vec![];
45        bytes.write_all(self.0.to_bytes_le().as_slice()).unwrap();
46        bytes.into_abi()
47    }
48}
49
50pub fn to_biguint(x: &BigInteger256) -> BigUint {
51    let x_ = x.0.as_ptr() as *const u8;
52    let x_ = unsafe { core::slice::from_raw_parts(x_, BIGINT256_NUM_BYTES) };
53    num_bigint::BigUint::from_bytes_le(x_)
54}
55
56pub fn of_biguint(x: &BigUint) -> BigInteger256 {
57    let mut bytes = x.to_bytes_le();
58    bytes.resize(BIGINT256_NUM_BYTES, 0);
59    let limbs = bytes.as_ptr();
60    let limbs = limbs as *const [u64; BIGINT256_NUM_LIMBS as usize];
61    let limbs = unsafe { &(*limbs) };
62    BigInt(*limbs)
63}
64
65#[wasm_bindgen]
66pub fn caml_bigint_256_of_numeral(s: String, _len: u32, base: u32) -> WasmBigInteger256 {
67    match BigUint::parse_bytes(&s.into_bytes(), base) {
68        Some(data) => WasmBigInteger256(of_biguint(&data)),
69        None => panic!("caml_bigint_256_of_numeral"),
70    }
71}
72
73#[wasm_bindgen]
74pub fn caml_bigint_256_of_decimal_string(s: String) -> WasmBigInteger256 {
75    match BigUint::parse_bytes(&s.into_bytes(), 10) {
76        Some(data) => WasmBigInteger256(of_biguint(&data)),
77        None => panic!("caml_bigint_256_of_decimal_string"),
78    }
79}
80
81#[wasm_bindgen]
82pub fn caml_bigint_256_num_limbs() -> i32 {
83    BIGINT256_NUM_LIMBS
84}
85
86#[wasm_bindgen]
87pub fn caml_bigint_256_bytes_per_limb() -> i32 {
88    BIGINT256_LIMB_BYTES
89}
90
91#[wasm_bindgen]
92pub fn caml_bigint_256_div(x: WasmBigInteger256, y: WasmBigInteger256) -> WasmBigInteger256 {
93    let res: BigUint = to_biguint(&x.0) / to_biguint(&y.0);
94    WasmBigInteger256(of_biguint(&res))
95}
96
97#[wasm_bindgen]
98pub fn caml_bigint_256_compare(x: WasmBigInteger256, y: WasmBigInteger256) -> i8 {
99    match x.0.cmp(&y.0) {
100        Less => -1,
101        Equal => 0,
102        Greater => 1,
103    }
104}
105
106#[wasm_bindgen]
107pub fn caml_bigint_256_print(x: WasmBigInteger256) {
108    println!("{}", to_biguint(&x.0));
109}
110
111#[wasm_bindgen]
112pub fn caml_bigint_256_to_string(x: WasmBigInteger256) -> String {
113    to_biguint(&x.0).to_string()
114}
115
116#[wasm_bindgen]
117pub fn caml_bigint_256_test_bit(x: WasmBigInteger256, i: i32) -> bool {
118    match i.try_into() {
119        Ok(i) => x.0.get_bit(i),
120        Err(_) => panic!("caml_bigint_256_test_bit"),
121    }
122}
123
124#[wasm_bindgen]
125pub fn caml_bigint_256_to_bytes(x: WasmBigInteger256) -> Vec<u8> {
126    let mut serialized_bytes = vec![];
127    x.0.serialize_compressed(&mut serialized_bytes)
128        .expect("serialize failed");
129    serialized_bytes
130}
131
132#[wasm_bindgen]
133pub fn caml_bigint_256_of_bytes(x: &[u8]) -> WasmBigInteger256 {
134    let len = core::mem::size_of::<WasmBigInteger256>();
135    if x.len() != len {
136        panic!("caml_bigint_256_of_bytes");
137    };
138    // TODO this used FromBytes before arkworks 0.4.2, check serialization is consistent after update
139    WasmBigInteger256(
140        BigInteger256::deserialize_compressed(&mut &x[..]).expect("deserialization error"),
141    )
142}
143
144#[wasm_bindgen]
145pub fn caml_bigint_256_deep_copy(x: WasmBigInteger256) -> WasmBigInteger256 {
146    x
147}