clvm_utils/
curry_tree_hash.rs1use crate::{tree_hash_atom, tree_hash_pair, TreeHash};
2
3pub fn curry_tree_hash(program_hash: TreeHash, arg_hashes: &[TreeHash]) -> TreeHash {
4 let nil = tree_hash_atom(&[]);
5 let op_q = tree_hash_atom(&[1]);
6 let op_a = tree_hash_atom(&[2]);
7 let op_c = tree_hash_atom(&[4]);
8
9 let quoted_program = tree_hash_pair(op_q, program_hash);
10 let mut quoted_args = tree_hash_atom(&[1]);
11
12 for &arg_hash in arg_hashes.iter().rev() {
13 let quoted_arg = tree_hash_pair(op_q, arg_hash);
14 let terminated_args = tree_hash_pair(quoted_args, nil);
15 let terminated_args = tree_hash_pair(quoted_arg, terminated_args);
16 quoted_args = tree_hash_pair(op_c, terminated_args);
17 }
18
19 let terminated_args = tree_hash_pair(quoted_args, nil);
20 let program_and_args = tree_hash_pair(quoted_program, terminated_args);
21 tree_hash_pair(op_a, program_and_args)
22}
23
24#[cfg(test)]
25mod tests {
26 use clvm_traits::{clvm_curried_args, ToClvm};
27 use clvmr::Allocator;
28 use hex::ToHex;
29
30 use crate::{tree_hash, CurriedProgram};
31
32 use super::*;
33
34 #[test]
35 fn test_equivalence() {
36 let mut a = Allocator::new();
37
38 let program = a.new_number(2.into()).unwrap();
39 let arg_1 = a.new_number(5.into()).unwrap();
40 let arg_2 = a.new_number(8.into()).unwrap();
41 let args = clvm_curried_args!(5, 8).to_clvm(&mut a).unwrap();
42 let curried = CurriedProgram { program, args }.to_clvm(&mut a).unwrap();
43
44 let tree_hash_result = tree_hash(&a, curried);
45
46 let program_hash = tree_hash(&a, program);
47 let arg_1_hash = tree_hash(&a, arg_1);
48 let arg_2_hash = tree_hash(&a, arg_2);
49 let curry_tree_hash_result = curry_tree_hash(program_hash, &[arg_1_hash, arg_2_hash]);
50
51 assert_eq!(
52 tree_hash_result.encode_hex::<String>(),
53 curry_tree_hash_result.encode_hex::<String>()
54 );
55 }
56}