mina_hasher/
roinput.rs

1//! Random oracle input structures and algorithms
2//!
3//! Definition of random oracle input structure and
4//! methods for serializing into bytes and field elements
5
6use core::fmt::Error;
7
8use super::Hashable;
9use alloc::{vec, vec::Vec};
10use ark_ff::{BigInteger, PrimeField};
11use bitvec::{prelude::*, view::AsBits};
12use mina_curves::pasta::{Fp, Fq};
13use o1_utils::FieldHelpers;
14
15const SER_HEADER_SIZE: usize = 8; // total number of bytes for the header of the serialized ROInput
16const SINGLE_HEADER_SIZE: usize = 4; // number of bytes for each part of the header of the serialized ROInput
17
18/// Random oracle input structure
19///
20/// The random oracle input encapsulates the serialization format and methods using during hashing.
21///
22/// When implementing the [`Hashable`] trait to enable hashing for a type, you must implement
23/// its `to_roinput()` serialization method using the [`ROInput`] functions below.
24///
25/// The random oracle input structure is used (by generic code) to serialize the object into
26/// both a vector of `pasta::Fp` field elements and into a vector of bytes, depending on the situation.
27///
28/// Here is an example of how `ROInput` is used during the definition of the `Hashable` trait.
29///
30/// ```rust
31/// use mina_hasher::{Hashable, ROInput};
32/// use mina_curves::pasta::Fp;
33///
34/// #[derive(Clone)]
35/// pub struct MyExample {
36///     pub x: Fp,
37///     pub y: Fp,
38///     pub nonce: u64,
39/// }
40///
41/// impl Hashable for MyExample {
42///     type D = ();
43///
44///     fn to_roinput(&self) -> ROInput {
45///         ROInput::new()
46///             .append_field(self.x)
47///             .append_field(self.y)
48///             .append_u64(self.nonce)
49///     }
50///
51///     fn domain_string(_: Self::D) -> Option<String> {
52///         format!("MyExampleMainnet").into()
53///     }
54/// }
55/// ```
56/// **Details:** For technical reasons related to our proof system and performance,
57/// non-field-element members are serialized for signing differently than other types.
58/// Additionally, during signing all members of the random oracle input get serialized
59/// together in two different ways: both as *bytes* and as a vector of *field elements*.
60/// The random oracle input automates and encapsulates this complexity.
61#[derive(Default, Debug, Clone, PartialEq, Eq)]
62pub struct ROInput {
63    fields: Vec<Fp>,
64    bits: BitVec<u8>,
65}
66
67impl ROInput {
68    /// Create a new empty random oracle input
69    pub fn new() -> Self {
70        ROInput {
71            fields: vec![],
72            bits: BitVec::new(),
73        }
74    }
75
76    /// Append a `Hashable` input
77    pub fn append_hashable(self, input: &impl Hashable) -> Self {
78        self.append_roinput(input.to_roinput())
79    }
80
81    /// Append another random oracle input
82    pub fn append_roinput(mut self, mut roi: ROInput) -> Self {
83        self.fields.append(&mut roi.fields);
84        self.bits.extend(roi.bits);
85        self
86    }
87
88    /// Append a base field element
89    pub fn append_field(mut self, f: Fp) -> Self {
90        self.fields.push(f);
91        self
92    }
93
94    /// Append a scalar field element
95    pub fn append_scalar(mut self, s: Fq) -> Self {
96        // mina scalars are 255 bytes
97        let bytes = s.to_bytes();
98        let bits = &bytes.as_bits::<Lsb0>()[..Fq::MODULUS_BIT_SIZE as usize];
99        self.bits.extend(bits);
100        self
101    }
102
103    /// Append a single bit
104    pub fn append_bool(mut self, b: bool) -> Self {
105        self.bits.push(b);
106        self
107    }
108
109    /// Append bytes
110    pub fn append_bytes(mut self, bytes: &[u8]) -> Self {
111        self.bits.extend_from_bitslice(bytes.as_bits::<Lsb0>());
112        self
113    }
114
115    /// Append a 32-bit unsigned integer
116    pub fn append_u32(self, x: u32) -> Self {
117        self.append_bytes(&x.to_le_bytes())
118    }
119
120    /// Append a 64-bit unsigned integer
121    pub fn append_u64(self, x: u64) -> Self {
122        self.append_bytes(&x.to_le_bytes())
123    }
124
125    /// Serialize random oracle input to bytes
126    pub fn to_bytes(&self) -> Vec<u8> {
127        let mut bits: BitVec<u8> = self.fields.iter().fold(BitVec::new(), |mut acc, fe| {
128            acc.extend_from_bitslice(
129                &fe.to_bytes().as_bits::<Lsb0>()[..Fp::MODULUS_BIT_SIZE as usize],
130            );
131
132            acc
133        });
134
135        bits.extend(&self.bits);
136
137        bits.into()
138    }
139
140    /// Serialize random oracle input to vector of base field elements
141    pub fn to_fields(&self) -> Vec<Fp> {
142        let mut fields: Vec<Fp> = self.fields.clone();
143
144        let bits_as_fields =
145            self.bits
146                .chunks(Fp::MODULUS_BIT_SIZE as usize - 1)
147                .fold(vec![], |mut acc, chunk| {
148                    // Workaround: chunk.clone() does not appear to respect
149                    // the chunk's boundaries when it's not byte-aligned.
150                    //
151                    // That is,
152                    //
153                    //   let mut bv = chunk.clone().to_bitvec();
154                    //   bv.resize(B::size_in_bits(), false);
155                    //   fields.push(B::from_bytes(bv.into()));
156                    //
157                    // doesn't work.
158                    //
159                    // Instead we must do
160
161                    let mut bv = BitVec::<u8>::new();
162                    bv.resize(chunk.len(), false);
163                    bv.clone_from_bitslice(chunk);
164
165                    // extend to the size of a field;
166                    bv.resize(Fp::MODULUS_BIT_SIZE as usize, false);
167
168                    acc.push(
169                        Fp::from_bytes(&bv.into_vec())
170                            .expect("failed to create base field element"),
171                    );
172
173                    acc
174                });
175
176        fields.extend(bits_as_fields);
177
178        fields
179    }
180
181    /// Serialize the ROInput into bytes
182    pub fn serialize(&self) -> Vec<u8> {
183        // 4-byte LE field count, 4-byte LE bit count, then payload
184        let fields_len = self.fields.len() as u32;
185        let bits_len = self.bits.len() as u32;
186
187        let mut bytes = Vec::with_capacity(SER_HEADER_SIZE + self.to_bytes().len());
188        bytes.extend_from_slice(&fields_len.to_le_bytes());
189        bytes.extend_from_slice(&bits_len.to_le_bytes());
190        bytes.extend_from_slice(&self.to_bytes());
191        bytes
192    }
193
194    /// Deserialize a `ROInput` from bytes
195    pub fn deserialize(input: &[u8]) -> Result<Self, Error> {
196        if input.len() < SER_HEADER_SIZE {
197            return Err(Error);
198        }
199
200        // read back our two u32 little-endian lengths
201        let fields_len =
202            u32::from_le_bytes(input[0..SINGLE_HEADER_SIZE].try_into().unwrap()) as usize;
203        let bits_len = u32::from_le_bytes(
204            input[SINGLE_HEADER_SIZE..SER_HEADER_SIZE]
205                .try_into()
206                .unwrap(),
207        ) as usize;
208
209        // the rest is payload
210        let bits = input[SER_HEADER_SIZE..].view_bits::<Lsb0>();
211
212        // Check that the number of bytes is consistent with the expected lengths
213        let expected_len_bits = fields_len * Fp::MODULUS_BIT_SIZE as usize + bits_len;
214        // Round up to nearest multiple of 8
215        let expected_len = (expected_len_bits + 7) / 8 + SER_HEADER_SIZE;
216        if input.len() != expected_len {
217            return Err(Error);
218        }
219
220        // allocate space for exactly `fields_len` elements
221        let mut fields = Vec::with_capacity(fields_len);
222
223        for chunk in bits.chunks(Fp::MODULUS_BIT_SIZE as usize).take(fields_len) {
224            let bools: Vec<bool> = chunk.iter().by_vals().collect();
225            // conver little-endian bits to a big integer representation
226            let repr = <Fp as PrimeField>::BigInt::from_bits_le(&bools);
227            // convert to field element (reduces mod p)
228            let elt = Fp::from_bigint(repr).ok_or(Error)?;
229            fields.push(elt);
230        }
231
232        let remainder = &bits[fields_len * Fp::MODULUS_BIT_SIZE as usize..];
233        // Delete the final bits according to the bits length
234        let bits = remainder.iter().take(bits_len).collect::<BitVec<u8>>();
235
236        let roi = ROInput { fields, bits };
237
238        Ok(roi)
239    }
240}
241
242#[cfg(test)]
243mod tests {
244    use super::*;
245    use crate::{
246        alloc::string::{String, ToString},
247        Hashable,
248    };
249
250    #[test]
251    fn append_bool() {
252        let roi = ROInput::new().append_bool(true);
253        assert!(roi.bits.len() == 1);
254        assert!(roi.bits.as_raw_slice() == [0x01]);
255    }
256
257    #[test]
258    fn append_two_bits() {
259        let roi = ROInput::new().append_bool(false).append_bool(true);
260        assert!(roi.bits.len() == 2);
261        assert!(roi.bits.as_raw_slice() == [0x02]);
262    }
263
264    #[test]
265    fn append_five_bits() {
266        let roi = ROInput::new()
267            .append_bool(false)
268            .append_bool(true)
269            .append_bool(false)
270            .append_bool(false)
271            .append_bool(true);
272        assert!(roi.bits.len() == 5);
273        assert!(roi.bits.as_raw_slice() == [0x12]);
274    }
275
276    #[test]
277    fn append_byte() {
278        let roi = ROInput::new().append_bytes(&[0x01]);
279        assert!(roi.bits.len() == 8);
280        assert!(roi.bits.as_raw_slice() == [0x01]);
281    }
282
283    #[test]
284    fn append_two_bytes() {
285        let roi = ROInput::new().append_bytes(&[0x10, 0xac]);
286        assert!(roi.bits.len() == 16);
287        assert!(roi.bits.as_raw_slice() == [0x10, 0xac]);
288    }
289
290    #[test]
291    fn append_five_bytes() {
292        let roi = ROInput::new().append_bytes(&[0x10, 0xac, 0x01, 0xeb, 0xca]);
293        assert!(roi.bits.len() == 40);
294        assert!(roi.bits.as_raw_slice() == [0x10, 0xac, 0x01, 0xeb, 0xca]);
295    }
296
297    #[test]
298    fn append_scalar() {
299        let scalar =
300            Fq::from_hex("18b7ef420128e69623c0c0dcfa28d47a029d462720deb769d7b5dd6f17444216")
301                .expect("failed to create scalar");
302        let roi = ROInput::new().append_scalar(scalar);
303        assert_eq!(roi.bits.len(), 255);
304        assert_eq!(
305            roi.bits.as_raw_slice(),
306            [
307                0x18, 0xb7, 0xef, 0x42, 0x01, 0x28, 0xe6, 0x96, 0x23, 0xc0, 0xc0, 0xdc, 0xfa, 0x28,
308                0xd4, 0x7a, 0x02, 0x9d, 0x46, 0x27, 0x20, 0xde, 0xb7, 0x69, 0xd7, 0xb5, 0xdd, 0x6f,
309                0x17, 0x44, 0x42, 0x16
310            ]
311        );
312        assert_eq!(
313            roi.to_bytes(),
314            [
315                0x18, 0xb7, 0xef, 0x42, 0x01, 0x28, 0xe6, 0x96, 0x23, 0xc0, 0xc0, 0xdc, 0xfa, 0x28,
316                0xd4, 0x7a, 0x02, 0x9d, 0x46, 0x27, 0x20, 0xde, 0xb7, 0x69, 0xd7, 0xb5, 0xdd, 0x6f,
317                0x17, 0x44, 0x42, 0x16
318            ]
319        );
320    }
321
322    #[test]
323    fn append_scalar_and_byte() {
324        let scalar =
325            Fq::from_hex("18b7ef420128e69623c0c0dcfa28d47a029d462720deb769d7b5dd6f17444216")
326                .expect("failed to create scalar");
327        let roi = ROInput::new().append_scalar(scalar).append_bytes(&[0x01]);
328        assert!(roi.bits.len() == 263);
329        assert!(
330            roi.bits.as_raw_slice()
331                == [
332                    0x18, 0xb7, 0xef, 0x42, 0x01, 0x28, 0xe6, 0x96, 0x23, 0xc0, 0xc0, 0xdc, 0xfa,
333                    0x28, 0xd4, 0x7a, 0x02, 0x9d, 0x46, 0x27, 0x20, 0xde, 0xb7, 0x69, 0xd7, 0xb5,
334                    0xdd, 0x6f, 0x17, 0x44, 0x42, 0x96, 0x00
335                ]
336        );
337    }
338
339    #[test]
340    fn append_two_scalars() {
341        let scalar1 =
342            Fq::from_hex("18b7ef420128e69623c0c0dcfa28d47a029d462720deb769d7b5dd6f17444216")
343                .expect("failed to create scalar");
344        let scalar2 =
345            Fq::from_hex("a1b1e948835be341277548134e0effabdbcb95b742e8c5e967e9bf13eb4ae805")
346                .expect("failed to create scalar");
347        let roi = ROInput::new().append_scalar(scalar1).append_scalar(scalar2);
348        assert!(roi.bits.len() == 510);
349        assert!(
350            roi.bits.as_raw_slice()
351                == [
352                    0x18, 0xb7, 0xef, 0x42, 0x01, 0x28, 0xe6, 0x96, 0x23, 0xc0, 0xc0, 0xdc, 0xfa,
353                    0x28, 0xd4, 0x7a, 0x02, 0x9d, 0x46, 0x27, 0x20, 0xde, 0xb7, 0x69, 0xd7, 0xb5,
354                    0xdd, 0x6f, 0x17, 0x44, 0x42, 0x96, 0xd0, 0xd8, 0x74, 0xa4, 0xc1, 0xad, 0xf1,
355                    0xa0, 0x93, 0x3a, 0xa4, 0x09, 0x27, 0x87, 0xff, 0xd5, 0xed, 0xe5, 0xca, 0x5b,
356                    0x21, 0xf4, 0xe2, 0xf4, 0xb3, 0xf4, 0xdf, 0x89, 0x75, 0x25, 0xf4, 0x02
357                ]
358        );
359    }
360
361    #[test]
362    fn append_two_scalars_and_byte() {
363        let scalar1 =
364            Fq::from_hex("60db6f4f5b8ce1c7cb747fba9e324cc3268c7a6e3f43cd82d451ae99a7b2bd1f")
365                .expect("failed to create scalar");
366        let scalar2 =
367            Fq::from_hex("fe7775b106bceb58f3e23e5a4eb99f404b8ed8cf2afeef9c9d1800f12138cd07")
368                .expect("failed to create scalar");
369        let roi = ROInput::new()
370            .append_scalar(scalar1)
371            .append_bytes(&[0x2a])
372            .append_scalar(scalar2);
373        assert!(roi.bits.len() == 518);
374        assert!(
375            roi.bits.as_raw_slice()
376                == [
377                    0x60, 0xdb, 0x6f, 0x4f, 0x5b, 0x8c, 0xe1, 0xc7, 0xcb, 0x74, 0x7f, 0xba, 0x9e,
378                    0x32, 0x4c, 0xc3, 0x26, 0x8c, 0x7a, 0x6e, 0x3f, 0x43, 0xcd, 0x82, 0xd4, 0x51,
379                    0xae, 0x99, 0xa7, 0xb2, 0xbd, 0x1f, 0x15, 0xff, 0xbb, 0xba, 0x58, 0x03, 0xde,
380                    0x75, 0xac, 0x79, 0x71, 0x1f, 0x2d, 0xa7, 0xdc, 0x4f, 0xa0, 0x25, 0x47, 0xec,
381                    0x67, 0x15, 0xff, 0x77, 0xce, 0x4e, 0x0c, 0x80, 0xf8, 0x10, 0x9c, 0xe6, 0x03
382                ]
383        );
384    }
385
386    #[test]
387    fn append_u32() {
388        let roi = ROInput::new().append_u32(1984u32);
389        assert!(roi.bits.len() == 32);
390        assert!(roi.bits.as_raw_slice() == [0xc0, 0x07, 0x00, 0x00]);
391    }
392
393    #[test]
394    fn append_two_u32_and_bit() {
395        let roi = ROInput::new()
396            .append_u32(1729u32)
397            .append_bool(false)
398            .append_u32(u32::MAX);
399        assert!(roi.bits.len() == 65);
400        assert!(roi.bits.as_raw_slice() == [0xc1, 0x06, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01]);
401    }
402
403    #[test]
404    fn append_u64() {
405        let roi = ROInput::new().append_u64(6174u64);
406        assert!(roi.bits.len() == 64);
407        assert!(roi.bits.as_raw_slice() == [0x1e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
408    }
409
410    #[test]
411    fn append_two_u64_and_bits() {
412        let roi = ROInput::new()
413            .append_bool(true)
414            .append_u64(u64::MAX / 6174u64)
415            .append_bool(false)
416            .append_u64(u64::MAX / 1111u64);
417        assert!(roi.bits.len() == 130);
418        assert!(
419            roi.bits.as_raw_slice()
420                == [
421                    0xe1, 0x29, 0x89, 0xd6, 0xcb, 0x3a, 0x15, 0x00, 0x08, 0x17, 0xc4, 0x9b, 0x04,
422                    0xf4, 0xeb, 0x00, 0x00
423                ]
424        );
425    }
426
427    #[test]
428    fn all_1() {
429        let roi = ROInput::new()
430            .append_bool(true)
431            .append_scalar(
432                Fq::from_hex("01d1755db21c8cd2a9cf5a3436178da3d70f484cd4b4c8834b799921e7d7a102")
433                    .expect("failed to create scalar"),
434            )
435            .append_u64(18446744073709551557)
436            .append_bytes(&[0xba, 0xdc, 0x0f, 0xfe])
437            .append_scalar(
438                Fq::from_hex("e70187e9b125524489d0433da76fd8287fa652eaebde147b45fa0cd86f171810")
439                    .expect("failed to create scalar"),
440            )
441            .append_bool(false)
442            .append_u32(2147483647)
443            .append_bool(true);
444
445        assert!(roi.bits.len() == 641);
446        assert!(
447            roi.bits.as_raw_slice()
448                == [
449                    0x03, 0xa2, 0xeb, 0xba, 0x64, 0x39, 0x18, 0xa5, 0x53, 0x9f, 0xb5, 0x68, 0x6c,
450                    0x2e, 0x1a, 0x47, 0xaf, 0x1f, 0x90, 0x98, 0xa8, 0x69, 0x91, 0x07, 0x97, 0xf2,
451                    0x32, 0x43, 0xce, 0xaf, 0x43, 0x05, 0xc5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
452                    0xff, 0xba, 0xdc, 0x0f, 0xfe, 0xe7, 0x01, 0x87, 0xe9, 0xb1, 0x25, 0x52, 0x44,
453                    0x89, 0xd0, 0x43, 0x3d, 0xa7, 0x6f, 0xd8, 0x28, 0x7f, 0xa6, 0x52, 0xea, 0xeb,
454                    0xde, 0x14, 0x7b, 0x45, 0xfa, 0x0c, 0xd8, 0x6f, 0x17, 0x18, 0x10, 0xff, 0xff,
455                    0xff, 0x7f, 0x01
456                ]
457        );
458    }
459
460    #[test]
461    fn transaction_bits() {
462        let roi = ROInput::new()
463            .append_u64(1000000) // fee
464            .append_u64(1) // fee token
465            .append_bool(true) // fee payer pk odd
466            .append_u32(0) // nonce
467            .append_u32(u32::MAX) // valid_until
468            .append_bytes(&[0; 34]) // memo
469            .append_bool(false) // tags[0]
470            .append_bool(false) // tags[1]
471            .append_bool(false) // tags[2]
472            .append_bool(true) // sender pk odd
473            .append_bool(false) // receiver pk odd
474            .append_u64(1) // token_id
475            .append_u64(10000000000) // amount
476            .append_bool(false) // token_locked
477            .append_scalar(
478                Fq::from_hex("de217a3017ca0b7a278e75f63c09890e3894be532d8dbadd30a7d450055f6d2d")
479                    .expect("failed to create scalar"),
480            )
481            .append_bytes(&[0x01]);
482        assert_eq!(roi.bits.len(), 862);
483        assert_eq!(
484            roi.bits.as_raw_slice(),
485            [
486                0x40, 0x42, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
487                0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
488                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490                0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x02,
491                0x95, 0x00, 0x00, 0x00, 0x00, 0xef, 0x10, 0x3d, 0x98, 0x0b, 0xe5, 0x05, 0xbd, 0x13,
492                0xc7, 0x3a, 0x7b, 0x9e, 0x84, 0x44, 0x07, 0x1c, 0x4a, 0xdf, 0xa9, 0x96, 0x46, 0xdd,
493                0x6e, 0x98, 0x53, 0x6a, 0xa8, 0x82, 0xaf, 0xb6, 0x56, 0x00
494            ]
495        )
496    }
497
498    #[test]
499    fn append_field() {
500        let roi = ROInput::new().append_field(
501            Fp::from_hex("2eaedae42a7461d5952d27b97ecad068b698ebb94e8a0e4c45388bb613de7e08")
502                .expect("failed to create field"),
503        );
504
505        assert_eq!(
506            roi.to_bytes(),
507            [
508                0x2e, 0xae, 0xda, 0xe4, 0x2a, 0x74, 0x61, 0xd5, 0x95, 0x2d, 0x27, 0xb9, 0x7e, 0xca,
509                0xd0, 0x68, 0xb6, 0x98, 0xeb, 0xb9, 0x4e, 0x8a, 0x0e, 0x4c, 0x45, 0x38, 0x8b, 0xb6,
510                0x13, 0xde, 0x7e, 0x08
511            ]
512        );
513    }
514
515    #[test]
516    fn append_two_fields() {
517        let roi = ROInput::new()
518            .append_field(
519                Fp::from_hex("0cdaf334e9632268a5aa959c2781fb32bf45565fe244ae42c849d3fdc7c6441d")
520                    .expect("failed to create field"),
521            )
522            .append_field(
523                Fp::from_hex("2eaedae42a7461d5952d27b97ecad068b698ebb94e8a0e4c45388bb613de7e08")
524                    .expect("failed to create field"),
525            );
526
527        assert_eq!(
528            roi.to_bytes(),
529            [
530                0x0c, 0xda, 0xf3, 0x34, 0xe9, 0x63, 0x22, 0x68, 0xa5, 0xaa, 0x95, 0x9c, 0x27, 0x81,
531                0xfb, 0x32, 0xbf, 0x45, 0x56, 0x5f, 0xe2, 0x44, 0xae, 0x42, 0xc8, 0x49, 0xd3, 0xfd,
532                0xc7, 0xc6, 0x44, 0x1d, 0x17, 0x57, 0x6d, 0x72, 0x15, 0xba, 0xb0, 0xea, 0xca, 0x96,
533                0x93, 0x5c, 0x3f, 0x65, 0x68, 0x34, 0x5b, 0xcc, 0xf5, 0x5c, 0x27, 0x45, 0x07, 0xa6,
534                0x22, 0x9c, 0x45, 0xdb, 0x09, 0x6f, 0x3f, 0x04
535            ]
536        );
537    }
538
539    #[test]
540    fn append_three_fields() {
541        let roi = ROInput::new()
542            .append_field(
543                Fp::from_hex("1f3f142986041b54427aa2032632e34df2fa9bde9bce70c04c5034266619e529")
544                    .expect("failed to create field"),
545            )
546            .append_field(
547                Fp::from_hex("37f4433b85e753a91a1d79751645f1448954c433f9492e36a933ca7f3df61a04")
548                    .expect("failed to create field"),
549            )
550            .append_field(
551                Fp::from_hex("6cf4772d3e1aab98a2b514b73a4f6e0df1fb4f703ecfa762196b22c26da4341c")
552                    .expect("failed to create field"),
553            );
554
555        assert_eq!(
556            roi.to_bytes(),
557            [
558                0x1f, 0x3f, 0x14, 0x29, 0x86, 0x04, 0x1b, 0x54, 0x42, 0x7a, 0xa2, 0x03, 0x26, 0x32,
559                0xe3, 0x4d, 0xf2, 0xfa, 0x9b, 0xde, 0x9b, 0xce, 0x70, 0xc0, 0x4c, 0x50, 0x34, 0x26,
560                0x66, 0x19, 0xe5, 0xa9, 0x1b, 0xfa, 0xa1, 0x9d, 0xc2, 0xf3, 0xa9, 0x54, 0x8d, 0x8e,
561                0xbc, 0x3a, 0x8b, 0xa2, 0x78, 0xa2, 0x44, 0x2a, 0xe2, 0x99, 0xfc, 0x24, 0x17, 0x9b,
562                0xd4, 0x19, 0xe5, 0xbf, 0x1e, 0x7b, 0x0d, 0x02, 0x1b, 0xfd, 0x5d, 0x8b, 0x8f, 0xc6,
563                0x2a, 0xa6, 0x68, 0x2d, 0xc5, 0xad, 0xce, 0x93, 0x5b, 0x43, 0xfc, 0xfe, 0x13, 0x9c,
564                0xcf, 0xf3, 0xa9, 0x58, 0xc6, 0x9a, 0x88, 0x70, 0x1b, 0x29, 0x0d, 0x07
565            ]
566        );
567    }
568
569    #[test]
570    fn append_field_and_scalar() {
571        let roi = ROInput::new()
572            .append_field(
573                Fp::from_hex("64cde530327a36fcb88b6d769adca9b7c5d266e7d0042482203f3fd3a0d71721")
574                    .expect("failed to create field"),
575            )
576            .append_scalar(
577                Fq::from_hex("604355d0daa455db783fd7ee11c5bd9b04d67ba64c27c95bef95e379f98c6432")
578                    .expect("failed to create scalar"),
579            );
580
581        assert_eq!(
582            roi.to_bytes(),
583            [
584                0x64, 0xcd, 0xe5, 0x30, 0x32, 0x7a, 0x36, 0xfc, 0xb8, 0x8b, 0x6d, 0x76, 0x9a, 0xdc,
585                0xa9, 0xb7, 0xc5, 0xd2, 0x66, 0xe7, 0xd0, 0x04, 0x24, 0x82, 0x20, 0x3f, 0x3f, 0xd3,
586                0xa0, 0xd7, 0x17, 0x21, 0xb0, 0xa1, 0x2a, 0x68, 0x6d, 0xd2, 0xaa, 0x6d, 0xbc, 0x9f,
587                0x6b, 0xf7, 0x88, 0xe2, 0xde, 0x4d, 0x02, 0xeb, 0x3d, 0x53, 0xa6, 0x93, 0xe4, 0xad,
588                0xf7, 0xca, 0xf1, 0xbc, 0x7c, 0x46, 0x32, 0x19
589            ]
590        );
591    }
592
593    #[test]
594    fn append_field_bit_and_scalar() {
595        let roi = ROInput::new()
596            .append_field(
597                Fp::from_hex("d897c7a8b811d8acd3eeaa4adf42292802eed80031c2ad7c8989aea1fe94322c")
598                    .expect("failed to create field"),
599            )
600            .append_bool(false)
601            .append_scalar(
602                Fq::from_hex("79586cc6b8b53c8991b2abe0ca76508f056ca50f06836ce4d818c2ff73d42b28")
603                    .expect("failed to create scalar"),
604            );
605
606        assert_eq!(
607            roi.to_bytes(),
608            [
609                0xd8, 0x97, 0xc7, 0xa8, 0xb8, 0x11, 0xd8, 0xac, 0xd3, 0xee, 0xaa, 0x4a, 0xdf, 0x42,
610                0x29, 0x28, 0x02, 0xee, 0xd8, 0x00, 0x31, 0xc2, 0xad, 0x7c, 0x89, 0x89, 0xae, 0xa1,
611                0xfe, 0x94, 0x32, 0x2c, 0x79, 0x58, 0x6c, 0xc6, 0xb8, 0xb5, 0x3c, 0x89, 0x91, 0xb2,
612                0xab, 0xe0, 0xca, 0x76, 0x50, 0x8f, 0x05, 0x6c, 0xa5, 0x0f, 0x06, 0x83, 0x6c, 0xe4,
613                0xd8, 0x18, 0xc2, 0xff, 0x73, 0xd4, 0x2b, 0x28
614            ]
615        );
616    }
617
618    #[test]
619    fn to_bytes() {
620        let roi = ROInput::new()
621            .append_field(
622                Fp::from_hex("a5984f2bd00906f9a86e75bfb4b2c3625f1a0d1cfacc1501e8e82ae7041efc14")
623                    .expect("failed to create field"),
624            )
625            .append_field(
626                Fp::from_hex("8af0bc770d49a5b9fcabfcdd033bab470b2a211ef80b710efe71315cfa818c0a")
627                    .expect("failed to create field"),
628            )
629            .append_bool(false)
630            .append_u32(314u32)
631            .append_scalar(
632                Fq::from_hex("c23c43a23ddc1516578b0f0d81b93cdbbc97744acc697cfc8c5dfd01cc448323")
633                    .expect("failed to create scalar"),
634            );
635
636        assert_eq!(
637            roi.to_bytes(),
638            [
639                0xa5, 0x98, 0x4f, 0x2b, 0xd0, 0x09, 0x06, 0xf9, 0xa8, 0x6e, 0x75, 0xbf, 0xb4, 0xb2,
640                0xc3, 0x62, 0x5f, 0x1a, 0x0d, 0x1c, 0xfa, 0xcc, 0x15, 0x01, 0xe8, 0xe8, 0x2a, 0xe7,
641                0x04, 0x1e, 0xfc, 0x14, 0x45, 0x78, 0xde, 0xbb, 0x86, 0xa4, 0xd2, 0x5c, 0xfe, 0x55,
642                0xfe, 0xee, 0x81, 0x9d, 0xd5, 0xa3, 0x05, 0x95, 0x10, 0x0f, 0xfc, 0x85, 0x38, 0x07,
643                0xff, 0xb8, 0x18, 0x2e, 0xfd, 0x40, 0x46, 0x05, 0x9d, 0x00, 0x00, 0x00, 0x61, 0x9e,
644                0x21, 0xd1, 0x1e, 0xee, 0x0a, 0x8b, 0xab, 0xc5, 0x87, 0x86, 0xc0, 0x5c, 0x9e, 0x6d,
645                0xde, 0x4b, 0x3a, 0x25, 0xe6, 0x34, 0x3e, 0x7e, 0xc6, 0xae, 0xfe, 0x00, 0x66, 0xa2,
646                0xc1, 0x11
647            ]
648        );
649    }
650
651    #[test]
652    fn to_fields_1_scalar() {
653        let roi = ROInput::new().append_scalar(
654            Fq::from_hex("5d496dd8ff63f640c006887098092b16bc8c78504f84fa1ee3a0b54f85f0a625")
655                .expect("failed to create scalar"),
656        );
657
658        assert_eq!(
659            roi.to_bytes(),
660            [
661                0x5d, 0x49, 0x6d, 0xd8, 0xff, 0x63, 0xf6, 0x40, 0xc0, 0x06, 0x88, 0x70, 0x98, 0x09,
662                0x2b, 0x16, 0xbc, 0x8c, 0x78, 0x50, 0x4f, 0x84, 0xfa, 0x1e, 0xe3, 0xa0, 0xb5, 0x4f,
663                0x85, 0xf0, 0xa6, 0x25
664            ]
665        );
666
667        assert_eq!(
668            roi.to_fields(),
669            [
670                Fp::from_hex("5d496dd8ff63f640c006887098092b16bc8c78504f84fa1ee3a0b54f85f0a625")
671                    .expect("failed to create field"),
672                Fp::from_hex("0000000000000000000000000000000000000000000000000000000000000000")
673                    .expect("failed to create field"),
674            ]
675        );
676    }
677
678    #[test]
679    fn to_fields_1_scalar_2_bits() {
680        let roi = ROInput::new()
681            .append_scalar(
682                Fq::from_hex("e8a9961c8c417b0d0e3d7366f6b0e6ef90a6dad123070f715e8a9eaa02e47330")
683                    .expect("failed to create scalar"),
684            )
685            .append_bool(false)
686            .append_bool(true);
687
688        assert_eq!(
689            roi.to_bytes(),
690            [
691                0xe8, 0xa9, 0x96, 0x1c, 0x8c, 0x41, 0x7b, 0x0d, 0x0e, 0x3d, 0x73, 0x66, 0xf6, 0xb0,
692                0xe6, 0xef, 0x90, 0xa6, 0xda, 0xd1, 0x23, 0x07, 0x0f, 0x71, 0x5e, 0x8a, 0x9e, 0xaa,
693                0x02, 0xe4, 0x73, 0x30, 0x01
694            ]
695        );
696
697        assert_eq!(
698            roi.to_fields(),
699            [
700                Fp::from_hex("e8a9961c8c417b0d0e3d7366f6b0e6ef90a6dad123070f715e8a9eaa02e47330")
701                    .expect("failed to create field"),
702                Fp::from_hex("0400000000000000000000000000000000000000000000000000000000000000")
703                    .expect("failed to create field"),
704            ]
705        );
706    }
707
708    #[test]
709    fn to_fields_2_scalars() {
710        let roi = ROInput::new()
711            .append_scalar(
712                Fq::from_hex("e05c25d2c17ec20d6bc8fd21204af52808451076cff687407164a21d352ddd22")
713                    .expect("failed to create scalar"),
714            )
715            .append_scalar(
716                Fq::from_hex("c356dbb39478508818e0320dffa6c1ef512564366ec885ee2fc4d385dd36df0f")
717                    .expect("failed to create scalar"),
718            );
719
720        assert_eq!(
721            roi.to_bytes(),
722            [
723                0xe0, 0x5c, 0x25, 0xd2, 0xc1, 0x7e, 0xc2, 0x0d, 0x6b, 0xc8, 0xfd, 0x21, 0x20, 0x4a,
724                0xf5, 0x28, 0x08, 0x45, 0x10, 0x76, 0xcf, 0xf6, 0x87, 0x40, 0x71, 0x64, 0xa2, 0x1d,
725                0x35, 0x2d, 0xdd, 0xa2, 0x61, 0xab, 0xed, 0x59, 0x4a, 0x3c, 0x28, 0x44, 0x0c, 0x70,
726                0x99, 0x86, 0x7f, 0xd3, 0xe0, 0xf7, 0xa8, 0x12, 0x32, 0x1b, 0x37, 0xe4, 0x42, 0xf7,
727                0x17, 0xe2, 0xe9, 0xc2, 0x6e, 0x9b, 0xef, 0x07
728            ]
729        );
730
731        assert_eq!(
732            roi.to_fields(),
733            [
734                Fp::from_hex("e05c25d2c17ec20d6bc8fd21204af52808451076cff687407164a21d352ddd22")
735                    .expect("failed to create field"),
736                Fp::from_hex("86adb66729f1a01031c0651afe4d83dfa34ac86cdc900bdd5f88a70bbb6dbe1f")
737                    .expect("failed to create field"),
738                Fp::from_hex("0000000000000000000000000000000000000000000000000000000000000000")
739                    .expect("failed to create field"),
740            ]
741        );
742    }
743
744    #[test]
745    fn to_fields_2_bits_scalar_u32() {
746        let roi = ROInput::new()
747            .append_bool(true)
748            .append_bool(false)
749            .append_scalar(
750                Fq::from_hex("689634de233b06251a80ac7df64483922727757eea1adc6f0c8f184441cfe10d")
751                    .expect("failed to create scalar"),
752            )
753            .append_u32(834803);
754
755        assert_eq!(
756            roi.to_bytes(),
757            [
758                0xa1, 0x59, 0xd2, 0x78, 0x8f, 0xec, 0x18, 0x94, 0x68, 0x00, 0xb2, 0xf6, 0xd9, 0x13,
759                0x0d, 0x4a, 0x9e, 0x9c, 0xd4, 0xf9, 0xa9, 0x6b, 0x70, 0xbf, 0x31, 0x3c, 0x62, 0x10,
760                0x05, 0x3d, 0x87, 0x37, 0xe6, 0x79, 0x19, 0x00, 0x00
761            ]
762        );
763
764        assert_eq!(
765            roi.to_fields(),
766            [
767                Fp::from_hex("a159d2788fec18946800b2f6d9130d4a9e9cd4f9a96b70bf313c6210053d8737")
768                    .expect("failed to create field"),
769                Fp::from_hex("98e7650000000000000000000000000000000000000000000000000000000000")
770                    .expect("failed to create field"),
771            ]
772        );
773    }
774
775    #[test]
776    fn to_fields_2_bits_field_scalar() {
777        let roi = ROInput::new()
778            .append_bool(false)
779            .append_bool(true)
780            .append_field(
781                Fp::from_hex("90926b620ad09ed616d5df158504faed42928719c58ae619d9eccc062f920411")
782                    .expect("failed to create field"),
783            )
784            .append_scalar(
785                Fq::from_hex("689634de233b06251a80ac7df64483922727757eea1adc6f0c8f184441cfe10d")
786                    .expect("failed to create scalar"),
787            );
788
789        assert_eq!(
790            roi.to_bytes(),
791            [
792                0x90, 0x92, 0x6b, 0x62, 0x0a, 0xd0, 0x9e, 0xd6, 0x16, 0xd5, 0xdf, 0x15, 0x85, 0x04,
793                0xfa, 0xed, 0x42, 0x92, 0x87, 0x19, 0xc5, 0x8a, 0xe6, 0x19, 0xd9, 0xec, 0xcc, 0x06,
794                0x2f, 0x92, 0x04, 0x11, 0xd1, 0x2c, 0x69, 0xbc, 0x47, 0x76, 0x0c, 0x4a, 0x34, 0x00,
795                0x59, 0xfb, 0xec, 0x89, 0x06, 0x25, 0x4f, 0x4e, 0xea, 0xfc, 0xd4, 0x35, 0xb8, 0xdf,
796                0x18, 0x1e, 0x31, 0x88, 0x82, 0x9e, 0xc3, 0x1b
797            ]
798        );
799
800        assert_eq!(
801            roi.to_fields(),
802            [
803                Fp::from_hex("90926b620ad09ed616d5df158504faed42928719c58ae619d9eccc062f920411")
804                    .expect("failed to create field"),
805                Fp::from_hex("a259d2788fec18946800b2f6d9130d4a9e9cd4f9a96b70bf313c6210053d8737")
806                    .expect("failed to create field"),
807                Fp::from_hex("0000000000000000000000000000000000000000000000000000000000000000")
808                    .expect("failed to create field"),
809            ]
810        );
811    }
812
813    #[test]
814    fn transaction_test_1() {
815        let roi = ROInput::new()
816            .append_field(
817                Fp::from_hex("41203c6bbac14b357301e1f386d80f52123fd00f02197491b690bddfa742ca22")
818                    .expect("failed to create field"),
819            ) // fee payer
820            .append_field(
821                Fp::from_hex("992cdaf29ffe15b2bcea5d00e498ed4fffd117c197f0f98586e405f72ef88e00")
822                    .expect("failed to create field"),
823            ) // source
824            .append_field(
825                Fp::from_hex("3fba4fa71bce0dfdf709d827463036d6291458dfef772ff65e87bd6d1b1e062a")
826                    .expect("failed to create field"),
827            ) // receiver
828            .append_u64(1000000) // fee
829            .append_u64(1) // fee token
830            .append_bool(true) // fee payer pk odd
831            .append_u32(0) // nonce
832            .append_u32(u32::MAX) // valid_until
833            .append_bytes(&[0; 34]) // memo
834            .append_bool(false) // tags[0]
835            .append_bool(false) // tags[1]
836            .append_bool(false) // tags[2]
837            .append_bool(true) // sender pk odd
838            .append_bool(false) // receiver pk odd
839            .append_u64(1) // token_id
840            .append_u64(10000000000) // amount
841            .append_bool(false); // token_locked
842        assert_eq!(roi.bits.len() + roi.fields.len() * 255, 1364);
843        assert_eq!(
844            roi.to_bytes(),
845            [
846                0x41, 0x20, 0x3c, 0x6b, 0xba, 0xc1, 0x4b, 0x35, 0x73, 0x01, 0xe1, 0xf3, 0x86, 0xd8,
847                0x0f, 0x52, 0x12, 0x3f, 0xd0, 0x0f, 0x02, 0x19, 0x74, 0x91, 0xb6, 0x90, 0xbd, 0xdf,
848                0xa7, 0x42, 0xca, 0xa2, 0x4c, 0x16, 0x6d, 0xf9, 0x4f, 0xff, 0x0a, 0x59, 0x5e, 0xf5,
849                0x2e, 0x00, 0x72, 0xcc, 0xf6, 0xa7, 0xff, 0xe8, 0x8b, 0xe0, 0x4b, 0xf8, 0xfc, 0x42,
850                0x43, 0xf2, 0x82, 0x7b, 0x17, 0x7c, 0x47, 0xc0, 0x8f, 0xee, 0xd3, 0xe9, 0x86, 0x73,
851                0x43, 0xff, 0x7d, 0x02, 0xf6, 0x89, 0x11, 0x8c, 0x8d, 0x75, 0x0a, 0x05, 0xd6, 0xf7,
852                0xfb, 0xdd, 0x8b, 0xbd, 0xd7, 0x61, 0x6f, 0xdb, 0x86, 0x87, 0x81, 0x0a, 0x48, 0xe8,
853                0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
854                0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
855                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
856                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
857                0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x5f, 0xa0, 0x12, 0x00,
858                0x00, 0x00, 0x00
859            ]
860        );
861
862        assert_eq!(
863            roi.to_fields(),
864            [
865                Fp::from_hex("41203c6bbac14b357301e1f386d80f52123fd00f02197491b690bddfa742ca22")
866                    .expect("failed to create field"),
867                Fp::from_hex("992cdaf29ffe15b2bcea5d00e498ed4fffd117c197f0f98586e405f72ef88e00")
868                    .expect("failed to create field"),
869                Fp::from_hex("3fba4fa71bce0dfdf709d827463036d6291458dfef772ff65e87bd6d1b1e062a")
870                    .expect("failed to create field"),
871                Fp::from_hex("40420f0000000000010000000000000001000000feffffff0100000000000000")
872                    .expect("failed to create field"),
873                Fp::from_hex("0000000000000000000000000000000000000000000000000000400100000000")
874                    .expect("failed to create field"),
875                Fp::from_hex("00000000902f5009000000000000000000000000000000000000000000000000")
876                    .expect("failed to create field"),
877            ]
878        );
879    }
880
881    #[test]
882    fn nested_roinput_test() {
883        #[derive(Clone, Debug)]
884        struct A {
885            x: u32,
886            y: bool,
887            z: u32,
888        }
889
890        impl Hashable for A {
891            type D = ();
892
893            fn to_roinput(&self) -> ROInput {
894                ROInput::new()
895                    .append_u32(self.x)
896                    .append_bool(self.y)
897                    .append_u32(self.z)
898            }
899
900            fn domain_string(_: Self::D) -> Option<String> {
901                "A".to_string().into()
902            }
903        }
904
905        #[derive(Clone, Debug)]
906        struct B1 {
907            a: A,
908            b: u64,
909            c: bool,
910        }
911
912        impl Hashable for B1 {
913            type D = ();
914
915            fn to_roinput(&self) -> ROInput {
916                self.a.to_roinput().append_u64(self.b).append_bool(self.c)
917            }
918
919            fn domain_string(_: Self::D) -> Option<String> {
920                "B".to_string().into()
921            }
922        }
923
924        #[derive(Clone, Debug)]
925        struct B2 {
926            a: A,
927            b: u64,
928            c: bool,
929        }
930
931        impl Hashable for B2 {
932            type D = ();
933
934            fn to_roinput(&self) -> ROInput {
935                self.a
936                    .to_roinput()
937                    .append_roinput(ROInput::new().append_u64(self.b).append_bool(self.c))
938            }
939
940            fn domain_string(_: Self::D) -> Option<String> {
941                "B".to_string().into()
942            }
943        }
944
945        let a = A {
946            x: 16830533,
947            y: false,
948            z: 39827791,
949        };
950        let b1 = B1 {
951            a,
952            b: 124819,
953            c: true,
954        };
955        let b2 = B2 {
956            a: b1.a.clone(),
957            b: b1.b,
958            c: b1.c,
959        };
960
961        assert_eq!(b1.to_roinput(), b2.to_roinput());
962
963        let b2 = B2 {
964            a: b1.a.clone(),
965            b: b1.b,
966            c: false,
967        };
968        assert_ne!(b1.to_roinput(), b2.to_roinput());
969
970        let b2 = B2 {
971            a: b1.a.clone(),
972            b: b1.b + 1,
973            c: b1.c,
974        };
975        assert_ne!(b1.to_roinput(), b2.to_roinput());
976    }
977
978    #[test]
979    fn serialize_empty() {
980        let roi = ROInput::new();
981
982        let serialized = roi.serialize();
983
984        assert_eq!(
985            serialized,
986            vec![0; SER_HEADER_SIZE],
987            "Serialized empty ROInput should be zero bytes"
988        );
989
990        let deserialized_roi =
991            ROInput::deserialize(&serialized).expect("Failed to deserialize ROInput");
992        assert_eq!(
993            roi, deserialized_roi,
994            "Serialized and deserialized ROInput do not match"
995        );
996    }
997
998    #[test]
999    fn serialize_single_field() {
1000        let roi = ROInput::new().append_field(
1001            Fp::from_hex("41203c6bbac14b357301e1f386d80f52123fd00f02197491b690bddfa742ca22")
1002                .expect("failed to create field"),
1003        );
1004
1005        let serialized = roi.serialize();
1006        let expected_length = SER_HEADER_SIZE + 32; // 32 bytes for the field
1007        assert_eq!(
1008            serialized.len(),
1009            expected_length,
1010            "Serialized ROInput length mismatch"
1011        );
1012        assert_eq!(
1013            serialized,
1014            [
1015                0x01, 0x00, 0x00, 0x00, // Field count
1016                0x00, 0x00, 0x00, 0x00, // Bit count
1017                0x41, 0x20, 0x3c, 0x6b, 0xba, 0xc1, 0x4b, 0x35, 0x73, 0x01, 0xe1, 0xf3, 0x86, 0xd8,
1018                0x0f, 0x52, 0x12, 0x3f, 0xd0, 0x0f, 0x02, 0x19, 0x74, 0x91, 0xb6, 0x90, 0xbd, 0xdf,
1019                0xa7, 0x42, 0xca, 0x22
1020            ]
1021            .to_vec(),
1022            "Serialized ROInput does not match expected output"
1023        );
1024
1025        assert_eq!(
1026            roi,
1027            ROInput::deserialize(&serialized).expect("Failed to deserialize ROInput"),
1028            "Serialized and deserialized ROInput do not match"
1029        )
1030    }
1031
1032    #[test]
1033    fn serialize_single_bool() {
1034        let roi = ROInput::new().append_bool(true);
1035
1036        let serialized = roi.serialize();
1037        let expected_length = SER_HEADER_SIZE + 1; // 1 byte for the boolean
1038        assert_eq!(
1039            serialized.len(),
1040            expected_length,
1041            "Serialized ROInput length mismatch"
1042        );
1043        assert_eq!(
1044            serialized,
1045            [
1046                0x00, 0x00, 0x00, 0x00,
1047                0x01, 0x00, 0x00, 0x00,
1048                0x01  // Boolean value
1049            ]
1050            .to_vec(),
1051            "Serialized ROInput does not match expected output"
1052        );
1053
1054        assert_eq!(
1055            roi,
1056            ROInput::deserialize(&serialized).expect("Failed to deserialize ROInput"),
1057            "Serialized and deserialized ROInput do not match"
1058        );
1059    }
1060
1061    #[test]
1062    fn serialize_multiple_bools_length() {
1063        for i in 0..1024 {
1064            let roi = ROInput::new().append_bool(i % 2 == 0);
1065            let serialized = roi.serialize();
1066
1067            // Deserialize and check if it matches
1068            let deserialized_roi =
1069                ROInput::deserialize(&serialized).expect("Failed to deserialize ROInput");
1070            assert_eq!(
1071                roi, deserialized_roi,
1072                "Serialized and deserialized ROInput do not match for i={}",
1073                i
1074            );
1075        }
1076    }
1077
1078    #[test]
1079    fn deserialize_invalid() {
1080        let invalid_data = vec![0x01, 0x00, 0x00, 0x00]; // Invalid header, missing fields and bits
1081
1082        let result = ROInput::deserialize(&invalid_data);
1083        assert!(
1084            result.is_err(),
1085            "Deserialization should fail for invalid data"
1086        );
1087    }
1088
1089    #[test]
1090    fn deserialize_invalid_inconsistent_bitlen() {
1091        let invalid_data = vec![
1092            0x01, 0x00, 0x00, // Field count
1093            0x01, 0x00, 0x00, 0x00, // Bit count
1094            0x01, // Boolean value
1095                  // Missing bits for the boolean
1096        ];
1097
1098        let result = ROInput::deserialize(&invalid_data);
1099        assert!(
1100            result.is_err(),
1101            "Deserialization should fail for inconsistent bit length"
1102        );
1103    }
1104
1105    #[test]
1106    fn deserialize_invalid_message() {
1107        let msg = b"Test message for Mina compatibility".to_vec();
1108        let result = ROInput::deserialize(&msg);
1109        assert!(
1110            result.is_err(),
1111            "Deserialization should fail for invalid message format"
1112        );
1113    }
1114
1115    #[test]
1116    fn deserialize_invalid_fieldheader() {
1117        let invalid_data = vec![
1118            0x01, 0x00, 0x00, 0x00, // Field count
1119            0x01, 0x00, 0x00, 0x00, // Bit count
1120            // Incorrect number of bytes for field header
1121            0x01, 0x02, 0x03, 0x04, 0x01, // Boolean value
1122        ];
1123
1124        let result = ROInput::deserialize(&invalid_data);
1125        assert!(
1126            result.is_err(),
1127            "Deserialization should fail for overflow in field header"
1128        );
1129    }
1130
1131    #[test]
1132    fn serialize_tx() {
1133        let tx_roi = ROInput::new()
1134            .append_field(
1135                Fp::from_hex("41203c6bbac14b357301e1f386d80f52123fd00f02197491b690bddfa742ca22")
1136                    .expect("failed to create field"),
1137            )
1138            .append_field(
1139                Fp::from_hex("992cdaf29ffe15b2bcea5d00e498ed4fffd117c197f0f98586e405f72ef88e00")
1140                    .expect("failed to create field"),
1141            ) // source
1142            .append_field(
1143                Fp::from_hex("3fba4fa71bce0dfdf709d827463036d6291458dfef772ff65e87bd6d1b1e062a")
1144                    .expect("failed to create field"),
1145            ) // receiver
1146            .append_u64(1000000) // fee
1147            .append_u64(1) // fee token
1148            .append_bool(true) // fee payer pk odd
1149            .append_u32(0) // nonce
1150            .append_u32(u32::MAX) // valid_until
1151            .append_bytes(&[0; 34]) // memo
1152            .append_bool(false) // tags[0]
1153            .append_bool(false) // tags[1]
1154            .append_bool(false) // tags[2]
1155            .append_bool(true) // sender pk odd
1156            .append_bool(false) // receiver pk odd
1157            .append_u64(1) // token_id
1158            .append_u64(10000000000) // amount
1159            .append_bool(false); // token_locked
1160
1161        let tx_bytes = tx_roi.serialize();
1162
1163        let deserialized_roi =
1164            ROInput::deserialize(&tx_bytes).expect("Failed to deserialize ROInput");
1165
1166        assert_eq!(
1167            tx_roi, deserialized_roi,
1168            "Serialized and deserialized ROInput do not match"
1169        );
1170    }
1171}