chia_sdk_driver/layers/
p2_parent.rs

1use chia_sdk_types::puzzles::{P2_PARENT_PUZZLE_HASH, P2ParentArgs, P2ParentSolution};
2use clvm_traits::FromClvm;
3use clvm_utils::TreeHash;
4use clvmr::{Allocator, NodePtr};
5
6use crate::{CatMaker, DriverError, Layer, Puzzle, SpendContext};
7
8/// The p2 parent [`Layer`] fixes a coin's delegated inner puzzle to match the parent's inner puzzle.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct P2ParentLayer {
11    pub cat_maker: CatMaker,
12}
13
14impl P2ParentLayer {
15    pub fn xch() -> Self {
16        Self {
17            cat_maker: CatMaker::Xch,
18        }
19    }
20
21    pub fn cat(tail_hash_hash: TreeHash) -> Self {
22        Self {
23            cat_maker: CatMaker::Default { tail_hash_hash },
24        }
25    }
26
27    pub fn revocable_cat(tail_hash_hash: TreeHash, hidden_puzzle_hash_hash: TreeHash) -> Self {
28        Self {
29            cat_maker: CatMaker::Revocable {
30                tail_hash_hash,
31                hidden_puzzle_hash_hash,
32            },
33        }
34    }
35}
36
37impl Layer for P2ParentLayer {
38    type Solution = P2ParentSolution<NodePtr, NodePtr, NodePtr>;
39
40    fn parse_puzzle(allocator: &Allocator, puzzle: Puzzle) -> Result<Option<Self>, DriverError> {
41        let Some(puzzle) = puzzle.as_curried() else {
42            return Ok(None);
43        };
44
45        if puzzle.mod_hash != P2_PARENT_PUZZLE_HASH {
46            return Ok(None);
47        }
48
49        let args = P2ParentArgs::from_clvm(allocator, puzzle.args)?;
50        let Some(cat_maker) =
51            CatMaker::parse_puzzle(allocator, Puzzle::parse(allocator, args.cat_maker))?
52        else {
53            return Ok(None);
54        };
55
56        Ok(Some(Self { cat_maker }))
57    }
58
59    fn parse_solution(
60        allocator: &Allocator,
61        solution: NodePtr,
62    ) -> Result<Self::Solution, DriverError> {
63        Ok(P2ParentSolution::<NodePtr, NodePtr, NodePtr>::from_clvm(
64            allocator, solution,
65        )?)
66    }
67
68    fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
69        let cat_maker = self.cat_maker.get_puzzle(ctx)?;
70
71        let curried = ctx.curry(P2ParentArgs { cat_maker })?;
72        ctx.alloc(&curried)
73    }
74
75    fn construct_solution(
76        &self,
77        ctx: &mut SpendContext,
78        solution: Self::Solution,
79    ) -> Result<NodePtr, DriverError> {
80        ctx.alloc(&solution)
81    }
82}