1use ark_ff::{fields::arithmetic::InvalidBigInt, BigInteger256};
2use malloc_size_of::MallocSizeOf;
3use rsexp::{OfSexp, SexpOf};
4use serde::{Deserialize, Serialize};
5
6#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, derive_more::From, derive_more::Into)]
7pub struct BigInt(BigInteger256);
8
9impl std::fmt::Debug for BigInt {
10 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
11 let Self(bigint) = self;
12 f.write_fmt(format_args!("BigInt({:?})", bigint.to_native()))
14 }
15}
16
17impl MallocSizeOf for BigInt {
18 fn size_of(&self, _ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
19 0
20 }
21}
22
23#[derive(Debug, thiserror::Error)]
24#[error("Invalid decimal number")]
25pub struct InvalidDecimalNumber;
26
27impl BigInt {
28 pub fn zero() -> Self {
29 mina_curves::pasta::Fp::from(0u64).into()
30 }
31
32 pub fn one() -> Self {
33 mina_curves::pasta::Fp::from(1u64).into()
34 }
35
36 pub fn to_field<F>(&self) -> Result<F, InvalidBigInt>
37 where
38 F: ark_ff::Field + TryFrom<BigInteger256, Error = InvalidBigInt>,
39 {
40 let Self(biginteger) = self;
41 F::try_from(*biginteger)
42 }
43
44 pub fn to_bytes(&self) -> [u8; 32] {
45 use ark_ff::ToBytes;
46 let mut bytes = std::io::Cursor::new([0u8; 32]);
47 self.0.write(&mut bytes).unwrap(); bytes.into_inner()
49 }
50
51 pub fn from_bytes(bytes: [u8; 32]) -> Self {
52 use ark_ff::FromBytes;
53 Self(BigInteger256::read(&bytes[..]).unwrap()) }
55
56 pub fn from_decimal(s: &str) -> Result<Self, InvalidDecimalNumber> {
57 num_bigint::BigInt::<4>::parse_bytes(s.as_bytes(), 10)
58 .map(|num| {
59 let mut bytes = num.to_bytes_be().1;
60 bytes.reverse();
61 bytes.resize(32, 0); BigInt::from_bytes(bytes.try_into().unwrap())
63 })
64 .ok_or(InvalidDecimalNumber)
65 }
66
67 pub fn to_decimal(&self) -> String {
68 let bigint: num_bigint::BigUint = self.0.into();
69 bigint.to_string()
70 }
71}
72
73impl AsRef<BigInteger256> for BigInt {
74 fn as_ref(&self) -> &BigInteger256 {
75 let Self(biginteger) = self;
76 biginteger
77 }
78}
79
80impl From<mina_curves::pasta::Fp> for BigInt {
81 fn from(field: mina_curves::pasta::Fp) -> Self {
82 use ark_ff::PrimeField;
83 Self(field.into_repr())
84 }
85}
86
87impl From<mina_curves::pasta::Fq> for BigInt {
88 fn from(field: mina_curves::pasta::Fq) -> Self {
89 use ark_ff::PrimeField;
90 Self(field.into_repr())
91 }
92}
93
94impl From<&mina_curves::pasta::Fp> for BigInt {
95 fn from(field: &mina_curves::pasta::Fp) -> Self {
96 use ark_ff::PrimeField;
97 Self(field.into_repr())
98 }
99}
100
101impl From<&mina_curves::pasta::Fq> for BigInt {
102 fn from(field: &mina_curves::pasta::Fq) -> Self {
103 use ark_ff::PrimeField;
104 Self(field.into_repr())
105 }
106}
107
108impl TryFrom<BigInt> for mina_curves::pasta::Fp {
109 type Error = <mina_curves::pasta::Fp as TryFrom<BigInteger256>>::Error;
110 fn try_from(bigint: BigInt) -> Result<Self, Self::Error> {
111 bigint.to_field()
112 }
113}
114
115impl TryFrom<BigInt> for mina_curves::pasta::Fq {
116 type Error = <mina_curves::pasta::Fq as TryFrom<BigInteger256>>::Error;
117 fn try_from(bigint: BigInt) -> Result<Self, Self::Error> {
118 bigint.to_field()
119 }
120}
121
122impl TryFrom<&BigInt> for mina_curves::pasta::Fp {
123 type Error = <mina_curves::pasta::Fp as TryFrom<BigInteger256>>::Error;
124 fn try_from(bigint: &BigInt) -> Result<Self, Self::Error> {
125 bigint.to_field()
126 }
127}
128
129impl TryFrom<&BigInt> for mina_curves::pasta::Fq {
130 type Error = <mina_curves::pasta::Fq as TryFrom<BigInteger256>>::Error;
131 fn try_from(bigint: &BigInt) -> Result<Self, Self::Error> {
132 bigint.to_field()
133 }
134}
135
136impl OfSexp for BigInt {
137 fn of_sexp(s: &rsexp::Sexp) -> Result<Self, rsexp::IntoSexpError>
138 where
139 Self: Sized,
140 {
141 let bytes = s.extract_atom("BigInt")?;
142 let hex_str = std::str::from_utf8(bytes).map_err(|_| {
143 rsexp::IntoSexpError::StringConversionError {
144 err: format!("Expected hex string with 0x prefix, got {bytes:?}"),
145 }
146 })?;
147
148 let hex_str = hex_str.strip_prefix("0x").unwrap_or(hex_str);
149
150 let padded_hex = format!("{:0>64}", hex_str);
151
152 if padded_hex.len() != 64 {
153 return Err(rsexp::IntoSexpError::StringConversionError {
154 err: format!("Expected 64-character hex string, got {padded_hex:?}"),
155 });
156 }
157
158 let byte_vec: Vec<u8> = (0..padded_hex.len())
159 .step_by(2)
160 .map(|i| u8::from_str_radix(&padded_hex[i..i + 2], 16))
161 .rev()
162 .collect::<Result<Vec<u8>, _>>()
163 .map_err(|_| rsexp::IntoSexpError::StringConversionError {
164 err: format!("Failed to parse hex string: {padded_hex:?}"),
165 })?;
166
167 Ok(BigInt::from_bytes(byte_vec.try_into().unwrap()))
168 }
169}
170
171impl SexpOf for BigInt {
172 fn sexp_of(&self) -> rsexp::Sexp {
173 use std::fmt::Write;
174 let byte_vec = self.to_bytes();
175 let hex_str = byte_vec
176 .iter()
177 .rev()
178 .fold("0x".to_string(), |mut output, byte| {
179 let _ = write!(output, "{byte:02X}");
180 output
181 });
182
183 rsexp::Sexp::Atom(hex_str.into_bytes())
184 }
185}
186
187impl binprot::BinProtRead for BigInt {
188 fn binprot_read<R: std::io::Read + ?Sized>(r: &mut R) -> Result<Self, binprot::Error>
189 where
190 Self: Sized,
191 {
192 use ark_ff::FromBytes;
193 Ok(Self(BigInteger256::read(r)?))
194 }
195}
196
197impl binprot::BinProtWrite for BigInt {
198 fn binprot_write<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
199 use ark_ff::ToBytes;
200 let Self(biginteger) = self;
201 biginteger.write(w)
202 }
203}
204
205impl Serialize for BigInt {
206 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
207 where
208 S: serde::Serializer,
209 {
210 if serializer.is_human_readable() {
211 let mut rev = self.to_bytes();
213 rev[..].reverse();
214 let mut hex = [0_u8; 32 * 2 + 2];
215 hex[..2].copy_from_slice(b"0x");
216 hex::encode_to_slice(rev, &mut hex[2..]).unwrap();
217 serializer.serialize_str(String::from_utf8_lossy(&hex).as_ref())
218 } else {
219 serializer.serialize_bytes(&self.to_bytes())
220 }
221 }
222}
223
224impl<'de> Deserialize<'de> for BigInt {
225 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
226 where
227 D: serde::Deserializer<'de>,
228 {
229 if deserializer.is_human_readable() {
230 struct V;
231 impl<'de> serde::de::Visitor<'de> for V {
232 type Value = Vec<u8>;
233
234 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
235 formatter.write_str("hex string or numeric string")
236 }
237
238 fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
239 where
240 E: serde::de::Error,
241 {
242 match v.strip_prefix("0x") {
243 Some(v) => hex::decode(v).map_err(|_| {
244 serde::de::Error::custom(format!("failed to decode hex str: {v}"))
245 }),
246 None => {
247 num_bigint::BigInt::<4>::parse_bytes(v.as_bytes(), 10)
249 .map(|num| {
250 let mut bytes = num.to_bytes_be().1;
251 bytes.reverse();
252 bytes.resize(32, 0); bytes.reverse();
254 bytes
255 })
256 .ok_or_else(|| {
257 serde::de::Error::custom(
258 "failed to parse decimal number".to_string(),
259 )
260 })
261 }
262 }
263 }
264
265 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
266 where
267 E: serde::de::Error,
268 {
269 self.visit_borrowed_str(v)
270 }
271 }
272 let mut v = deserializer.deserialize_str(V)?;
273 v.reverse();
274 v.try_into()
275 .map_err(|_| serde::de::Error::custom("failed to convert vec to array".to_string()))
276 } else {
277 struct V;
278 impl serde::de::Visitor<'_> for V {
279 type Value = [u8; 32];
280
281 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
282 formatter.write_str("sequence of 32 bytes")
283 }
284
285 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
286 where
287 E: serde::de::Error,
288 {
289 let v: [u8; 32] = v
290 .try_into()
291 .map_err(|_| serde::de::Error::custom("expecting 32 bytes".to_string()))?;
292 Ok(v)
293 }
294 }
295 deserializer.deserialize_bytes(V)
296 }
297 .map(Self::from_bytes)
298 }
299}
300
301impl mina_hasher::Hashable for BigInt {
302 type D = ();
303
304 fn to_roinput(&self) -> mina_hasher::ROInput {
305 mina_hasher::ROInput::new()
306 .append_field(self.to_field().expect("Failed to convert Hash into Fp"))
307 }
308
309 fn domain_string(_: Self::D) -> Option<String> {
310 None
311 }
312}
313
314#[cfg(test)]
315mod tests {
316 use binprot::{BinProtRead, BinProtWrite};
317
318 use super::BigInt;
319
320 fn to_binprot(v: &BigInt) -> Vec<u8> {
321 let mut w = Vec::new();
322 v.binprot_write(&mut w).unwrap();
323 w
324 }
325
326 fn from_binprot(mut b: &[u8]) -> BigInt {
327 BigInt::binprot_read(&mut b).unwrap()
328 }
329
330 fn from_byte(b: u8) -> BigInt {
331 BigInt::from_bytes([b; 32])
332 }
333
334 fn from_bytes<'a, I>(it: I) -> BigInt
335 where
336 I: IntoIterator<Item = &'a u8>,
337 I::IntoIter: Clone,
338 {
339 let mut bytes = [0; 32];
340 let it = it.into_iter().cycle();
341 bytes.iter_mut().zip(it).for_each(|(b, i)| *b = *i);
342 BigInt::from_bytes(bytes)
343 }
344
345 #[test]
346 fn serialize_bigint() {
347 let bigints = [
348 from_byte(0),
349 from_byte(1),
350 from_byte(0xff),
351 from_bytes(&[0, 1, 2, 3, 4]),
352 ];
353
354 for bigint in bigints {
355 let binprot = to_binprot(&bigint);
356 assert_eq!(binprot.as_slice(), bigint.to_bytes());
357 }
358 }
359
360 #[test]
361 fn deserialize_bigint() {
362 let bigints = [
363 from_byte(0),
364 from_byte(1),
365 from_byte(0xff),
366 from_bytes(&[0, 1, 2, 3, 4]),
367 ];
368
369 for bigint in bigints {
370 let deser: BigInt = from_binprot(&bigint.to_bytes());
371 assert_eq!(&bigint.0, &deser.0);
372 }
373 }
374
375 #[test]
376 fn to_json() {
377 let bigints = [
378 from_byte(0),
379 from_byte(1),
380 from_byte(0xff),
381 from_bytes(&[0, 1, 2, 3, 4]),
382 ];
383
384 for bigint in bigints {
385 let json = serde_json::to_string(&bigint).unwrap();
386 let mut v = bigint.to_bytes();
387 v.reverse();
388 let json_exp = format!(r#""0x{}""#, hex::encode(v));
389 assert_eq!(json, json_exp);
390 }
391 }
392
393 #[test]
394 fn from_json() {
395 let bigints = [
396 from_byte(0),
397 from_byte(1),
398 from_byte(0xff),
399 from_bytes(&[0, 1, 2, 3, 4]),
400 ];
401
402 for bigint in bigints {
403 let mut be = bigint.to_bytes();
404 be.reverse();
405 let json = format!(r#""0x{}""#, hex::encode(be.as_ref()));
406 let bigint_exp = serde_json::from_str(&json).unwrap();
407 assert_eq!(bigint, bigint_exp);
408 }
409 }
410
411 #[test]
412 fn from_numeric_string() {
413 let hex = "075bcd1500000000000000000000000000000000000000000000000000000000";
414 let deser: BigInt = serde_json::from_str(r#""123456789""#).unwrap();
415
416 let mut deser = deser.to_bytes();
417 deser.reverse();
418 let result_hex = hex::encode(deser);
419
420 assert_eq!(result_hex, hex.to_string());
421 }
422
423 #[test]
424 fn from_numeric_string_2() {
425 let rx =
426 r#""23298604903871047876308234794524469025218548053411207476198573374353464993732""#;
427 let s = r#""160863098041039391219472069845715442980741444645399750596310972807022542440""#;
428
429 let deser_rx: BigInt = serde_json::from_str(rx).unwrap();
430 let deser_s: BigInt = serde_json::from_str(s).unwrap();
431
432 println!("rx: {:?}", deser_rx);
433 println!("s: {:?}", deser_s);
434
435 let _ = deser_rx.to_field::<mina_curves::pasta::Fp>().unwrap();
436 println!("rx OK");
437 let _ = deser_s.to_field::<mina_curves::pasta::Fp>().unwrap();
438 println!("s OK");
439 }
440
441 use super::*;
442 use rsexp::Sexp;
443
444 #[test]
445 fn test_sexp_bigint() {
446 let hex_str = "0x248D179F4E92EA85C644CD99EF72187463B541D5F797943898C3D7A6CEEEC523";
447 let expected_array = [
448 0x98C3D7A6CEEEC523,
449 0x63B541D5F7979438,
450 0xC644CD99EF721874,
451 0x248D179F4E92EA85,
452 ];
453
454 let original_sexp = Sexp::Atom(hex_str.as_bytes().to_vec());
455
456 let result = BigInt::of_sexp(&original_sexp).expect("Failed to convert Sexp to BigInt");
457 let expected_result = BigInt(BigInteger256::from_64x4(expected_array));
458
459 assert_eq!(result, expected_result);
460
461 let produced_sexp = result.sexp_of();
462
463 assert_eq!(original_sexp, produced_sexp);
464 }
465}