chia_sdk_driver/layers/
revocation_layer.rs

1use chia_protocol::Bytes32;
2use chia_puzzles::REVOCATION_LAYER_HASH;
3use chia_sdk_types::{
4    puzzles::{RevocationArgs, RevocationSolution},
5    Mod,
6};
7use clvm_traits::FromClvm;
8use clvm_utils::{ToTreeHash, TreeHash};
9use clvmr::{Allocator, NodePtr};
10
11use crate::{DriverError, Layer, Puzzle, SpendContext};
12
13/// The revocation [`Layer`] allows the issuer to revoke the asset.
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct RevocationLayer {
16    pub hidden_puzzle_hash: Bytes32,
17    pub inner_puzzle_hash: Bytes32,
18}
19
20impl RevocationLayer {
21    pub fn new(hidden_puzzle_hash: Bytes32, inner_puzzle_hash: Bytes32) -> Self {
22        Self {
23            hidden_puzzle_hash,
24            inner_puzzle_hash,
25        }
26    }
27}
28
29impl Layer for RevocationLayer {
30    type Solution = RevocationSolution<NodePtr, NodePtr>;
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 != REVOCATION_LAYER_HASH.into() {
38            return Ok(None);
39        }
40
41        let args = RevocationArgs::from_clvm(allocator, puzzle.args)?;
42
43        if args.mod_hash != REVOCATION_LAYER_HASH.into() {
44            return Err(DriverError::InvalidModHash);
45        }
46
47        Ok(Some(Self {
48            hidden_puzzle_hash: args.hidden_puzzle_hash,
49            inner_puzzle_hash: args.inner_puzzle_hash,
50        }))
51    }
52
53    fn parse_solution(
54        allocator: &Allocator,
55        solution: NodePtr,
56    ) -> Result<Self::Solution, DriverError> {
57        Ok(RevocationSolution::<NodePtr, NodePtr>::from_clvm(
58            allocator, solution,
59        )?)
60    }
61
62    fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
63        ctx.curry(RevocationArgs::new(
64            self.hidden_puzzle_hash,
65            self.inner_puzzle_hash,
66        ))
67    }
68
69    fn construct_solution(
70        &self,
71        ctx: &mut SpendContext,
72        solution: Self::Solution,
73    ) -> Result<NodePtr, DriverError> {
74        ctx.alloc(&solution)
75    }
76}
77
78impl ToTreeHash for RevocationLayer {
79    fn tree_hash(&self) -> TreeHash {
80        RevocationArgs::new(self.hidden_puzzle_hash, self.inner_puzzle_hash).curry_tree_hash()
81    }
82}