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