Skip to main content

drive/state_transition_action/shielded/shield/
mod.rs

1/// transformer
2pub mod transformer;
3/// v0
4pub mod v0;
5
6use crate::state_transition_action::shielded::shield::v0::ShieldTransitionActionV0;
7use crate::state_transition_action::shielded::ShieldedActionNote;
8use derive_more::From;
9use dpp::address_funds::{AddressFundsFeeStrategy, PlatformAddress};
10use dpp::fee::Credits;
11use dpp::prelude::{AddressNonce, UserFeeIncrease};
12use std::collections::BTreeMap;
13
14/// Shield transition action
15#[derive(Debug, Clone, From)]
16pub enum ShieldTransitionAction {
17    /// v0
18    V0(ShieldTransitionActionV0),
19}
20
21impl ShieldTransitionAction {
22    /// Get inputs with remaining balance
23    pub fn inputs_with_remaining_balance(
24        &self,
25    ) -> &BTreeMap<PlatformAddress, (AddressNonce, Credits)> {
26        match self {
27            ShieldTransitionAction::V0(transition) => &transition.inputs_with_remaining_balance,
28        }
29    }
30    /// Get the shield amount
31    pub fn shield_amount(&self) -> Credits {
32        match self {
33            ShieldTransitionAction::V0(transition) => transition.shield_amount,
34        }
35    }
36    /// Get notes
37    pub fn notes(&self) -> &[ShieldedActionNote] {
38        match self {
39            ShieldTransitionAction::V0(transition) => &transition.notes,
40        }
41    }
42    /// fee multiplier
43    pub fn user_fee_increase(&self) -> UserFeeIncrease {
44        match self {
45            ShieldTransitionAction::V0(transition) => transition.user_fee_increase,
46        }
47    }
48    /// fee strategy
49    pub fn fee_strategy(&self) -> &AddressFundsFeeStrategy {
50        match self {
51            ShieldTransitionAction::V0(transition) => &transition.fee_strategy,
52        }
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59    use dpp::address_funds::fee_strategy::AddressFundsFeeStrategyStep;
60
61    fn make_note() -> ShieldedActionNote {
62        ShieldedActionNote {
63            nullifier: [0x11; 32],
64            cmx: [0x22; 32],
65            cv_net: [0x22; 32],
66            encrypted_note: vec![0xAB, 0xCD, 0xEF],
67        }
68    }
69
70    fn make_action() -> ShieldTransitionAction {
71        let addr = PlatformAddress::P2pkh([0xAA; 20]);
72        let mut inputs = BTreeMap::new();
73        inputs.insert(addr, (3_u32, 10000_u64));
74
75        let v0 = ShieldTransitionActionV0 {
76            inputs_with_remaining_balance: inputs,
77            shield_amount: 5000,
78            notes: vec![make_note(), make_note()],
79            fee_strategy: vec![AddressFundsFeeStrategyStep::DeductFromInput(0)],
80            user_fee_increase: 2,
81            current_total_balance: 50000,
82        };
83        ShieldTransitionAction::from(v0)
84    }
85
86    #[test]
87    fn test_from_v0() {
88        let action = make_action();
89        assert!(matches!(action, ShieldTransitionAction::V0(_)));
90    }
91
92    #[test]
93    fn test_inputs_with_remaining_balance() {
94        let action = make_action();
95        let inputs = action.inputs_with_remaining_balance();
96        assert_eq!(inputs.len(), 1);
97        let addr = PlatformAddress::P2pkh([0xAA; 20]);
98        let (nonce, balance) = inputs.get(&addr).unwrap();
99        assert_eq!(*nonce, 3);
100        assert_eq!(*balance, 10000);
101    }
102
103    #[test]
104    fn test_shield_amount() {
105        let action = make_action();
106        assert_eq!(action.shield_amount(), 5000);
107    }
108
109    #[test]
110    fn test_notes() {
111        let action = make_action();
112        let notes = action.notes();
113        assert_eq!(notes.len(), 2);
114        assert_eq!(notes[0].nullifier, [0x11; 32]);
115        assert_eq!(notes[0].cmx, [0x22; 32]);
116        assert_eq!(notes[0].encrypted_note, vec![0xAB, 0xCD, 0xEF]);
117    }
118
119    #[test]
120    fn test_user_fee_increase() {
121        let action = make_action();
122        assert_eq!(action.user_fee_increase(), 2);
123    }
124
125    #[test]
126    fn test_fee_strategy() {
127        let action = make_action();
128        let strategy = action.fee_strategy();
129        assert_eq!(strategy.len(), 1);
130        assert!(matches!(
131            strategy[0],
132            AddressFundsFeeStrategyStep::DeductFromInput(0)
133        ));
134    }
135
136    #[test]
137    fn test_empty_notes() {
138        let v0 = ShieldTransitionActionV0 {
139            inputs_with_remaining_balance: BTreeMap::new(),
140            shield_amount: 0,
141            notes: vec![],
142            fee_strategy: vec![],
143            user_fee_increase: 0,
144            current_total_balance: 0,
145        };
146        let action = ShieldTransitionAction::from(v0);
147        assert!(action.notes().is_empty());
148        assert_eq!(action.shield_amount(), 0);
149    }
150
151    #[test]
152    fn test_clone() {
153        let action = make_action();
154        let cloned = action.clone();
155        assert_eq!(cloned.shield_amount(), 5000);
156        assert_eq!(cloned.notes().len(), 2);
157        assert_eq!(cloned.user_fee_increase(), 2);
158    }
159
160    #[test]
161    fn test_debug() {
162        let action = make_action();
163        let debug_str = format!("{:?}", action);
164        assert!(debug_str.contains("V0"));
165    }
166}