chia_sdk_driver/primitives/action_layer/
cat_maker.rs1use 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}