Skip to main content

drive/state_transition_action/shielded/
mod.rs

1/// IdentityCreateFromShieldedPool transition action
2pub mod identity_create_from_shielded_pool;
3/// Shield transition action
4pub mod shield;
5/// Shield from asset lock transition action
6pub mod shield_from_asset_lock;
7/// Shielded transfer transition action
8pub mod shielded_transfer;
9/// Shielded withdrawal transition action
10pub mod shielded_withdrawal;
11/// Unshield transition action
12pub mod unshield;
13
14use dpp::shielded::SerializedAction;
15
16/// One note from an Orchard action: the per-action fields that travel together.
17#[derive(Debug, Clone)]
18pub struct ShieldedActionNote {
19    /// Nullifier (needed for Rho derivation in trial decryption)
20    pub nullifier: [u8; 32],
21    /// Note commitment (cmx value)
22    pub cmx: [u8; 32],
23    /// Value commitment (cv_net). Stored unencrypted alongside the note so a
24    /// wallet can recover the value of an outgoing note via OVK decryption.
25    pub cv_net: [u8; 32],
26    /// Encrypted note ciphertext
27    pub encrypted_note: Vec<u8>,
28}
29
30impl From<&SerializedAction> for ShieldedActionNote {
31    fn from(action: &SerializedAction) -> Self {
32        ShieldedActionNote {
33            nullifier: action.nullifier,
34            cmx: action.cmx,
35            cv_net: action.cv_net,
36            encrypted_note: action.encrypted_note.clone(),
37        }
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[test]
46    fn test_shielded_action_note_fields() {
47        let note = ShieldedActionNote {
48            nullifier: [0xAA; 32],
49            cmx: [0xBB; 32],
50            cv_net: [0x22; 32],
51            encrypted_note: vec![1, 2, 3, 4],
52        };
53        assert_eq!(note.nullifier, [0xAA; 32]);
54        assert_eq!(note.cmx, [0xBB; 32]);
55        assert_eq!(note.cv_net, [0x22; 32]);
56        assert_eq!(note.encrypted_note, vec![1, 2, 3, 4]);
57    }
58
59    #[test]
60    fn test_from_serialized_action() {
61        let action = SerializedAction {
62            nullifier: [0x11; 32],
63            rk: [0x00; 32],
64            cmx: [0x22; 32],
65            encrypted_note: vec![0xAB, 0xCD],
66            cv_net: [0x33; 32],
67            spend_auth_sig: [0x00; 64],
68        };
69        let note = ShieldedActionNote::from(&action);
70        assert_eq!(note.nullifier, [0x11; 32]);
71        assert_eq!(note.cmx, [0x22; 32]);
72        assert_eq!(note.cv_net, [0x33; 32]);
73        assert_eq!(note.encrypted_note, vec![0xAB, 0xCD]);
74    }
75
76    #[test]
77    fn test_from_serialized_action_empty_encrypted_note() {
78        let action = SerializedAction {
79            nullifier: [0xFF; 32],
80            rk: [0x00; 32],
81            cmx: [0x00; 32],
82            encrypted_note: vec![],
83            cv_net: [0x44; 32],
84            spend_auth_sig: [0x00; 64],
85        };
86        let note = ShieldedActionNote::from(&action);
87        assert_eq!(note.nullifier, [0xFF; 32]);
88        assert_eq!(note.cv_net, [0x44; 32]);
89        assert!(note.encrypted_note.is_empty());
90    }
91
92    #[test]
93    fn test_clone() {
94        let note = ShieldedActionNote {
95            nullifier: [0xAA; 32],
96            cmx: [0xBB; 32],
97            cv_net: [0x22; 32],
98            encrypted_note: vec![5, 6, 7],
99        };
100        let cloned = note.clone();
101        assert_eq!(cloned.nullifier, note.nullifier);
102        assert_eq!(cloned.cmx, note.cmx);
103        assert_eq!(cloned.cv_net, note.cv_net);
104        assert_eq!(cloned.encrypted_note, note.encrypted_note);
105    }
106
107    #[test]
108    fn test_debug() {
109        let note = ShieldedActionNote {
110            nullifier: [0x00; 32],
111            cmx: [0x00; 32],
112            cv_net: [0x22; 32],
113            encrypted_note: vec![],
114        };
115        let debug_str = format!("{:?}", note);
116        assert!(debug_str.contains("ShieldedActionNote"));
117    }
118}