1use chia_protocol::{Coin, CoinSpend};
2use clvm_traits::{FromClvm, ToClvm};
3use clvmr::{Allocator, NodePtr};
4
5use crate::{DriverError, Puzzle, Spend, SpendContext};
6
7pub trait Layer {
9 type Solution;
12
13 fn parse_puzzle(allocator: &Allocator, puzzle: Puzzle) -> Result<Option<Self>, DriverError>
16 where
17 Self: Sized;
18
19 fn parse_solution(
21 allocator: &Allocator,
22 solution: NodePtr,
23 ) -> Result<Self::Solution, DriverError>;
24
25 fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError>;
28
29 fn construct_solution(
33 &self,
34 ctx: &mut SpendContext,
35 solution: Self::Solution,
36 ) -> Result<NodePtr, DriverError>;
37
38 fn construct_spend(
40 &self,
41 ctx: &mut SpendContext,
42 solution: Self::Solution,
43 ) -> Result<Spend, DriverError> {
44 let solution = self.construct_solution(ctx, solution)?;
45 let puzzle = self.construct_puzzle(ctx)?;
46 Ok(Spend::new(puzzle, solution))
47 }
48
49 fn construct_coin_spend(
51 &self,
52 ctx: &mut SpendContext,
53 coin: Coin,
54 solution: Self::Solution,
55 ) -> Result<CoinSpend, DriverError> {
56 let solution = self.construct_solution(ctx, solution)?;
57 let puzzle = self.construct_puzzle(ctx)?;
58 Ok(CoinSpend::new(
59 coin,
60 ctx.serialize(&puzzle)?,
61 ctx.serialize(&solution)?,
62 ))
63 }
64}
65
66impl<T> Layer for T
67where
68 T: ToClvm<Allocator> + FromClvm<Allocator>,
69{
70 type Solution = NodePtr;
71
72 fn parse_puzzle(allocator: &Allocator, puzzle: Puzzle) -> Result<Option<Self>, DriverError> {
73 Ok(Some(T::from_clvm(allocator, puzzle.ptr())?))
74 }
75
76 fn parse_solution(
77 _allocator: &Allocator,
78 solution: NodePtr,
79 ) -> Result<Self::Solution, DriverError> {
80 Ok(solution)
81 }
82
83 fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
84 ctx.alloc(&self)
85 }
86
87 fn construct_solution(
88 &self,
89 _ctx: &mut SpendContext,
90 solution: Self::Solution,
91 ) -> Result<NodePtr, DriverError> {
92 Ok(solution)
93 }
94}