chia_sdk_driver/primitives/action_layer/
uniqueness_prelauncher.rs1use chia_protocol::{Bytes32, Coin, CoinSpend};
2use chia_puzzles::SINGLETON_LAUNCHER_HASH;
3use chia_sdk_types::{
4 Mod,
5 puzzles::{UniquenessPrelauncher1stCurryArgs, UniquenessPrelauncher2ndCurryArgs},
6};
7use clvm_traits::ToClvm;
8use clvm_utils::{CurriedProgram, ToTreeHash, TreeHash, tree_hash};
9use clvmr::{Allocator, NodePtr};
10
11use crate::{DriverError, Launcher, SpendContext};
12
13#[derive(Debug, Clone)]
14#[must_use]
15pub struct UniquenessPrelauncher<V> {
16 pub coin: Coin,
17 pub value: V,
18}
19
20impl<V> UniquenessPrelauncher<V> {
21 pub fn from_coin(coin: Coin, value: V) -> Self {
22 Self { coin, value }
23 }
24
25 pub fn new(
26 allocator: &mut Allocator,
27 parent_coin_id: Bytes32,
28 value: V,
29 ) -> Result<Self, DriverError>
30 where
31 V: ToClvm<Allocator> + Clone,
32 {
33 let value_ptr = value.to_clvm(allocator)?;
34 let value_hash = tree_hash(allocator, value_ptr);
35
36 Ok(Self::from_coin(
37 Coin::new(
38 parent_coin_id,
39 UniquenessPrelauncher::<V>::puzzle_hash(value_hash).into(),
40 0,
41 ),
42 value,
43 ))
44 }
45
46 pub fn first_curry_hash() -> TreeHash {
47 UniquenessPrelauncher1stCurryArgs {
48 launcher_puzzle_hash: SINGLETON_LAUNCHER_HASH.into(),
49 }
50 .curry_tree_hash()
51 }
52
53 pub fn puzzle_hash(value_hash: TreeHash) -> TreeHash {
54 CurriedProgram {
55 program: Self::first_curry_hash(),
56 args: UniquenessPrelauncher2ndCurryArgs { value: value_hash },
57 }
58 .tree_hash()
59 }
60
61 pub fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError>
62 where
63 V: ToClvm<Allocator> + Clone,
64 {
65 let prog_1st_curry = ctx.curry(UniquenessPrelauncher1stCurryArgs {
66 launcher_puzzle_hash: SINGLETON_LAUNCHER_HASH.into(),
67 })?;
68
69 ctx.alloc(&CurriedProgram {
70 program: prog_1st_curry,
71 args: UniquenessPrelauncher2ndCurryArgs {
72 value: self.value.clone(),
73 },
74 })
75 }
76
77 pub fn spend(self, ctx: &mut SpendContext) -> Result<Launcher, DriverError>
78 where
79 V: ToClvm<Allocator> + Clone,
80 {
81 let puzzle_reveal = self.construct_puzzle(ctx)?;
82 let puzzle_reveal = ctx.serialize(&puzzle_reveal)?;
83
84 let solution = ctx.serialize(&NodePtr::NIL)?;
85
86 ctx.insert(CoinSpend::new(self.coin, puzzle_reveal, solution));
87
88 Ok(Launcher::new(self.coin.coin_id(), 1))
89 }
90}