chia_sdk_driver/layers/
revocation_layer.rs

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