chia_sdk_driver/actions/
update_did.rs

1use chia_protocol::Bytes32;
2
3use crate::{Deltas, DriverError, HashedPtr, Id, SpendAction, SpendContext, Spends};
4
5#[derive(Debug, Clone, Copy)]
6pub struct UpdateDidAction {
7    pub id: Id,
8    pub new_recovery_list_hash: Option<Option<Bytes32>>,
9    pub new_num_verifications_required: Option<u64>,
10    pub new_metadata: Option<HashedPtr>,
11}
12
13impl UpdateDidAction {
14    pub fn new(
15        id: Id,
16        new_recovery_list_hash: Option<Option<Bytes32>>,
17        new_num_verifications_required: Option<u64>,
18        new_metadata: Option<HashedPtr>,
19    ) -> Self {
20        Self {
21            id,
22            new_recovery_list_hash,
23            new_num_verifications_required,
24            new_metadata,
25        }
26    }
27}
28
29impl SpendAction for UpdateDidAction {
30    fn calculate_delta(&self, deltas: &mut Deltas, _index: usize) {
31        let did = deltas.update(self.id);
32        did.input += 1;
33        did.output += 1;
34    }
35
36    fn spend(
37        &self,
38        _ctx: &mut SpendContext,
39        spends: &mut Spends,
40        _index: usize,
41    ) -> Result<(), DriverError> {
42        let did = spends
43            .dids
44            .get_mut(&self.id)
45            .ok_or(DriverError::InvalidAssetId)?
46            .last_mut()?;
47
48        if let Some(new_recovery_list_hash) = self.new_recovery_list_hash {
49            did.child_info.recovery_list_hash = new_recovery_list_hash;
50        }
51
52        if let Some(new_num_verifications_required) = self.new_num_verifications_required {
53            did.child_info.num_verifications_required = new_num_verifications_required;
54        }
55
56        if let Some(new_metadata) = self.new_metadata {
57            did.child_info.metadata = new_metadata;
58        }
59
60        Ok(())
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use anyhow::Result;
67    use chia_sdk_test::Simulator;
68    use indexmap::indexmap;
69
70    use crate::{Action, Relation, BURN_PUZZLE_HASH};
71
72    use super::*;
73
74    #[test]
75    fn test_action_update_did() -> Result<()> {
76        let mut sim = Simulator::new();
77        let mut ctx = SpendContext::new();
78
79        let alice = sim.bls(1);
80
81        let metadata = ctx.alloc_hashed(&"Hello, world!")?;
82        let hint = ctx.hint(BURN_PUZZLE_HASH)?;
83
84        let mut spends = Spends::new(alice.puzzle_hash);
85        spends.add(alice.coin);
86
87        let deltas = spends.apply(
88            &mut ctx,
89            &[
90                Action::create_empty_did(),
91                Action::update_did(
92                    Id::New(0),
93                    Some(Some(Bytes32::default())),
94                    Some(2),
95                    Some(metadata),
96                ),
97                Action::burn(Id::New(0), 1, hint),
98            ],
99        )?;
100
101        let outputs = spends.finish_with_keys(
102            &mut ctx,
103            &deltas,
104            Relation::None,
105            &indexmap! { alice.puzzle_hash => alice.pk },
106        )?;
107
108        sim.spend_coins(ctx.take(), &[alice.sk])?;
109
110        let did = outputs.dids[&Id::New(0)];
111        assert_ne!(sim.coin_state(did.coin.coin_id()), None);
112        assert_eq!(did.info.recovery_list_hash, Some(Bytes32::default()));
113        assert_eq!(did.info.num_verifications_required, 2);
114        assert_eq!(did.info.metadata, metadata);
115        assert_eq!(did.info.p2_puzzle_hash, BURN_PUZZLE_HASH);
116        assert_eq!(did.coin.amount, 1);
117
118        Ok(())
119    }
120}