chia_sdk_driver/primitives/action_layer/
cat_maker.rs

1use chia_protocol::Bytes32;
2use chia_sdk_types::{
3    Mod,
4    puzzles::{
5        DEFAULT_CAT_MAKER_PUZZLE_HASH, DefaultCatMakerArgs, REVOCABLE_CAT_MAKER_PUZZLE_HASH,
6        RevocableCatMakerArgs, XCH_CAT_MAKER_PUZZLE_HASH, XchCatMaker,
7    },
8};
9use clvm_traits::{FromClvm, ToClvm, clvm_tuple};
10use clvm_utils::TreeHash;
11use clvmr::{Allocator, NodePtr};
12
13use crate::{DriverError, Puzzle, SpendContext};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum CatMaker {
17    Default {
18        tail_hash_hash: TreeHash,
19    },
20    Revocable {
21        tail_hash_hash: TreeHash,
22        hidden_puzzle_hash_hash: TreeHash,
23    },
24    Xch,
25}
26
27impl CatMaker {
28    pub fn curry_tree_hash(&self) -> TreeHash {
29        match self {
30            CatMaker::Default { tail_hash_hash } => {
31                DefaultCatMakerArgs::new((*tail_hash_hash).into()).curry_tree_hash()
32            }
33            CatMaker::Revocable {
34                tail_hash_hash,
35                hidden_puzzle_hash_hash,
36            } => RevocableCatMakerArgs::new(*tail_hash_hash, *hidden_puzzle_hash_hash)
37                .curry_tree_hash(),
38            CatMaker::Xch => XCH_CAT_MAKER_PUZZLE_HASH,
39        }
40    }
41
42    pub fn get_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
43        match self {
44            CatMaker::Default { tail_hash_hash } => {
45                ctx.curry(DefaultCatMakerArgs::new((*tail_hash_hash).into()))
46            }
47            CatMaker::Revocable {
48                tail_hash_hash,
49                hidden_puzzle_hash_hash,
50            } => ctx.curry(RevocableCatMakerArgs::new(
51                *tail_hash_hash,
52                *hidden_puzzle_hash_hash,
53            )),
54            CatMaker::Xch => ctx.alloc_mod::<XchCatMaker>(),
55        }
56    }
57
58    pub fn run<S>(
59        &self,
60        ctx: &mut SpendContext,
61        inner_puzzle_hash: Bytes32,
62        solution_rest: S,
63    ) -> Result<Bytes32, DriverError>
64    where
65        S: ToClvm<Allocator>,
66    {
67        let solution = clvm_tuple!(inner_puzzle_hash, solution_rest);
68        let solution = ctx.alloc(&solution)?;
69
70        let puzzle = self.get_puzzle(ctx)?;
71        let result = ctx.run(puzzle, solution)?;
72
73        ctx.extract(result)
74    }
75
76    pub fn parse_puzzle(
77        allocator: &Allocator,
78        puzzle: Puzzle,
79    ) -> Result<Option<Self>, DriverError> {
80        let puzzle_mod_hash = puzzle.mod_hash();
81
82        if puzzle_mod_hash == XCH_CAT_MAKER_PUZZLE_HASH {
83            return Ok(Some(Self::Xch));
84        }
85
86        if let Some(curried_puzzle) = puzzle.as_curried() {
87            if puzzle_mod_hash == DEFAULT_CAT_MAKER_PUZZLE_HASH {
88                let args = DefaultCatMakerArgs::from_clvm(allocator, curried_puzzle.args)?;
89
90                return Ok(Some(Self::Default {
91                    tail_hash_hash: args.tail_hash_hash.into(),
92                }));
93            } else if puzzle_mod_hash == REVOCABLE_CAT_MAKER_PUZZLE_HASH {
94                let args = RevocableCatMakerArgs::from_clvm(allocator, curried_puzzle.args)?;
95
96                return Ok(Some(Self::Revocable {
97                    tail_hash_hash: args.tail_hash_hash.into(),
98                    hidden_puzzle_hash_hash: args.mod_struct.hidden_puzzle_hash_hash.into(),
99                }));
100            }
101        }
102
103        Ok(None)
104    }
105}