miden_objects/note/
nullifier.rs1use alloc::string::String;
2use core::fmt::{Debug, Display, Formatter};
3
4use super::{
5 ByteReader, ByteWriter, Deserializable, DeserializationError, Digest, Felt, Hasher,
6 NoteDetails, Serializable, Word, WORD_SIZE, ZERO,
7};
8use crate::utils::{hex_to_bytes, HexParseError};
9
10#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
25pub struct Nullifier(Digest);
26
27impl Nullifier {
28 pub fn new(
30 script_hash: Digest,
31 inputs_hash: Digest,
32 asset_hash: Digest,
33 serial_num: Word,
34 ) -> Self {
35 let mut elements = [ZERO; 4 * WORD_SIZE];
36 elements[..4].copy_from_slice(&serial_num);
37 elements[4..8].copy_from_slice(script_hash.as_elements());
38 elements[8..12].copy_from_slice(inputs_hash.as_elements());
39 elements[12..].copy_from_slice(asset_hash.as_elements());
40 Self(Hasher::hash_elements(&elements))
41 }
42
43 pub fn as_elements(&self) -> &[Felt] {
45 self.0.as_elements()
46 }
47
48 pub fn most_significant_felt(&self) -> Felt {
50 self.as_elements()[3]
51 }
52
53 pub fn inner(&self) -> Digest {
55 self.0
56 }
57
58 pub fn from_hex(hex_value: &str) -> Result<Self, HexParseError> {
61 hex_to_bytes(hex_value).and_then(|bytes: [u8; 32]| {
62 let digest = Digest::try_from(bytes)?;
63 Ok(digest.into())
64 })
65 }
66
67 pub fn to_hex(&self) -> String {
69 self.0.to_hex()
70 }
71}
72
73impl Display for Nullifier {
74 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
75 f.write_str(&self.to_hex())
76 }
77}
78
79impl Debug for Nullifier {
80 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
81 Display::fmt(self, f)
82 }
83}
84
85impl From<&NoteDetails> for Nullifier {
89 fn from(note: &NoteDetails) -> Self {
90 Self::new(
91 note.script().hash(),
92 note.inputs().commitment(),
93 note.assets().commitment(),
94 note.serial_num(),
95 )
96 }
97}
98
99impl From<Word> for Nullifier {
100 fn from(value: Word) -> Self {
101 Self(value.into())
102 }
103}
104
105impl From<Digest> for Nullifier {
106 fn from(value: Digest) -> Self {
107 Self(value)
108 }
109}
110
111impl From<Nullifier> for Word {
115 fn from(nullifier: Nullifier) -> Self {
116 nullifier.0.into()
117 }
118}
119
120impl From<Nullifier> for [u8; 32] {
121 fn from(nullifier: Nullifier) -> Self {
122 nullifier.0.into()
123 }
124}
125
126impl From<&Nullifier> for Word {
127 fn from(nullifier: &Nullifier) -> Self {
128 nullifier.0.into()
129 }
130}
131
132impl From<&Nullifier> for [u8; 32] {
133 fn from(nullifier: &Nullifier) -> Self {
134 nullifier.0.into()
135 }
136}
137
138impl Serializable for Nullifier {
142 fn write_into<W: ByteWriter>(&self, target: &mut W) {
143 target.write_bytes(&self.0.to_bytes());
144 }
145}
146
147impl Deserializable for Nullifier {
148 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
149 let nullifier = Digest::read_from(source)?;
150 Ok(Self(nullifier))
151 }
152}
153
154#[cfg(test)]
158mod tests {
159 use crate::note::Nullifier;
160
161 #[test]
162 fn test_from_hex_and_back() {
163 let nullifier_hex = "0x41e7dbbc8ce63ec25cf2d76d76162f16ef8fd1195288171f5e5a3e178222f6d2";
164 let nullifier = Nullifier::from_hex(nullifier_hex).unwrap();
165
166 assert_eq!(nullifier_hex, nullifier.to_hex());
167 }
168}