chia_sdk_driver/layers/datalayer/
delegation_layer.rs

1use chia_protocol::Bytes32;
2use chia_sdk_types::puzzles::{
3    DelegationLayerArgs, DelegationLayerSolution, DELEGATION_LAYER_PUZZLE_HASH,
4};
5use clvm_traits::FromClvm;
6use clvmr::{Allocator, NodePtr};
7
8use crate::{DriverError, Layer, Puzzle, SpendContext};
9
10#[allow(clippy::doc_markdown)]
11/// The Delegation [`Layer`] is used to enable DataLayer delegation capabilities
12/// For more information, see CHIP-0035.
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub struct DelegationLayer {
15    /// Launcher ID of the singleton outer layer. Used as the default hint when recreating this layer.
16    pub launcher_id: Bytes32,
17    /// Puzzle hash of the owner (usually a p2 puzzle like the standard puzzle).
18    pub owner_puzzle_hash: Bytes32,
19    /// Merkle root corresponding to the tree of delegated puzzles.
20    pub merkle_root: Bytes32,
21}
22
23impl DelegationLayer {
24    pub fn new(launcher_id: Bytes32, owner_puzzle_hash: Bytes32, merkle_root: Bytes32) -> Self {
25        Self {
26            launcher_id,
27            owner_puzzle_hash,
28            merkle_root,
29        }
30    }
31}
32
33impl Layer for DelegationLayer {
34    type Solution = DelegationLayerSolution<NodePtr, NodePtr>;
35
36    fn parse_puzzle(allocator: &Allocator, puzzle: Puzzle) -> Result<Option<Self>, DriverError> {
37        let Some(puzzle) = puzzle.as_curried() else {
38            return Ok(None);
39        };
40
41        if puzzle.mod_hash != DELEGATION_LAYER_PUZZLE_HASH {
42            return Ok(None);
43        }
44
45        let args = DelegationLayerArgs::from_clvm(allocator, puzzle.args)?;
46
47        Ok(Some(Self {
48            launcher_id: args.launcher_id,
49            owner_puzzle_hash: args.owner_puzzle_hash,
50            merkle_root: args.merkle_root,
51        }))
52    }
53
54    fn parse_solution(
55        allocator: &Allocator,
56        solution: NodePtr,
57    ) -> Result<Self::Solution, DriverError> {
58        Ok(DelegationLayerSolution::<NodePtr, NodePtr>::from_clvm(
59            allocator, solution,
60        )?)
61    }
62
63    fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
64        let curried = ctx.curry(DelegationLayerArgs::new(
65            self.launcher_id,
66            self.owner_puzzle_hash,
67            self.merkle_root,
68        ))?;
69        ctx.alloc(&curried)
70    }
71
72    fn construct_solution(
73        &self,
74        ctx: &mut SpendContext,
75        solution: Self::Solution,
76    ) -> Result<NodePtr, DriverError> {
77        ctx.alloc(&solution)
78    }
79}