chia-sdk-driver 0.33.0

Driver code for interacting with standard puzzles on the Chia blockchain.
Documentation
use chia_protocol::Bytes32;

use crate::{Deltas, DriverError, HashedPtr, Id, SpendAction, SpendContext, Spends};

#[derive(Debug, Clone, Copy)]
pub struct UpdateDidAction {
    pub id: Id,
    pub new_recovery_list_hash: Option<Option<Bytes32>>,
    pub new_num_verifications_required: Option<u64>,
    pub new_metadata: Option<HashedPtr>,
}

impl UpdateDidAction {
    pub fn new(
        id: Id,
        new_recovery_list_hash: Option<Option<Bytes32>>,
        new_num_verifications_required: Option<u64>,
        new_metadata: Option<HashedPtr>,
    ) -> Self {
        Self {
            id,
            new_recovery_list_hash,
            new_num_verifications_required,
            new_metadata,
        }
    }
}

impl SpendAction for UpdateDidAction {
    fn calculate_delta(&self, deltas: &mut Deltas, _index: usize) {
        deltas.update(self.id).input += 1;
        deltas.update(self.id).output += 1;
        deltas.set_needed(self.id);
    }

    fn spend(
        &self,
        _ctx: &mut SpendContext,
        spends: &mut Spends,
        _index: usize,
    ) -> Result<(), DriverError> {
        let did = spends
            .dids
            .get_mut(&self.id)
            .ok_or(DriverError::InvalidAssetId)?
            .last_mut()?;

        if let Some(new_recovery_list_hash) = self.new_recovery_list_hash {
            did.child_info.recovery_list_hash = new_recovery_list_hash;
        }

        if let Some(new_num_verifications_required) = self.new_num_verifications_required {
            did.child_info.num_verifications_required = new_num_verifications_required;
        }

        if let Some(new_metadata) = self.new_metadata {
            did.child_info.metadata = new_metadata;
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use anyhow::Result;
    use chia_sdk_test::Simulator;
    use indexmap::indexmap;

    use crate::{Action, BURN_PUZZLE_HASH, Relation};

    use super::*;

    #[test]
    fn test_action_update_did() -> Result<()> {
        let mut sim = Simulator::new();
        let mut ctx = SpendContext::new();

        let alice = sim.bls(1);

        let metadata = ctx.alloc_hashed(&"Hello, world!")?;
        let hint = ctx.hint(BURN_PUZZLE_HASH)?;

        let mut spends = Spends::new(alice.puzzle_hash);
        spends.add(alice.coin);

        let deltas = spends.apply(
            &mut ctx,
            &[
                Action::create_empty_did(),
                Action::update_did(
                    Id::New(0),
                    Some(Some(Bytes32::default())),
                    Some(2),
                    Some(metadata),
                ),
                Action::burn(Id::New(0), 1, hint),
            ],
        )?;

        let outputs = spends.finish_with_keys(
            &mut ctx,
            &deltas,
            Relation::None,
            &indexmap! { alice.puzzle_hash => alice.pk },
        )?;

        sim.spend_coins(ctx.take(), &[alice.sk])?;

        let did = outputs.dids[&Id::New(0)];
        assert_ne!(sim.coin_state(did.coin.coin_id()), None);
        assert_eq!(did.info.recovery_list_hash, Some(Bytes32::default()));
        assert_eq!(did.info.num_verifications_required, 2);
        assert_eq!(did.info.metadata, metadata);
        assert_eq!(did.info.p2_puzzle_hash, BURN_PUZZLE_HASH);
        assert_eq!(did.coin.amount, 1);

        Ok(())
    }
}