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 super::Hashable;
7use alloc::{vec, vec::Vec};
8use ark_ff::PrimeField;
9use bitvec::{prelude::*, view::AsBits};
10use mina_curves::pasta::{Fp, Fq};
11use o1_utils::FieldHelpers;
12
13/// Random oracle input structure
14///
15/// The random oracle input encapsulates the serialization format and methods using during hashing.
16///
17/// When implementing the [`Hashable`] trait to enable hashing for a type, you must implement
18/// its `to_roinput()` serialization method using the [`ROInput`] functions below.
19///
20/// The random oracle input structure is used (by generic code) to serialize the object into
21/// both a vector of `pasta::Fp` field elements and into a vector of bytes, depending on the situation.
22///
23/// Here is an example of how `ROInput` is used during the definition of the `Hashable` trait.
24///
25/// ```rust
26/// use mina_hasher::{Hashable, ROInput};
27/// use mina_curves::pasta::Fp;
28///
29/// #[derive(Clone)]
30/// pub struct MyExample {
31///     pub x: Fp,
32///     pub y: Fp,
33///     pub nonce: u64,
34/// }
35///
36/// impl Hashable for MyExample {
37///     type D = ();
38///
39///     fn to_roinput(&self) -> ROInput {
40///         ROInput::new()
41///             .append_field(self.x)
42///             .append_field(self.y)
43///             .append_u64(self.nonce)
44///     }
45///
46///     fn domain_string(_: Self::D) -> Option<String> {
47///         format!("MyExampleMainnet").into()
48///     }
49/// }
50/// ```
51/// **Details:** For technical reasons related to our proof system and performance,
52/// non-field-element members are serialized for signing differently than other types.
53/// Additionally, during signing all members of the random oracle input get serialized
54/// together in two different ways: both as *bytes* and as a vector of *field elements*.
55/// The random oracle input automates and encapsulates this complexity.
56#[derive(Default, Debug, Clone, PartialEq, Eq)]
57pub struct ROInput {
58    fields: Vec<Fp>,
59    bits: BitVec<u8>,
60}
61
62impl ROInput {
63    /// Create a new empty random oracle input
64    pub fn new() -> Self {
65        ROInput {
66            fields: vec![],
67            bits: BitVec::new(),
68        }
69    }
70
71    /// Append a `Hashable` input
72    pub fn append_hashable(self, input: &impl Hashable) -> Self {
73        self.append_roinput(input.to_roinput())
74    }
75
76    /// Append another random oracle input
77    pub fn append_roinput(mut self, mut roi: ROInput) -> Self {
78        self.fields.append(&mut roi.fields);
79        self.bits.extend(roi.bits);
80        self
81    }
82
83    /// Append a base field element
84    pub fn append_field(mut self, f: Fp) -> Self {
85        self.fields.push(f);
86        self
87    }
88
89    /// Append a scalar field element
90    pub fn append_scalar(mut self, s: Fq) -> Self {
91        // mina scalars are 255 bytes
92        let bytes = s.to_bytes();
93        let bits = &bytes.as_bits::<Lsb0>()[..Fq::MODULUS_BIT_SIZE as usize];
94        self.bits.extend(bits);
95        self
96    }
97
98    /// Append a single bit
99    pub fn append_bool(mut self, b: bool) -> Self {
100        self.bits.push(b);
101        self
102    }
103
104    /// Append bytes
105    pub fn append_bytes(mut self, bytes: &[u8]) -> Self {
106        self.bits.extend_from_bitslice(bytes.as_bits::<Lsb0>());
107        self
108    }
109
110    /// Append a 32-bit unsigned integer
111    pub fn append_u32(self, x: u32) -> Self {
112        self.append_bytes(&x.to_le_bytes())
113    }
114
115    /// Append a 64-bit unsigned integer
116    pub fn append_u64(self, x: u64) -> Self {
117        self.append_bytes(&x.to_le_bytes())
118    }
119
120    /// Serialize random oracle input to bytes
121    pub fn to_bytes(&self) -> Vec<u8> {
122        let mut bits: BitVec<u8> = self.fields.iter().fold(BitVec::new(), |mut acc, fe| {
123            acc.extend_from_bitslice(
124                &fe.to_bytes().as_bits::<Lsb0>()[..Fp::MODULUS_BIT_SIZE as usize],
125            );
126
127            acc
128        });
129
130        bits.extend(&self.bits);
131
132        bits.into()
133    }
134
135    /// Serialize random oracle input to vector of base field elements
136    pub fn to_fields(&self) -> Vec<Fp> {
137        let mut fields: Vec<Fp> = self.fields.clone();
138
139        let bits_as_fields =
140            self.bits
141                .chunks(Fp::MODULUS_BIT_SIZE as usize - 1)
142                .fold(vec![], |mut acc, chunk| {
143                    // Workaround: chunk.clone() does not appear to respect
144                    // the chunk's boundaries when it's not byte-aligned.
145                    //
146                    // That is,
147                    //
148                    //   let mut bv = chunk.clone().to_bitvec();
149                    //   bv.resize(B::size_in_bits(), false);
150                    //   fields.push(B::from_bytes(bv.into()));
151                    //
152                    // doesn't work.
153                    //
154                    // Instead we must do
155
156                    let mut bv = BitVec::<u8>::new();
157                    bv.resize(chunk.len(), false);
158                    bv.clone_from_bitslice(chunk);
159
160                    // extend to the size of a field;
161                    bv.resize(Fp::MODULUS_BIT_SIZE as usize, false);
162
163                    acc.push(
164                        Fp::from_bytes(&bv.into_vec())
165                            .expect("failed to create base field element"),
166                    );
167
168                    acc
169                });
170
171        fields.extend(bits_as_fields);
172
173        fields
174    }
175}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180    use crate::{
181        alloc::string::{String, ToString},
182        Hashable,
183    };
184
185    #[test]
186    fn append_bool() {
187        let roi = ROInput::new().append_bool(true);
188        assert!(roi.bits.len() == 1);
189        assert!(roi.bits.as_raw_slice() == [0x01]);
190    }
191
192    #[test]
193    fn append_two_bits() {
194        let roi = ROInput::new().append_bool(false).append_bool(true);
195        assert!(roi.bits.len() == 2);
196        assert!(roi.bits.as_raw_slice() == [0x02]);
197    }
198
199    #[test]
200    fn append_five_bits() {
201        let roi = ROInput::new()
202            .append_bool(false)
203            .append_bool(true)
204            .append_bool(false)
205            .append_bool(false)
206            .append_bool(true);
207        assert!(roi.bits.len() == 5);
208        assert!(roi.bits.as_raw_slice() == [0x12]);
209    }
210
211    #[test]
212    fn append_byte() {
213        let roi = ROInput::new().append_bytes(&[0x01]);
214        assert!(roi.bits.len() == 8);
215        assert!(roi.bits.as_raw_slice() == [0x01]);
216    }
217
218    #[test]
219    fn append_two_bytes() {
220        let roi = ROInput::new().append_bytes(&[0x10, 0xac]);
221        assert!(roi.bits.len() == 16);
222        assert!(roi.bits.as_raw_slice() == [0x10, 0xac]);
223    }
224
225    #[test]
226    fn append_five_bytes() {
227        let roi = ROInput::new().append_bytes(&[0x10, 0xac, 0x01, 0xeb, 0xca]);
228        assert!(roi.bits.len() == 40);
229        assert!(roi.bits.as_raw_slice() == [0x10, 0xac, 0x01, 0xeb, 0xca]);
230    }
231
232    #[test]
233    fn append_scalar() {
234        let scalar =
235            Fq::from_hex("18b7ef420128e69623c0c0dcfa28d47a029d462720deb769d7b5dd6f17444216")
236                .expect("failed to create scalar");
237        let roi = ROInput::new().append_scalar(scalar);
238        assert_eq!(roi.bits.len(), 255);
239        assert_eq!(
240            roi.bits.as_raw_slice(),
241            [
242                0x18, 0xb7, 0xef, 0x42, 0x01, 0x28, 0xe6, 0x96, 0x23, 0xc0, 0xc0, 0xdc, 0xfa, 0x28,
243                0xd4, 0x7a, 0x02, 0x9d, 0x46, 0x27, 0x20, 0xde, 0xb7, 0x69, 0xd7, 0xb5, 0xdd, 0x6f,
244                0x17, 0x44, 0x42, 0x16
245            ]
246        );
247        assert_eq!(
248            roi.to_bytes(),
249            [
250                0x18, 0xb7, 0xef, 0x42, 0x01, 0x28, 0xe6, 0x96, 0x23, 0xc0, 0xc0, 0xdc, 0xfa, 0x28,
251                0xd4, 0x7a, 0x02, 0x9d, 0x46, 0x27, 0x20, 0xde, 0xb7, 0x69, 0xd7, 0xb5, 0xdd, 0x6f,
252                0x17, 0x44, 0x42, 0x16
253            ]
254        );
255    }
256
257    #[test]
258    fn append_scalar_and_byte() {
259        let scalar =
260            Fq::from_hex("18b7ef420128e69623c0c0dcfa28d47a029d462720deb769d7b5dd6f17444216")
261                .expect("failed to create scalar");
262        let roi = ROInput::new().append_scalar(scalar).append_bytes(&[0x01]);
263        assert!(roi.bits.len() == 263);
264        assert!(
265            roi.bits.as_raw_slice()
266                == [
267                    0x18, 0xb7, 0xef, 0x42, 0x01, 0x28, 0xe6, 0x96, 0x23, 0xc0, 0xc0, 0xdc, 0xfa,
268                    0x28, 0xd4, 0x7a, 0x02, 0x9d, 0x46, 0x27, 0x20, 0xde, 0xb7, 0x69, 0xd7, 0xb5,
269                    0xdd, 0x6f, 0x17, 0x44, 0x42, 0x96, 0x00
270                ]
271        );
272    }
273
274    #[test]
275    fn append_two_scalars() {
276        let scalar1 =
277            Fq::from_hex("18b7ef420128e69623c0c0dcfa28d47a029d462720deb769d7b5dd6f17444216")
278                .expect("failed to create scalar");
279        let scalar2 =
280            Fq::from_hex("a1b1e948835be341277548134e0effabdbcb95b742e8c5e967e9bf13eb4ae805")
281                .expect("failed to create scalar");
282        let roi = ROInput::new().append_scalar(scalar1).append_scalar(scalar2);
283        assert!(roi.bits.len() == 510);
284        assert!(
285            roi.bits.as_raw_slice()
286                == [
287                    0x18, 0xb7, 0xef, 0x42, 0x01, 0x28, 0xe6, 0x96, 0x23, 0xc0, 0xc0, 0xdc, 0xfa,
288                    0x28, 0xd4, 0x7a, 0x02, 0x9d, 0x46, 0x27, 0x20, 0xde, 0xb7, 0x69, 0xd7, 0xb5,
289                    0xdd, 0x6f, 0x17, 0x44, 0x42, 0x96, 0xd0, 0xd8, 0x74, 0xa4, 0xc1, 0xad, 0xf1,
290                    0xa0, 0x93, 0x3a, 0xa4, 0x09, 0x27, 0x87, 0xff, 0xd5, 0xed, 0xe5, 0xca, 0x5b,
291                    0x21, 0xf4, 0xe2, 0xf4, 0xb3, 0xf4, 0xdf, 0x89, 0x75, 0x25, 0xf4, 0x02
292                ]
293        );
294    }
295
296    #[test]
297    fn append_two_scalars_and_byte() {
298        let scalar1 =
299            Fq::from_hex("60db6f4f5b8ce1c7cb747fba9e324cc3268c7a6e3f43cd82d451ae99a7b2bd1f")
300                .expect("failed to create scalar");
301        let scalar2 =
302            Fq::from_hex("fe7775b106bceb58f3e23e5a4eb99f404b8ed8cf2afeef9c9d1800f12138cd07")
303                .expect("failed to create scalar");
304        let roi = ROInput::new()
305            .append_scalar(scalar1)
306            .append_bytes(&[0x2a])
307            .append_scalar(scalar2);
308        assert!(roi.bits.len() == 518);
309        assert!(
310            roi.bits.as_raw_slice()
311                == [
312                    0x60, 0xdb, 0x6f, 0x4f, 0x5b, 0x8c, 0xe1, 0xc7, 0xcb, 0x74, 0x7f, 0xba, 0x9e,
313                    0x32, 0x4c, 0xc3, 0x26, 0x8c, 0x7a, 0x6e, 0x3f, 0x43, 0xcd, 0x82, 0xd4, 0x51,
314                    0xae, 0x99, 0xa7, 0xb2, 0xbd, 0x1f, 0x15, 0xff, 0xbb, 0xba, 0x58, 0x03, 0xde,
315                    0x75, 0xac, 0x79, 0x71, 0x1f, 0x2d, 0xa7, 0xdc, 0x4f, 0xa0, 0x25, 0x47, 0xec,
316                    0x67, 0x15, 0xff, 0x77, 0xce, 0x4e, 0x0c, 0x80, 0xf8, 0x10, 0x9c, 0xe6, 0x03
317                ]
318        );
319    }
320
321    #[test]
322    fn append_u32() {
323        let roi = ROInput::new().append_u32(1984u32);
324        assert!(roi.bits.len() == 32);
325        assert!(roi.bits.as_raw_slice() == [0xc0, 0x07, 0x00, 0x00]);
326    }
327
328    #[test]
329    fn append_two_u32_and_bit() {
330        let roi = ROInput::new()
331            .append_u32(1729u32)
332            .append_bool(false)
333            .append_u32(u32::MAX);
334        assert!(roi.bits.len() == 65);
335        assert!(roi.bits.as_raw_slice() == [0xc1, 0x06, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01]);
336    }
337
338    #[test]
339    fn append_u64() {
340        let roi = ROInput::new().append_u64(6174u64);
341        assert!(roi.bits.len() == 64);
342        assert!(roi.bits.as_raw_slice() == [0x1e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
343    }
344
345    #[test]
346    fn append_two_u64_and_bits() {
347        let roi = ROInput::new()
348            .append_bool(true)
349            .append_u64(u64::MAX / 6174u64)
350            .append_bool(false)
351            .append_u64(u64::MAX / 1111u64);
352        assert!(roi.bits.len() == 130);
353        assert!(
354            roi.bits.as_raw_slice()
355                == [
356                    0xe1, 0x29, 0x89, 0xd6, 0xcb, 0x3a, 0x15, 0x00, 0x08, 0x17, 0xc4, 0x9b, 0x04,
357                    0xf4, 0xeb, 0x00, 0x00
358                ]
359        );
360    }
361
362    #[test]
363    fn all_1() {
364        let roi = ROInput::new()
365            .append_bool(true)
366            .append_scalar(
367                Fq::from_hex("01d1755db21c8cd2a9cf5a3436178da3d70f484cd4b4c8834b799921e7d7a102")
368                    .expect("failed to create scalar"),
369            )
370            .append_u64(18446744073709551557)
371            .append_bytes(&[0xba, 0xdc, 0x0f, 0xfe])
372            .append_scalar(
373                Fq::from_hex("e70187e9b125524489d0433da76fd8287fa652eaebde147b45fa0cd86f171810")
374                    .expect("failed to create scalar"),
375            )
376            .append_bool(false)
377            .append_u32(2147483647)
378            .append_bool(true);
379
380        assert!(roi.bits.len() == 641);
381        assert!(
382            roi.bits.as_raw_slice()
383                == [
384                    0x03, 0xa2, 0xeb, 0xba, 0x64, 0x39, 0x18, 0xa5, 0x53, 0x9f, 0xb5, 0x68, 0x6c,
385                    0x2e, 0x1a, 0x47, 0xaf, 0x1f, 0x90, 0x98, 0xa8, 0x69, 0x91, 0x07, 0x97, 0xf2,
386                    0x32, 0x43, 0xce, 0xaf, 0x43, 0x05, 0xc5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
387                    0xff, 0xba, 0xdc, 0x0f, 0xfe, 0xe7, 0x01, 0x87, 0xe9, 0xb1, 0x25, 0x52, 0x44,
388                    0x89, 0xd0, 0x43, 0x3d, 0xa7, 0x6f, 0xd8, 0x28, 0x7f, 0xa6, 0x52, 0xea, 0xeb,
389                    0xde, 0x14, 0x7b, 0x45, 0xfa, 0x0c, 0xd8, 0x6f, 0x17, 0x18, 0x10, 0xff, 0xff,
390                    0xff, 0x7f, 0x01
391                ]
392        );
393    }
394
395    #[test]
396    fn transaction_bits() {
397        let roi = ROInput::new()
398            .append_u64(1000000) // fee
399            .append_u64(1) // fee token
400            .append_bool(true) // fee payer pk odd
401            .append_u32(0) // nonce
402            .append_u32(u32::MAX) // valid_until
403            .append_bytes(&[0; 34]) // memo
404            .append_bool(false) // tags[0]
405            .append_bool(false) // tags[1]
406            .append_bool(false) // tags[2]
407            .append_bool(true) // sender pk odd
408            .append_bool(false) // receiver pk odd
409            .append_u64(1) // token_id
410            .append_u64(10000000000) // amount
411            .append_bool(false) // token_locked
412            .append_scalar(
413                Fq::from_hex("de217a3017ca0b7a278e75f63c09890e3894be532d8dbadd30a7d450055f6d2d")
414                    .expect("failed to create scalar"),
415            )
416            .append_bytes(&[0x01]);
417        assert_eq!(roi.bits.len(), 862);
418        assert_eq!(
419            roi.bits.as_raw_slice(),
420            [
421                0x40, 0x42, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
422                0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
423                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425                0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x02,
426                0x95, 0x00, 0x00, 0x00, 0x00, 0xef, 0x10, 0x3d, 0x98, 0x0b, 0xe5, 0x05, 0xbd, 0x13,
427                0xc7, 0x3a, 0x7b, 0x9e, 0x84, 0x44, 0x07, 0x1c, 0x4a, 0xdf, 0xa9, 0x96, 0x46, 0xdd,
428                0x6e, 0x98, 0x53, 0x6a, 0xa8, 0x82, 0xaf, 0xb6, 0x56, 0x00
429            ]
430        )
431    }
432
433    #[test]
434    fn append_field() {
435        let roi = ROInput::new().append_field(
436            Fp::from_hex("2eaedae42a7461d5952d27b97ecad068b698ebb94e8a0e4c45388bb613de7e08")
437                .expect("failed to create field"),
438        );
439
440        assert_eq!(
441            roi.to_bytes(),
442            [
443                0x2e, 0xae, 0xda, 0xe4, 0x2a, 0x74, 0x61, 0xd5, 0x95, 0x2d, 0x27, 0xb9, 0x7e, 0xca,
444                0xd0, 0x68, 0xb6, 0x98, 0xeb, 0xb9, 0x4e, 0x8a, 0x0e, 0x4c, 0x45, 0x38, 0x8b, 0xb6,
445                0x13, 0xde, 0x7e, 0x08
446            ]
447        );
448    }
449
450    #[test]
451    fn append_two_fields() {
452        let roi = ROInput::new()
453            .append_field(
454                Fp::from_hex("0cdaf334e9632268a5aa959c2781fb32bf45565fe244ae42c849d3fdc7c6441d")
455                    .expect("failed to create field"),
456            )
457            .append_field(
458                Fp::from_hex("2eaedae42a7461d5952d27b97ecad068b698ebb94e8a0e4c45388bb613de7e08")
459                    .expect("failed to create field"),
460            );
461
462        assert_eq!(
463            roi.to_bytes(),
464            [
465                0x0c, 0xda, 0xf3, 0x34, 0xe9, 0x63, 0x22, 0x68, 0xa5, 0xaa, 0x95, 0x9c, 0x27, 0x81,
466                0xfb, 0x32, 0xbf, 0x45, 0x56, 0x5f, 0xe2, 0x44, 0xae, 0x42, 0xc8, 0x49, 0xd3, 0xfd,
467                0xc7, 0xc6, 0x44, 0x1d, 0x17, 0x57, 0x6d, 0x72, 0x15, 0xba, 0xb0, 0xea, 0xca, 0x96,
468                0x93, 0x5c, 0x3f, 0x65, 0x68, 0x34, 0x5b, 0xcc, 0xf5, 0x5c, 0x27, 0x45, 0x07, 0xa6,
469                0x22, 0x9c, 0x45, 0xdb, 0x09, 0x6f, 0x3f, 0x04
470            ]
471        );
472    }
473
474    #[test]
475    fn append_three_fields() {
476        let roi = ROInput::new()
477            .append_field(
478                Fp::from_hex("1f3f142986041b54427aa2032632e34df2fa9bde9bce70c04c5034266619e529")
479                    .expect("failed to create field"),
480            )
481            .append_field(
482                Fp::from_hex("37f4433b85e753a91a1d79751645f1448954c433f9492e36a933ca7f3df61a04")
483                    .expect("failed to create field"),
484            )
485            .append_field(
486                Fp::from_hex("6cf4772d3e1aab98a2b514b73a4f6e0df1fb4f703ecfa762196b22c26da4341c")
487                    .expect("failed to create field"),
488            );
489
490        assert_eq!(
491            roi.to_bytes(),
492            [
493                0x1f, 0x3f, 0x14, 0x29, 0x86, 0x04, 0x1b, 0x54, 0x42, 0x7a, 0xa2, 0x03, 0x26, 0x32,
494                0xe3, 0x4d, 0xf2, 0xfa, 0x9b, 0xde, 0x9b, 0xce, 0x70, 0xc0, 0x4c, 0x50, 0x34, 0x26,
495                0x66, 0x19, 0xe5, 0xa9, 0x1b, 0xfa, 0xa1, 0x9d, 0xc2, 0xf3, 0xa9, 0x54, 0x8d, 0x8e,
496                0xbc, 0x3a, 0x8b, 0xa2, 0x78, 0xa2, 0x44, 0x2a, 0xe2, 0x99, 0xfc, 0x24, 0x17, 0x9b,
497                0xd4, 0x19, 0xe5, 0xbf, 0x1e, 0x7b, 0x0d, 0x02, 0x1b, 0xfd, 0x5d, 0x8b, 0x8f, 0xc6,
498                0x2a, 0xa6, 0x68, 0x2d, 0xc5, 0xad, 0xce, 0x93, 0x5b, 0x43, 0xfc, 0xfe, 0x13, 0x9c,
499                0xcf, 0xf3, 0xa9, 0x58, 0xc6, 0x9a, 0x88, 0x70, 0x1b, 0x29, 0x0d, 0x07
500            ]
501        );
502    }
503
504    #[test]
505    fn append_field_and_scalar() {
506        let roi = ROInput::new()
507            .append_field(
508                Fp::from_hex("64cde530327a36fcb88b6d769adca9b7c5d266e7d0042482203f3fd3a0d71721")
509                    .expect("failed to create field"),
510            )
511            .append_scalar(
512                Fq::from_hex("604355d0daa455db783fd7ee11c5bd9b04d67ba64c27c95bef95e379f98c6432")
513                    .expect("failed to create scalar"),
514            );
515
516        assert_eq!(
517            roi.to_bytes(),
518            [
519                0x64, 0xcd, 0xe5, 0x30, 0x32, 0x7a, 0x36, 0xfc, 0xb8, 0x8b, 0x6d, 0x76, 0x9a, 0xdc,
520                0xa9, 0xb7, 0xc5, 0xd2, 0x66, 0xe7, 0xd0, 0x04, 0x24, 0x82, 0x20, 0x3f, 0x3f, 0xd3,
521                0xa0, 0xd7, 0x17, 0x21, 0xb0, 0xa1, 0x2a, 0x68, 0x6d, 0xd2, 0xaa, 0x6d, 0xbc, 0x9f,
522                0x6b, 0xf7, 0x88, 0xe2, 0xde, 0x4d, 0x02, 0xeb, 0x3d, 0x53, 0xa6, 0x93, 0xe4, 0xad,
523                0xf7, 0xca, 0xf1, 0xbc, 0x7c, 0x46, 0x32, 0x19
524            ]
525        );
526    }
527
528    #[test]
529    fn append_field_bit_and_scalar() {
530        let roi = ROInput::new()
531            .append_field(
532                Fp::from_hex("d897c7a8b811d8acd3eeaa4adf42292802eed80031c2ad7c8989aea1fe94322c")
533                    .expect("failed to create field"),
534            )
535            .append_bool(false)
536            .append_scalar(
537                Fq::from_hex("79586cc6b8b53c8991b2abe0ca76508f056ca50f06836ce4d818c2ff73d42b28")
538                    .expect("failed to create scalar"),
539            );
540
541        assert_eq!(
542            roi.to_bytes(),
543            [
544                0xd8, 0x97, 0xc7, 0xa8, 0xb8, 0x11, 0xd8, 0xac, 0xd3, 0xee, 0xaa, 0x4a, 0xdf, 0x42,
545                0x29, 0x28, 0x02, 0xee, 0xd8, 0x00, 0x31, 0xc2, 0xad, 0x7c, 0x89, 0x89, 0xae, 0xa1,
546                0xfe, 0x94, 0x32, 0x2c, 0x79, 0x58, 0x6c, 0xc6, 0xb8, 0xb5, 0x3c, 0x89, 0x91, 0xb2,
547                0xab, 0xe0, 0xca, 0x76, 0x50, 0x8f, 0x05, 0x6c, 0xa5, 0x0f, 0x06, 0x83, 0x6c, 0xe4,
548                0xd8, 0x18, 0xc2, 0xff, 0x73, 0xd4, 0x2b, 0x28
549            ]
550        );
551    }
552
553    #[test]
554    fn to_bytes() {
555        let roi = ROInput::new()
556            .append_field(
557                Fp::from_hex("a5984f2bd00906f9a86e75bfb4b2c3625f1a0d1cfacc1501e8e82ae7041efc14")
558                    .expect("failed to create field"),
559            )
560            .append_field(
561                Fp::from_hex("8af0bc770d49a5b9fcabfcdd033bab470b2a211ef80b710efe71315cfa818c0a")
562                    .expect("failed to create field"),
563            )
564            .append_bool(false)
565            .append_u32(314u32)
566            .append_scalar(
567                Fq::from_hex("c23c43a23ddc1516578b0f0d81b93cdbbc97744acc697cfc8c5dfd01cc448323")
568                    .expect("failed to create scalar"),
569            );
570
571        assert_eq!(
572            roi.to_bytes(),
573            [
574                0xa5, 0x98, 0x4f, 0x2b, 0xd0, 0x09, 0x06, 0xf9, 0xa8, 0x6e, 0x75, 0xbf, 0xb4, 0xb2,
575                0xc3, 0x62, 0x5f, 0x1a, 0x0d, 0x1c, 0xfa, 0xcc, 0x15, 0x01, 0xe8, 0xe8, 0x2a, 0xe7,
576                0x04, 0x1e, 0xfc, 0x14, 0x45, 0x78, 0xde, 0xbb, 0x86, 0xa4, 0xd2, 0x5c, 0xfe, 0x55,
577                0xfe, 0xee, 0x81, 0x9d, 0xd5, 0xa3, 0x05, 0x95, 0x10, 0x0f, 0xfc, 0x85, 0x38, 0x07,
578                0xff, 0xb8, 0x18, 0x2e, 0xfd, 0x40, 0x46, 0x05, 0x9d, 0x00, 0x00, 0x00, 0x61, 0x9e,
579                0x21, 0xd1, 0x1e, 0xee, 0x0a, 0x8b, 0xab, 0xc5, 0x87, 0x86, 0xc0, 0x5c, 0x9e, 0x6d,
580                0xde, 0x4b, 0x3a, 0x25, 0xe6, 0x34, 0x3e, 0x7e, 0xc6, 0xae, 0xfe, 0x00, 0x66, 0xa2,
581                0xc1, 0x11
582            ]
583        );
584    }
585
586    #[test]
587    fn to_fields_1_scalar() {
588        let roi = ROInput::new().append_scalar(
589            Fq::from_hex("5d496dd8ff63f640c006887098092b16bc8c78504f84fa1ee3a0b54f85f0a625")
590                .expect("failed to create scalar"),
591        );
592
593        assert_eq!(
594            roi.to_bytes(),
595            [
596                0x5d, 0x49, 0x6d, 0xd8, 0xff, 0x63, 0xf6, 0x40, 0xc0, 0x06, 0x88, 0x70, 0x98, 0x09,
597                0x2b, 0x16, 0xbc, 0x8c, 0x78, 0x50, 0x4f, 0x84, 0xfa, 0x1e, 0xe3, 0xa0, 0xb5, 0x4f,
598                0x85, 0xf0, 0xa6, 0x25
599            ]
600        );
601
602        assert_eq!(
603            roi.to_fields(),
604            [
605                Fp::from_hex("5d496dd8ff63f640c006887098092b16bc8c78504f84fa1ee3a0b54f85f0a625")
606                    .expect("failed to create field"),
607                Fp::from_hex("0000000000000000000000000000000000000000000000000000000000000000")
608                    .expect("failed to create field"),
609            ]
610        );
611    }
612
613    #[test]
614    fn to_fields_1_scalar_2_bits() {
615        let roi = ROInput::new()
616            .append_scalar(
617                Fq::from_hex("e8a9961c8c417b0d0e3d7366f6b0e6ef90a6dad123070f715e8a9eaa02e47330")
618                    .expect("failed to create scalar"),
619            )
620            .append_bool(false)
621            .append_bool(true);
622
623        assert_eq!(
624            roi.to_bytes(),
625            [
626                0xe8, 0xa9, 0x96, 0x1c, 0x8c, 0x41, 0x7b, 0x0d, 0x0e, 0x3d, 0x73, 0x66, 0xf6, 0xb0,
627                0xe6, 0xef, 0x90, 0xa6, 0xda, 0xd1, 0x23, 0x07, 0x0f, 0x71, 0x5e, 0x8a, 0x9e, 0xaa,
628                0x02, 0xe4, 0x73, 0x30, 0x01
629            ]
630        );
631
632        assert_eq!(
633            roi.to_fields(),
634            [
635                Fp::from_hex("e8a9961c8c417b0d0e3d7366f6b0e6ef90a6dad123070f715e8a9eaa02e47330")
636                    .expect("failed to create field"),
637                Fp::from_hex("0400000000000000000000000000000000000000000000000000000000000000")
638                    .expect("failed to create field"),
639            ]
640        );
641    }
642
643    #[test]
644    fn to_fields_2_scalars() {
645        let roi = ROInput::new()
646            .append_scalar(
647                Fq::from_hex("e05c25d2c17ec20d6bc8fd21204af52808451076cff687407164a21d352ddd22")
648                    .expect("failed to create scalar"),
649            )
650            .append_scalar(
651                Fq::from_hex("c356dbb39478508818e0320dffa6c1ef512564366ec885ee2fc4d385dd36df0f")
652                    .expect("failed to create scalar"),
653            );
654
655        assert_eq!(
656            roi.to_bytes(),
657            [
658                0xe0, 0x5c, 0x25, 0xd2, 0xc1, 0x7e, 0xc2, 0x0d, 0x6b, 0xc8, 0xfd, 0x21, 0x20, 0x4a,
659                0xf5, 0x28, 0x08, 0x45, 0x10, 0x76, 0xcf, 0xf6, 0x87, 0x40, 0x71, 0x64, 0xa2, 0x1d,
660                0x35, 0x2d, 0xdd, 0xa2, 0x61, 0xab, 0xed, 0x59, 0x4a, 0x3c, 0x28, 0x44, 0x0c, 0x70,
661                0x99, 0x86, 0x7f, 0xd3, 0xe0, 0xf7, 0xa8, 0x12, 0x32, 0x1b, 0x37, 0xe4, 0x42, 0xf7,
662                0x17, 0xe2, 0xe9, 0xc2, 0x6e, 0x9b, 0xef, 0x07
663            ]
664        );
665
666        assert_eq!(
667            roi.to_fields(),
668            [
669                Fp::from_hex("e05c25d2c17ec20d6bc8fd21204af52808451076cff687407164a21d352ddd22")
670                    .expect("failed to create field"),
671                Fp::from_hex("86adb66729f1a01031c0651afe4d83dfa34ac86cdc900bdd5f88a70bbb6dbe1f")
672                    .expect("failed to create field"),
673                Fp::from_hex("0000000000000000000000000000000000000000000000000000000000000000")
674                    .expect("failed to create field"),
675            ]
676        );
677    }
678
679    #[test]
680    fn to_fields_2_bits_scalar_u32() {
681        let roi = ROInput::new()
682            .append_bool(true)
683            .append_bool(false)
684            .append_scalar(
685                Fq::from_hex("689634de233b06251a80ac7df64483922727757eea1adc6f0c8f184441cfe10d")
686                    .expect("failed to create scalar"),
687            )
688            .append_u32(834803);
689
690        assert_eq!(
691            roi.to_bytes(),
692            [
693                0xa1, 0x59, 0xd2, 0x78, 0x8f, 0xec, 0x18, 0x94, 0x68, 0x00, 0xb2, 0xf6, 0xd9, 0x13,
694                0x0d, 0x4a, 0x9e, 0x9c, 0xd4, 0xf9, 0xa9, 0x6b, 0x70, 0xbf, 0x31, 0x3c, 0x62, 0x10,
695                0x05, 0x3d, 0x87, 0x37, 0xe6, 0x79, 0x19, 0x00, 0x00
696            ]
697        );
698
699        assert_eq!(
700            roi.to_fields(),
701            [
702                Fp::from_hex("a159d2788fec18946800b2f6d9130d4a9e9cd4f9a96b70bf313c6210053d8737")
703                    .expect("failed to create field"),
704                Fp::from_hex("98e7650000000000000000000000000000000000000000000000000000000000")
705                    .expect("failed to create field"),
706            ]
707        );
708    }
709
710    #[test]
711    fn to_fields_2_bits_field_scalar() {
712        let roi = ROInput::new()
713            .append_bool(false)
714            .append_bool(true)
715            .append_field(
716                Fp::from_hex("90926b620ad09ed616d5df158504faed42928719c58ae619d9eccc062f920411")
717                    .expect("failed to create field"),
718            )
719            .append_scalar(
720                Fq::from_hex("689634de233b06251a80ac7df64483922727757eea1adc6f0c8f184441cfe10d")
721                    .expect("failed to create scalar"),
722            );
723
724        assert_eq!(
725            roi.to_bytes(),
726            [
727                0x90, 0x92, 0x6b, 0x62, 0x0a, 0xd0, 0x9e, 0xd6, 0x16, 0xd5, 0xdf, 0x15, 0x85, 0x04,
728                0xfa, 0xed, 0x42, 0x92, 0x87, 0x19, 0xc5, 0x8a, 0xe6, 0x19, 0xd9, 0xec, 0xcc, 0x06,
729                0x2f, 0x92, 0x04, 0x11, 0xd1, 0x2c, 0x69, 0xbc, 0x47, 0x76, 0x0c, 0x4a, 0x34, 0x00,
730                0x59, 0xfb, 0xec, 0x89, 0x06, 0x25, 0x4f, 0x4e, 0xea, 0xfc, 0xd4, 0x35, 0xb8, 0xdf,
731                0x18, 0x1e, 0x31, 0x88, 0x82, 0x9e, 0xc3, 0x1b
732            ]
733        );
734
735        assert_eq!(
736            roi.to_fields(),
737            [
738                Fp::from_hex("90926b620ad09ed616d5df158504faed42928719c58ae619d9eccc062f920411")
739                    .expect("failed to create field"),
740                Fp::from_hex("a259d2788fec18946800b2f6d9130d4a9e9cd4f9a96b70bf313c6210053d8737")
741                    .expect("failed to create field"),
742                Fp::from_hex("0000000000000000000000000000000000000000000000000000000000000000")
743                    .expect("failed to create field"),
744            ]
745        );
746    }
747
748    #[test]
749    fn transaction_test_1() {
750        let roi = ROInput::new()
751            .append_field(
752                Fp::from_hex("41203c6bbac14b357301e1f386d80f52123fd00f02197491b690bddfa742ca22")
753                    .expect("failed to create field"),
754            ) // fee payer
755            .append_field(
756                Fp::from_hex("992cdaf29ffe15b2bcea5d00e498ed4fffd117c197f0f98586e405f72ef88e00")
757                    .expect("failed to create field"),
758            ) // source
759            .append_field(
760                Fp::from_hex("3fba4fa71bce0dfdf709d827463036d6291458dfef772ff65e87bd6d1b1e062a")
761                    .expect("failed to create field"),
762            ) // receiver
763            .append_u64(1000000) // fee
764            .append_u64(1) // fee token
765            .append_bool(true) // fee payer pk odd
766            .append_u32(0) // nonce
767            .append_u32(u32::MAX) // valid_until
768            .append_bytes(&[0; 34]) // memo
769            .append_bool(false) // tags[0]
770            .append_bool(false) // tags[1]
771            .append_bool(false) // tags[2]
772            .append_bool(true) // sender pk odd
773            .append_bool(false) // receiver pk odd
774            .append_u64(1) // token_id
775            .append_u64(10000000000) // amount
776            .append_bool(false); // token_locked
777        assert_eq!(roi.bits.len() + roi.fields.len() * 255, 1364);
778        assert_eq!(
779            roi.to_bytes(),
780            [
781                0x41, 0x20, 0x3c, 0x6b, 0xba, 0xc1, 0x4b, 0x35, 0x73, 0x01, 0xe1, 0xf3, 0x86, 0xd8,
782                0x0f, 0x52, 0x12, 0x3f, 0xd0, 0x0f, 0x02, 0x19, 0x74, 0x91, 0xb6, 0x90, 0xbd, 0xdf,
783                0xa7, 0x42, 0xca, 0xa2, 0x4c, 0x16, 0x6d, 0xf9, 0x4f, 0xff, 0x0a, 0x59, 0x5e, 0xf5,
784                0x2e, 0x00, 0x72, 0xcc, 0xf6, 0xa7, 0xff, 0xe8, 0x8b, 0xe0, 0x4b, 0xf8, 0xfc, 0x42,
785                0x43, 0xf2, 0x82, 0x7b, 0x17, 0x7c, 0x47, 0xc0, 0x8f, 0xee, 0xd3, 0xe9, 0x86, 0x73,
786                0x43, 0xff, 0x7d, 0x02, 0xf6, 0x89, 0x11, 0x8c, 0x8d, 0x75, 0x0a, 0x05, 0xd6, 0xf7,
787                0xfb, 0xdd, 0x8b, 0xbd, 0xd7, 0x61, 0x6f, 0xdb, 0x86, 0x87, 0x81, 0x0a, 0x48, 0xe8,
788                0x01, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
789                0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
790                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
791                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
792                0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x5f, 0xa0, 0x12, 0x00,
793                0x00, 0x00, 0x00
794            ]
795        );
796
797        assert_eq!(
798            roi.to_fields(),
799            [
800                Fp::from_hex("41203c6bbac14b357301e1f386d80f52123fd00f02197491b690bddfa742ca22")
801                    .expect("failed to create field"),
802                Fp::from_hex("992cdaf29ffe15b2bcea5d00e498ed4fffd117c197f0f98586e405f72ef88e00")
803                    .expect("failed to create field"),
804                Fp::from_hex("3fba4fa71bce0dfdf709d827463036d6291458dfef772ff65e87bd6d1b1e062a")
805                    .expect("failed to create field"),
806                Fp::from_hex("40420f0000000000010000000000000001000000feffffff0100000000000000")
807                    .expect("failed to create field"),
808                Fp::from_hex("0000000000000000000000000000000000000000000000000000400100000000")
809                    .expect("failed to create field"),
810                Fp::from_hex("00000000902f5009000000000000000000000000000000000000000000000000")
811                    .expect("failed to create field"),
812            ]
813        );
814    }
815
816    #[test]
817    fn nested_roinput_test() {
818        #[derive(Clone, Debug)]
819        struct A {
820            x: u32,
821            y: bool,
822            z: u32,
823        }
824
825        impl Hashable for A {
826            type D = ();
827
828            fn to_roinput(&self) -> ROInput {
829                ROInput::new()
830                    .append_u32(self.x)
831                    .append_bool(self.y)
832                    .append_u32(self.z)
833            }
834
835            fn domain_string(_: Self::D) -> Option<String> {
836                "A".to_string().into()
837            }
838        }
839
840        #[derive(Clone, Debug)]
841        struct B1 {
842            a: A,
843            b: u64,
844            c: bool,
845        }
846
847        impl Hashable for B1 {
848            type D = ();
849
850            fn to_roinput(&self) -> ROInput {
851                self.a.to_roinput().append_u64(self.b).append_bool(self.c)
852            }
853
854            fn domain_string(_: Self::D) -> Option<String> {
855                "B".to_string().into()
856            }
857        }
858
859        #[derive(Clone, Debug)]
860        struct B2 {
861            a: A,
862            b: u64,
863            c: bool,
864        }
865
866        impl Hashable for B2 {
867            type D = ();
868
869            fn to_roinput(&self) -> ROInput {
870                self.a
871                    .to_roinput()
872                    .append_roinput(ROInput::new().append_u64(self.b).append_bool(self.c))
873            }
874
875            fn domain_string(_: Self::D) -> Option<String> {
876                "B".to_string().into()
877            }
878        }
879
880        let a = A {
881            x: 16830533,
882            y: false,
883            z: 39827791,
884        };
885        let b1 = B1 {
886            a,
887            b: 124819,
888            c: true,
889        };
890        let b2 = B2 {
891            a: b1.a.clone(),
892            b: b1.b,
893            c: b1.c,
894        };
895
896        assert_eq!(b1.to_roinput(), b2.to_roinput());
897
898        let b2 = B2 {
899            a: b1.a.clone(),
900            b: b1.b,
901            c: false,
902        };
903        assert_ne!(b1.to_roinput(), b2.to_roinput());
904
905        let b2 = B2 {
906            a: b1.a.clone(),
907            b: b1.b + 1,
908            c: b1.c,
909        };
910        assert_ne!(b1.to_roinput(), b2.to_roinput());
911    }
912}