miden_protocol/note/
nullifier.rs1use alloc::string::String;
2use core::fmt::{Debug, Display, Formatter};
3
4use miden_core::WORD_SIZE;
5use miden_crypto::WordError;
6use miden_protocol_macros::WordWrapper;
7
8use super::{
9 ByteReader,
10 ByteWriter,
11 Deserializable,
12 DeserializationError,
13 Felt,
14 Hasher,
15 NoteDetails,
16 Serializable,
17 Word,
18 ZERO,
19};
20
21const NULLIFIER_PREFIX_SHIFT: u8 = 48;
25
26#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, WordWrapper)]
41pub struct Nullifier(Word);
42
43impl Nullifier {
44 pub fn new(
46 script_root: Word,
47 storage_commitment: Word,
48 asset_commitment: Word,
49 serial_num: Word,
50 ) -> Self {
51 let mut elements = [ZERO; 4 * WORD_SIZE];
52 elements[..4].copy_from_slice(serial_num.as_elements());
53 elements[4..8].copy_from_slice(script_root.as_elements());
54 elements[8..12].copy_from_slice(storage_commitment.as_elements());
55 elements[12..].copy_from_slice(asset_commitment.as_elements());
56 Self(Hasher::hash_elements(&elements))
57 }
58
59 pub fn most_significant_felt(&self) -> Felt {
61 self.as_elements()[3]
62 }
63
64 pub fn prefix(&self) -> u16 {
68 (self.as_word()[3].as_canonical_u64() >> NULLIFIER_PREFIX_SHIFT) as u16
69 }
70
71 pub fn from_hex(hex_value: &str) -> Result<Self, WordError> {
76 Word::try_from(hex_value).map(Self::from_raw)
77 }
78
79 #[cfg(any(feature = "testing", test))]
80 pub fn dummy(n: u64) -> Self {
81 Self(Word::new([Felt::ZERO, Felt::ZERO, Felt::ZERO, Felt::new(n)]))
82 }
83}
84
85impl Display for Nullifier {
86 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
87 f.write_str(&self.to_hex())
88 }
89}
90
91impl Debug for Nullifier {
92 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
93 Display::fmt(self, f)
94 }
95}
96
97impl From<&NoteDetails> for Nullifier {
101 fn from(note: &NoteDetails) -> Self {
102 Self::new(
103 note.script().root(),
104 note.storage().commitment(),
105 note.assets().commitment(),
106 note.serial_num(),
107 )
108 }
109}
110
111impl Serializable for Nullifier {
115 fn write_into<W: ByteWriter>(&self, target: &mut W) {
116 target.write_bytes(&self.0.to_bytes());
117 }
118
119 fn get_size_hint(&self) -> usize {
120 Word::SERIALIZED_SIZE
121 }
122}
123
124impl Deserializable for Nullifier {
125 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
126 let nullifier = Word::read_from(source)?;
127 Ok(Self(nullifier))
128 }
129}
130
131#[cfg(test)]
135mod tests {
136 use crate::note::Nullifier;
137
138 #[test]
139 fn test_from_hex_and_back() {
140 let nullifier_hex = "0x41e7dbbc8ce63ec25cf2d76d76162f16ef8fd1195288171f5e5a3e178222f6d2";
141 let nullifier = Nullifier::from_hex(nullifier_hex).unwrap();
142
143 assert_eq!(nullifier_hex, nullifier.to_hex());
144 }
145}