Skip to main content

drive/state_transition_action/shielded/unshield/
mod.rs

1/// transformer
2pub mod transformer;
3/// v0
4pub mod v0;
5
6use crate::state_transition_action::shielded::unshield::v0::UnshieldTransitionActionV0;
7use crate::state_transition_action::shielded::ShieldedActionNote;
8use derive_more::From;
9use dpp::address_funds::PlatformAddress;
10use dpp::fee::Credits;
11
12/// Unshield transition action
13#[derive(Debug, Clone, From)]
14pub enum UnshieldTransitionAction {
15    /// v0
16    V0(UnshieldTransitionActionV0),
17}
18
19impl UnshieldTransitionAction {
20    /// Get output address
21    pub fn output_address(&self) -> &PlatformAddress {
22        match self {
23            UnshieldTransitionAction::V0(transition) => &transition.output_address,
24        }
25    }
26    /// Get amount
27    pub fn amount(&self) -> Credits {
28        match self {
29            UnshieldTransitionAction::V0(transition) => transition.amount,
30        }
31    }
32    /// Get notes
33    pub fn notes(&self) -> &[ShieldedActionNote] {
34        match self {
35            UnshieldTransitionAction::V0(transition) => &transition.notes,
36        }
37    }
38    /// Get anchor
39    pub fn anchor(&self) -> &[u8; 32] {
40        match self {
41            UnshieldTransitionAction::V0(transition) => &transition.anchor,
42        }
43    }
44    /// Fee amount (value_balance - amount), paid to proposers
45    pub fn fee_amount(&self) -> Credits {
46        match self {
47            UnshieldTransitionAction::V0(transition) => transition.fee_amount,
48        }
49    }
50    /// `true` only when this action is the chargeable failure of an
51    /// `IdentityCreateFromShieldedPool` (see `UnshieldTransitionActionV0::chargeable_failure`).
52    pub fn chargeable_failure(&self) -> bool {
53        match self {
54            UnshieldTransitionAction::V0(transition) => transition.chargeable_failure,
55        }
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    fn make_note() -> ShieldedActionNote {
64        ShieldedActionNote {
65            nullifier: [0x33; 32],
66            cmx: [0x44; 32],
67            cv_net: [0x22; 32],
68            encrypted_note: vec![0x10, 0x20],
69        }
70    }
71
72    fn make_action() -> UnshieldTransitionAction {
73        let v0 = UnshieldTransitionActionV0 {
74            output_address: PlatformAddress::P2pkh([0xBB; 20]),
75            amount: 7500,
76            notes: vec![make_note()],
77            anchor: [0x55; 32],
78            fee_amount: 250,
79            current_total_balance: 100000,
80            chargeable_failure: false,
81        };
82        UnshieldTransitionAction::from(v0)
83    }
84
85    #[test]
86    fn test_from_v0() {
87        let action = make_action();
88        assert!(matches!(action, UnshieldTransitionAction::V0(_)));
89    }
90
91    #[test]
92    fn test_output_address() {
93        let action = make_action();
94        assert_eq!(*action.output_address(), PlatformAddress::P2pkh([0xBB; 20]));
95    }
96
97    #[test]
98    fn test_amount() {
99        let action = make_action();
100        assert_eq!(action.amount(), 7500);
101    }
102
103    #[test]
104    fn test_notes() {
105        let action = make_action();
106        let notes = action.notes();
107        assert_eq!(notes.len(), 1);
108        assert_eq!(notes[0].nullifier, [0x33; 32]);
109        assert_eq!(notes[0].cmx, [0x44; 32]);
110    }
111
112    #[test]
113    fn test_anchor() {
114        let action = make_action();
115        assert_eq!(*action.anchor(), [0x55; 32]);
116    }
117
118    #[test]
119    fn test_fee_amount() {
120        let action = make_action();
121        assert_eq!(action.fee_amount(), 250);
122    }
123
124    #[test]
125    fn test_zero_fee_amount() {
126        let v0 = UnshieldTransitionActionV0 {
127            output_address: PlatformAddress::P2sh([0x00; 20]),
128            amount: 0,
129            notes: vec![],
130            anchor: [0x00; 32],
131            fee_amount: 0,
132            current_total_balance: 0,
133            chargeable_failure: false,
134        };
135        let action = UnshieldTransitionAction::from(v0);
136        assert_eq!(action.amount(), 0);
137        assert_eq!(action.fee_amount(), 0);
138        assert!(action.notes().is_empty());
139    }
140
141    #[test]
142    fn test_clone() {
143        let action = make_action();
144        let cloned = action.clone();
145        assert_eq!(cloned.amount(), 7500);
146        assert_eq!(cloned.fee_amount(), 250);
147        assert_eq!(*cloned.anchor(), [0x55; 32]);
148    }
149
150    #[test]
151    fn test_debug() {
152        let action = make_action();
153        let debug_str = format!("{:?}", action);
154        assert!(debug_str.contains("V0"));
155    }
156}