chia_sdk_driver/layers/
p2_one_of_many_layer.rs

1use chia_protocol::Bytes32;
2use chia_sdk_types::puzzles::{P2OneOfManyArgs, P2OneOfManySolution, P2_ONE_OF_MANY_PUZZLE_HASH};
3use clvm_traits::FromClvm;
4use clvm_utils::{CurriedProgram, ToTreeHash, TreeHash};
5use clvmr::{Allocator, NodePtr};
6
7use crate::{DriverError, Layer, Puzzle, SpendContext};
8
9/// The p2 1 of n [`Layer`] allows for picking from several delegated puzzles at runtime without revealing up front.
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub struct P2OneOfManyLayer {
12    /// The merkle root used to lookup the delegated puzzle as part of the solution.
13    pub merkle_root: Bytes32,
14}
15
16impl P2OneOfManyLayer {
17    pub fn new(merkle_root: Bytes32) -> Self {
18        Self { merkle_root }
19    }
20}
21
22impl Layer for P2OneOfManyLayer {
23    type Solution = P2OneOfManySolution<NodePtr, NodePtr>;
24
25    fn parse_puzzle(allocator: &Allocator, puzzle: Puzzle) -> Result<Option<Self>, DriverError> {
26        let Some(puzzle) = puzzle.as_curried() else {
27            return Ok(None);
28        };
29
30        if puzzle.mod_hash != P2_ONE_OF_MANY_PUZZLE_HASH {
31            return Ok(None);
32        }
33
34        let args = P2OneOfManyArgs::from_clvm(allocator, puzzle.args)?;
35
36        Ok(Some(Self {
37            merkle_root: args.merkle_root,
38        }))
39    }
40
41    fn parse_solution(
42        allocator: &Allocator,
43        solution: NodePtr,
44    ) -> Result<Self::Solution, DriverError> {
45        Ok(P2OneOfManySolution::<NodePtr, NodePtr>::from_clvm(
46            allocator, solution,
47        )?)
48    }
49
50    fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
51        ctx.curry(P2OneOfManyArgs {
52            merkle_root: self.merkle_root,
53        })
54    }
55
56    fn construct_solution(
57        &self,
58        ctx: &mut SpendContext,
59        solution: Self::Solution,
60    ) -> Result<NodePtr, DriverError> {
61        ctx.alloc(&solution)
62    }
63}
64
65impl ToTreeHash for P2OneOfManyLayer {
66    fn tree_hash(&self) -> TreeHash {
67        CurriedProgram {
68            program: P2_ONE_OF_MANY_PUZZLE_HASH,
69            args: P2OneOfManyArgs::new(self.merkle_root),
70        }
71        .tree_hash()
72    }
73}