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}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    fn make_note() -> ShieldedActionNote {
57        ShieldedActionNote {
58            nullifier: [0x33; 32],
59            cmx: [0x44; 32],
60            encrypted_note: vec![0x10, 0x20],
61        }
62    }
63
64    fn make_action() -> UnshieldTransitionAction {
65        let v0 = UnshieldTransitionActionV0 {
66            output_address: PlatformAddress::P2pkh([0xBB; 20]),
67            amount: 7500,
68            notes: vec![make_note()],
69            anchor: [0x55; 32],
70            fee_amount: 250,
71            current_total_balance: 100000,
72        };
73        UnshieldTransitionAction::from(v0)
74    }
75
76    #[test]
77    fn test_from_v0() {
78        let action = make_action();
79        assert!(matches!(action, UnshieldTransitionAction::V0(_)));
80    }
81
82    #[test]
83    fn test_output_address() {
84        let action = make_action();
85        assert_eq!(*action.output_address(), PlatformAddress::P2pkh([0xBB; 20]));
86    }
87
88    #[test]
89    fn test_amount() {
90        let action = make_action();
91        assert_eq!(action.amount(), 7500);
92    }
93
94    #[test]
95    fn test_notes() {
96        let action = make_action();
97        let notes = action.notes();
98        assert_eq!(notes.len(), 1);
99        assert_eq!(notes[0].nullifier, [0x33; 32]);
100        assert_eq!(notes[0].cmx, [0x44; 32]);
101    }
102
103    #[test]
104    fn test_anchor() {
105        let action = make_action();
106        assert_eq!(*action.anchor(), [0x55; 32]);
107    }
108
109    #[test]
110    fn test_fee_amount() {
111        let action = make_action();
112        assert_eq!(action.fee_amount(), 250);
113    }
114
115    #[test]
116    fn test_zero_fee_amount() {
117        let v0 = UnshieldTransitionActionV0 {
118            output_address: PlatformAddress::P2sh([0x00; 20]),
119            amount: 0,
120            notes: vec![],
121            anchor: [0x00; 32],
122            fee_amount: 0,
123            current_total_balance: 0,
124        };
125        let action = UnshieldTransitionAction::from(v0);
126        assert_eq!(action.amount(), 0);
127        assert_eq!(action.fee_amount(), 0);
128        assert!(action.notes().is_empty());
129    }
130
131    #[test]
132    fn test_clone() {
133        let action = make_action();
134        let cloned = action.clone();
135        assert_eq!(cloned.amount(), 7500);
136        assert_eq!(cloned.fee_amount(), 250);
137        assert_eq!(*cloned.anchor(), [0x55; 32]);
138    }
139
140    #[test]
141    fn test_debug() {
142        let action = make_action();
143        let debug_str = format!("{:?}", action);
144        assert!(debug_str.contains("V0"));
145    }
146}