clvm_utils/
hash_encoder.rs

1#![allow(clippy::items_after_statements)]
2
3use clvm_traits::{ClvmEncoder, ToClvm, ToClvmError};
4use clvmr::Atom;
5
6use crate::{tree_hash_atom, tree_hash_pair, TreeHash};
7
8pub trait ToTreeHash {
9    fn tree_hash(&self) -> TreeHash;
10}
11
12impl<T> ToTreeHash for T
13where
14    T: ToClvm<TreeHasher>,
15{
16    fn tree_hash(&self) -> TreeHash {
17        self.to_clvm(&mut TreeHasher).unwrap()
18    }
19}
20
21#[derive(Debug, Clone, Copy)]
22pub struct TreeHasher;
23
24impl ClvmEncoder for TreeHasher {
25    type Node = TreeHash;
26
27    fn encode_atom(&mut self, bytes: Atom<'_>) -> Result<Self::Node, ToClvmError> {
28        Ok(tree_hash_atom(bytes.as_ref()))
29    }
30
31    fn encode_pair(
32        &mut self,
33        first: Self::Node,
34        rest: Self::Node,
35    ) -> Result<Self::Node, ToClvmError> {
36        Ok(tree_hash_pair(first, rest))
37    }
38}
39
40impl ToClvm<TreeHasher> for TreeHash {
41    fn to_clvm(&self, _encoder: &mut TreeHasher) -> Result<TreeHash, ToClvmError> {
42        Ok(*self)
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    use clvm_traits::ToClvm;
51
52    use crate::{curry_tree_hash, CurriedProgram};
53
54    #[test]
55    fn test_tree_hash() {
56        assert_eq!(
57            hex::encode(().tree_hash()),
58            "4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a"
59        );
60        assert_eq!(
61            hex::encode([1, 2, 3].tree_hash()),
62            "bcd55bcd0daebba8cb158547e8480dc968570faf958f1e31a9887d6ae3dba591"
63        );
64        assert_eq!(
65            hex::encode("hello".tree_hash()),
66            "cceeb7a985ecc3dabcb4c8f666cd637f16f008e3c963db6aa6f83a7b288c54ef"
67        );
68        assert_eq!(
69            hex::encode(((1, 2), (3, 4)).tree_hash()),
70            "2824018d148bc6aed0847e2c86aaa8a5407b916169f15b12cea31fa932fc4c8d"
71        );
72
73        // This is the default hidden puzzle for the standard transaction.
74        // Its tree hash is known, and its CLVM is `(=)`.
75        assert_eq!(
76            hex::encode([9].tree_hash()),
77            "711d6c4e32c92e53179b199484cf8c897542bc57f2b22582799f9d657eec4699"
78        );
79    }
80
81    #[test]
82    fn test_curry_tree_hash() {
83        let hash_1 = [1, 2, 3].tree_hash();
84        let hash_2 = [4, 5, 6].tree_hash();
85        let hash_3 = [7, 8, 9].tree_hash();
86
87        let manual = curry_tree_hash(hash_1, &[hash_2, hash_3]);
88
89        #[derive(ToClvm)]
90        #[clvm(curry)]
91        struct Args<T> {
92            a: T,
93            b: T,
94        }
95
96        let hash = CurriedProgram {
97            program: hash_1,
98            args: Args {
99                a: hash_2,
100                b: hash_3,
101            },
102        }
103        .tree_hash();
104
105        assert_eq!(hash, manual);
106    }
107}