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