chia_sdk_driver/layers/datalayer/
writer_layer.rs1use chia_puzzle_types::standard::StandardSolution;
2use chia_sdk_types::{
3 puzzles::{WriterLayerArgs, WriterLayerSolution, WRITER_LAYER_PUZZLE_HASH},
4 Conditions,
5};
6use clvm_traits::{clvm_quote, FromClvm};
7use clvm_utils::{ToTreeHash, TreeHash};
8use clvmr::{Allocator, NodePtr};
9
10use crate::{DriverError, Layer, Puzzle, Spend, SpendContext, StandardLayer};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct WriterLayer<I> {
16 pub inner_puzzle: I,
18}
19
20impl<I> WriterLayer<I> {
21 pub fn new(inner_puzzle: I) -> Self {
22 Self { inner_puzzle }
23 }
24}
25
26impl<I> Layer for WriterLayer<I>
27where
28 I: Layer,
29{
30 type Solution = I::Solution;
31
32 fn parse_puzzle(allocator: &Allocator, puzzle: Puzzle) -> Result<Option<Self>, DriverError> {
33 let Some(puzzle) = puzzle.as_curried() else {
34 return Ok(None);
35 };
36
37 if puzzle.mod_hash != WRITER_LAYER_PUZZLE_HASH {
38 return Ok(None);
39 }
40
41 let args = WriterLayerArgs::<NodePtr>::from_clvm(allocator, puzzle.args)?;
42
43 let Some(inner_puzzle) =
44 I::parse_puzzle(allocator, Puzzle::parse(allocator, args.inner_puzzle))?
45 else {
46 return Ok(None);
47 };
48
49 Ok(Some(Self { inner_puzzle }))
50 }
51
52 fn parse_solution(
53 allocator: &Allocator,
54 solution: NodePtr,
55 ) -> Result<Self::Solution, DriverError> {
56 let inner_solution =
57 WriterLayerSolution::<NodePtr>::from_clvm(allocator, solution)?.inner_solution;
58
59 I::parse_solution(allocator, inner_solution)
60 }
61
62 fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
63 let inner_puzzle = self.inner_puzzle.construct_puzzle(ctx)?;
64 let curried = ctx.curry(WriterLayerArgs::new(inner_puzzle))?;
65 ctx.alloc(&curried)
66 }
67
68 fn construct_solution(
69 &self,
70 ctx: &mut SpendContext,
71 solution: Self::Solution,
72 ) -> Result<NodePtr, DriverError> {
73 let inner_solution = self.inner_puzzle.construct_solution(ctx, solution)?;
74
75 ctx.alloc(&WriterLayerSolution::<NodePtr> { inner_solution })
76 }
77}
78
79impl<I> ToTreeHash for WriterLayer<I>
80where
81 I: ToTreeHash,
82{
83 fn tree_hash(&self) -> TreeHash {
84 let inner_puzzle_hash = self.inner_puzzle.tree_hash();
85
86 WriterLayerArgs::curry_tree_hash(inner_puzzle_hash)
87 }
88}
89
90impl WriterLayer<StandardLayer> {
91 pub fn spend(
92 self,
93 ctx: &mut SpendContext,
94 output_conditions: Conditions,
95 ) -> Result<Spend, DriverError> {
96 let dp = ctx.alloc(&clvm_quote!(output_conditions))?;
97 let solution = self.construct_solution(
98 ctx,
99 StandardSolution {
100 original_public_key: None,
101 delegated_puzzle: dp,
102 solution: NodePtr::NIL,
103 },
104 )?;
105 let puzzle = self.construct_puzzle(ctx)?;
106
107 Ok(Spend { puzzle, solution })
108 }
109}