drive/verify/shielded/verify_shielded_encrypted_notes/mod.rs
1mod v0;
2
3use crate::drive::Drive;
4use crate::error::drive::DriveError;
5use crate::error::Error;
6use crate::verify::RootHash;
7use dpp::version::PlatformVersion;
8
9/// On-wire size of the Orchard `TransmittedNoteCiphertext` with Dash's 36-byte
10/// memo: `epk(32) + enc_ciphertext(104) + out_ciphertext(80)`. grovedb's
11/// commitment tree size-locks the stored ciphertext to this length, so every
12/// well-formed note item is exactly `32 + 32 + 32 + 216 = 312` bytes.
13pub const SHIELDED_ENCRYPTED_NOTE_LEN: usize = 216;
14
15/// A single shielded note item recovered from a verified
16/// `GetShieldedEncryptedNotes` proof: the fixed-layout bytes copied out of the
17/// stored `cmx || nullifier || cv_net || encrypted_note` commitment-tree item.
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct VerifiedShieldedEncryptedNote {
20 /// Note commitment.
21 pub cmx: [u8; 32],
22 /// Nullifier of the note spent in this action — Orchard reuses it as this
23 /// output note's ρ (rho) for trial decryption. Not the nullifier of the
24 /// note committed by `cmx`.
25 pub nullifier: [u8; 32],
26 /// Orchard value commitment (used for OVK outgoing-note recovery).
27 pub cv_net: [u8; 32],
28 /// Encrypted note ciphertext (`epk || enc_ciphertext || out_ciphertext`).
29 pub encrypted_note: [u8; SHIELDED_ENCRYPTED_NOTE_LEN],
30}
31
32impl Drive {
33 /// Verifies a proof for shielded encrypted notes.
34 ///
35 /// Returns `(root_hash, notes, total_count)`. `total_count` is the
36 /// on-chain total number of notes in the shielded `CommitmentTree`,
37 /// extracted from the SAME proof (the parent CommitmentTree element is
38 /// always present in a note-fetch proof) — wallets get the sync
39 /// progress-bar denominator for free on every chunk fetch.
40 pub fn verify_shielded_encrypted_notes(
41 proof: &[u8],
42 start_index: u64,
43 count: u32,
44 max_elements: u32,
45 verify_subset_of_proof: bool,
46 platform_version: &PlatformVersion,
47 ) -> Result<(RootHash, Vec<VerifiedShieldedEncryptedNote>, u64), Error> {
48 match platform_version
49 .drive
50 .methods
51 .verify
52 .shielded
53 .verify_shielded_encrypted_notes
54 {
55 0 => Self::verify_shielded_encrypted_notes_v0(
56 proof,
57 start_index,
58 count,
59 max_elements,
60 verify_subset_of_proof,
61 platform_version,
62 ),
63 version => Err(Error::Drive(DriveError::UnknownVersionMismatch {
64 method: "verify_shielded_encrypted_notes".to_string(),
65 known_versions: vec![0],
66 received: version,
67 })),
68 }
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75 use dpp::version::PlatformVersion;
76
77 #[test]
78 fn test_verify_shielded_encrypted_notes_unknown_version_mismatch() {
79 let mut platform_version = PlatformVersion::latest().clone();
80 platform_version
81 .drive
82 .methods
83 .verify
84 .shielded
85 .verify_shielded_encrypted_notes = 255;
86
87 let result = Drive::verify_shielded_encrypted_notes(&[], 0, 0, 0, false, &platform_version);
88
89 assert!(
90 matches!(
91 result,
92 Err(Error::Drive(DriveError::UnknownVersionMismatch { .. }))
93 ),
94 "expected UnknownVersionMismatch, got {:?}",
95 result,
96 );
97 }
98}