mina_p2p_messages/
hash_input.rs

1use crate::{
2    bigint::{BigInt, InvalidBigInt},
3    list::List,
4    number::{Int32, Int64, UInt32, UInt64},
5    string::{ByteString, ZkAppUri},
6};
7use poseidon::hash::Inputs;
8use std::ops::Deref;
9
10/// Difference with `ToInputs` in `ledger` is that it can fail here, due
11/// to invalid bigints
12pub trait FailableToInputs {
13    fn to_input(&self, inputs: &mut Inputs) -> Result<(), InvalidBigInt>;
14}
15
16impl FailableToInputs for bool {
17    fn to_input(&self, inputs: &mut Inputs) -> Result<(), InvalidBigInt> {
18        inputs.append_bool(*self);
19        Ok(())
20    }
21}
22
23impl FailableToInputs for BigInt {
24    fn to_input(&self, inputs: &mut Inputs) -> Result<(), InvalidBigInt> {
25        let field = self.to_field()?;
26        inputs.append_field(field);
27        Ok(())
28    }
29}
30
31impl FailableToInputs for Int32 {
32    fn to_input(&self, inputs: &mut Inputs) -> Result<(), InvalidBigInt> {
33        inputs.append_u32(self.as_u32());
34        Ok(())
35    }
36}
37
38impl FailableToInputs for Int64 {
39    fn to_input(&self, inputs: &mut Inputs) -> Result<(), InvalidBigInt> {
40        inputs.append_u64(self.as_u64());
41        Ok(())
42    }
43}
44
45impl FailableToInputs for UInt32 {
46    fn to_input(&self, inputs: &mut Inputs) -> Result<(), InvalidBigInt> {
47        inputs.append_u32(self.as_u32());
48        Ok(())
49    }
50}
51
52impl FailableToInputs for UInt64 {
53    fn to_input(&self, inputs: &mut Inputs) -> Result<(), InvalidBigInt> {
54        inputs.append_u64(self.as_u64());
55        Ok(())
56    }
57}
58
59impl FailableToInputs for ByteString {
60    fn to_input(&self, inputs: &mut Inputs) -> Result<(), InvalidBigInt> {
61        inputs.append_bytes(self.as_ref());
62        Ok(())
63    }
64}
65
66impl FailableToInputs for ZkAppUri {
67    fn to_input(&self, inputs: &mut Inputs) -> Result<(), InvalidBigInt> {
68        inputs.append_bytes(self.as_ref());
69        Ok(())
70    }
71}
72
73impl<T, D> FailableToInputs for List<D>
74where
75    D: Deref<Target = T>,
76    T: FailableToInputs,
77{
78    fn to_input(&self, inputs: &mut Inputs) -> Result<(), InvalidBigInt> {
79        for v in self.deref().iter() {
80            v.to_input(inputs)?;
81        }
82        Ok(())
83    }
84}
85
86#[cfg(test)]
87mod tests {
88    use super::Inputs;
89    use o1_utils::FieldHelpers;
90
91    macro_rules! test_to_field {
92        ($test:ident : $fun:ident ( $( $value:expr ),* $(,)? ) = $hex:expr ) => {
93            #[test]
94            fn $test() {
95                let mut inputs = Inputs::new();
96                $(
97                    inputs.$fun($value);
98                )*
99                let fields = inputs.to_fields();
100                assert_eq!(fields.len(), 1);
101                let hex = fields[0].to_hex();
102                assert_eq!(&hex, $hex);
103            }
104        };
105    }
106
107    fn u48(n: u64) -> [u8; 6] {
108        n.to_le_bytes()[..6].try_into().unwrap()
109    }
110
111    test_to_field!(to_field_bools_test: append_bool(true, false) = "0200000000000000000000000000000000000000000000000000000000000000");
112    test_to_field!(to_field_u2_test: append_u2(0, 1, 3, 4) = "1c00000000000000000000000000000000000000000000000000000000000000");
113    test_to_field!(to_field_u8_test: append_u8(u8::MIN, u8::MAX / 2, u8::MAX) = "ff7f000000000000000000000000000000000000000000000000000000000000");
114    test_to_field!(to_field_u32_test: append_u32(u32::MIN, u32::MAX/2, u32::MAX) = "ffffffffffffff7f000000000000000000000000000000000000000000000000");
115    test_to_field!(to_field_u64_test: append_u64(u64::MIN, u64::MAX/2, u64::MAX) = "ffffffffffffffffffffffffffffff7f00000000000000000000000000000000");
116    test_to_field!(to_field_u48_test: append_u48(u48(u64::MIN), u48(u64::MAX/2), u48(u64::MAX)) = "ffffffffffffffffffffffff0000000000000000000000000000000000000000");
117    test_to_field!(to_field_bytes_test: append_bytes(&[0, 1, 255]) = "ff80000000000000000000000000000000000000000000000000000000000000");
118}