1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
use crate::{tree_hash_atom, tree_hash_pair};

pub fn curry_tree_hash(program_hash: [u8; 32], arg_hashes: &[[u8; 32]]) -> [u8; 32] {
    let nil = tree_hash_atom(&[]);
    let op_q = tree_hash_atom(&[1]);
    let op_a = tree_hash_atom(&[2]);
    let op_c = tree_hash_atom(&[4]);

    let quoted_program = tree_hash_pair(op_q, program_hash);
    let mut quoted_args = tree_hash_atom(&[1]);

    for &arg_hash in arg_hashes.iter().rev() {
        let quoted_arg = tree_hash_pair(op_q, arg_hash);
        let terminated_args = tree_hash_pair(quoted_args, nil);
        let terminated_args = tree_hash_pair(quoted_arg, terminated_args);
        quoted_args = tree_hash_pair(op_c, terminated_args);
    }

    let terminated_args = tree_hash_pair(quoted_args, nil);
    let program_and_args = tree_hash_pair(quoted_program, terminated_args);
    tree_hash_pair(op_a, program_and_args)
}

#[cfg(test)]
mod tests {
    use clvm_traits::{clvm_curried_args, ToClvm};
    use clvmr::Allocator;
    use hex::ToHex;

    use crate::{tree_hash, CurriedProgram};

    use super::*;

    #[test]
    fn test_equivalence() {
        let mut a = Allocator::new();

        let program = a.new_number(2.into()).unwrap();
        let arg1 = a.new_number(5.into()).unwrap();
        let arg2 = a.new_number(8.into()).unwrap();
        let args = clvm_curried_args!(5, 8).to_clvm(&mut a).unwrap();
        let curried = CurriedProgram { program, args }.to_clvm(&mut a).unwrap();

        let tree_hash_result = tree_hash(&a, curried);

        let program_hash = tree_hash(&a, program);
        let arg1_hash = tree_hash(&a, arg1);
        let arg2_hash = tree_hash(&a, arg2);
        let curry_tree_hash_result = curry_tree_hash(program_hash, &[arg1_hash, arg2_hash]);

        assert_eq!(
            tree_hash_result.encode_hex::<String>(),
            curry_tree_hash_result.encode_hex::<String>()
        );
    }
}