chia_sdk_driver/primitives/action_layer/
slot.rs1use chia_protocol::{Bytes32, Coin, CoinSpend};
2use chia_puzzle_types::{LineageProof, singleton::SingletonArgs};
3use chia_sdk_types::{
4 Mod,
5 puzzles::{Slot1stCurryArgs, Slot2ndCurryArgs, SlotInfo, SlotSolution},
6};
7use clvm_utils::{CurriedProgram, ToTreeHash, TreeHash};
8use clvmr::NodePtr;
9
10use crate::{DriverError, SpendContext};
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13#[must_use]
14pub struct Slot<V> {
15 pub coin: Coin,
16 pub proof: LineageProof,
17
18 pub info: SlotInfo<V>,
19}
20
21impl<V> Slot<V> {
22 pub fn new(proof: LineageProof, info: SlotInfo<V>) -> Self {
23 let parent_coin_id = Coin::new(
24 proof.parent_parent_coin_info,
25 SingletonArgs::curry_tree_hash(info.launcher_id, proof.parent_inner_puzzle_hash.into())
26 .into(),
27 proof.parent_amount,
28 )
29 .coin_id();
30
31 Self {
32 coin: Coin::new(parent_coin_id, Slot::<V>::puzzle_hash(&info).into(), 0),
33 proof,
34 info,
35 }
36 }
37
38 pub fn first_curry_hash(launcher_id: Bytes32, nonce: u64) -> TreeHash {
39 Slot1stCurryArgs::new(launcher_id, nonce).curry_tree_hash()
40 }
41
42 pub fn puzzle_hash(info: &SlotInfo<V>) -> TreeHash {
43 CurriedProgram {
44 program: Self::first_curry_hash(info.launcher_id, info.nonce),
45 args: Slot2ndCurryArgs {
46 value_hash: info.value_hash,
47 },
48 }
49 .tree_hash()
50 }
51
52 pub fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
53 let self_program = ctx.curry(Slot1stCurryArgs::new(
54 self.info.launcher_id,
55 self.info.nonce,
56 ))?;
57
58 ctx.alloc(&CurriedProgram {
59 program: self_program,
60 args: Slot2ndCurryArgs {
61 value_hash: self.info.value_hash,
62 },
63 })
64 }
65
66 pub fn spend(
67 self,
68 ctx: &mut SpendContext,
69 spender_inner_puzzle_hash: Bytes32,
70 ) -> Result<(), DriverError> {
71 let puzzle_reveal = self.construct_puzzle(ctx)?;
72 let puzzle_reveal = ctx.serialize(&puzzle_reveal)?;
73
74 let solution = ctx.serialize(&SlotSolution {
75 lineage_proof: self.proof,
76 spender_inner_puzzle_hash,
77 })?;
78
79 ctx.insert(CoinSpend::new(self.coin, puzzle_reveal, solution));
80
81 Ok(())
82 }
83}