chia-sdk-driver 0.33.0

Driver code for interacting with standard puzzles on the Chia blockchain.
Documentation
use chia_protocol::{Bytes32, Coin, CoinSpend};
use chia_puzzle_types::{LineageProof, singleton::SingletonArgs};
use chia_sdk_types::{
    Mod,
    puzzles::{Slot1stCurryArgs, Slot2ndCurryArgs, SlotInfo, SlotSolution},
};
use clvm_utils::{CurriedProgram, ToTreeHash, TreeHash};
use clvmr::NodePtr;

use crate::{DriverError, SpendContext};

#[derive(Debug, Clone, PartialEq, Eq)]
#[must_use]
pub struct Slot<V> {
    pub coin: Coin,
    pub proof: LineageProof,

    pub info: SlotInfo<V>,
}

impl<V> Slot<V> {
    pub fn new(proof: LineageProof, info: SlotInfo<V>) -> Self {
        let parent_coin_id = Coin::new(
            proof.parent_parent_coin_info,
            SingletonArgs::curry_tree_hash(info.launcher_id, proof.parent_inner_puzzle_hash.into())
                .into(),
            proof.parent_amount,
        )
        .coin_id();

        Self {
            coin: Coin::new(parent_coin_id, Slot::<V>::puzzle_hash(&info).into(), 0),
            proof,
            info,
        }
    }

    pub fn first_curry_hash(launcher_id: Bytes32, nonce: u64) -> TreeHash {
        Slot1stCurryArgs::new(launcher_id, nonce).curry_tree_hash()
    }

    pub fn puzzle_hash(info: &SlotInfo<V>) -> TreeHash {
        CurriedProgram {
            program: Self::first_curry_hash(info.launcher_id, info.nonce),
            args: Slot2ndCurryArgs {
                value_hash: info.value_hash,
            },
        }
        .tree_hash()
    }

    pub fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
        let self_program = ctx.curry(Slot1stCurryArgs::new(
            self.info.launcher_id,
            self.info.nonce,
        ))?;

        ctx.alloc(&CurriedProgram {
            program: self_program,
            args: Slot2ndCurryArgs {
                value_hash: self.info.value_hash,
            },
        })
    }

    pub fn spend(
        self,
        ctx: &mut SpendContext,
        spender_inner_puzzle_hash: Bytes32,
    ) -> Result<(), DriverError> {
        let puzzle_reveal = self.construct_puzzle(ctx)?;
        let puzzle_reveal = ctx.serialize(&puzzle_reveal)?;

        let solution = ctx.serialize(&SlotSolution {
            lineage_proof: self.proof,
            spender_inner_puzzle_hash,
        })?;

        ctx.insert(CoinSpend::new(self.coin, puzzle_reveal, solution));

        Ok(())
    }
}