miden_objects/note/
inputs.rs1use alloc::vec::Vec;
2
3use super::{
4 ByteReader, ByteWriter, Deserializable, DeserializationError, Digest, Felt, Hasher, NoteError,
5 Serializable, WORD_SIZE, ZERO,
6};
7use crate::MAX_INPUTS_PER_NOTE;
8
9#[derive(Clone, Debug)]
21pub struct NoteInputs {
22 values: Vec<Felt>,
23 hash: Digest,
24}
25
26impl NoteInputs {
27 pub fn new(values: Vec<Felt>) -> Result<Self, NoteError> {
35 if values.len() > MAX_INPUTS_PER_NOTE {
36 return Err(NoteError::TooManyInputs(values.len()));
37 }
38
39 Ok(pad_and_build(values))
40 }
41
42 pub fn commitment(&self) -> Digest {
47 self.hash
48 }
49
50 pub fn num_values(&self) -> u8 {
54 const _: () = assert!(MAX_INPUTS_PER_NOTE <= u8::MAX as usize);
55 debug_assert!(
56 self.values.len() < MAX_INPUTS_PER_NOTE,
57 "The constructor should have checked the number of inputs"
58 );
59 self.values.len() as u8
60 }
61
62 pub fn values(&self) -> &[Felt] {
64 &self.values
65 }
66
67 pub fn format_for_advice(&self) -> Vec<Felt> {
75 let mut padded = pad_inputs(&self.values);
77 padded.insert(0, self.num_values().into());
78 padded
79 }
80}
81
82impl Default for NoteInputs {
83 fn default() -> Self {
84 pad_and_build(vec![])
85 }
86}
87
88impl PartialEq for NoteInputs {
89 fn eq(&self, other: &Self) -> bool {
90 let NoteInputs { values: inputs, hash: _ } = self;
91 inputs == &other.values
92 }
93}
94
95impl Eq for NoteInputs {}
96
97impl From<NoteInputs> for Vec<Felt> {
101 fn from(value: NoteInputs) -> Self {
102 value.values
103 }
104}
105
106impl TryFrom<Vec<Felt>> for NoteInputs {
107 type Error = NoteError;
108
109 fn try_from(value: Vec<Felt>) -> Result<Self, Self::Error> {
110 NoteInputs::new(value)
111 }
112}
113
114fn pad_inputs(inputs: &[Felt]) -> Vec<Felt> {
119 const BLOCK_SIZE: usize = WORD_SIZE * 2;
120
121 let padded_len = inputs.len().next_multiple_of(BLOCK_SIZE);
122 let mut padded_inputs = Vec::with_capacity(padded_len);
123 padded_inputs.extend(inputs.iter());
124 padded_inputs.resize(padded_len, ZERO);
125
126 padded_inputs
127}
128
129fn pad_and_build(values: Vec<Felt>) -> NoteInputs {
131 let hash = {
132 let padded_values = pad_inputs(&values);
133 Hasher::hash_elements(&padded_values)
134 };
135
136 NoteInputs { values, hash }
137}
138
139impl Serializable for NoteInputs {
143 fn write_into<W: ByteWriter>(&self, target: &mut W) {
144 let NoteInputs { values, hash: _hash } = self;
145 target.write_u8(values.len().try_into().expect("inputs len is not a u8 value"));
146 target.write_many(values);
147 }
148}
149
150impl Deserializable for NoteInputs {
151 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
152 let num_values = source.read_u8()? as usize;
153 let values = source.read_many::<Felt>(num_values)?;
154 Self::new(values).map_err(|v| DeserializationError::InvalidValue(format!("{v}")))
155 }
156}
157
158#[cfg(test)]
162mod tests {
163 use miden_crypto::utils::Deserializable;
164
165 use super::{Felt, NoteInputs, Serializable};
166
167 #[test]
168 fn test_input_ordering() {
169 let inputs = vec![Felt::new(1), Felt::new(2), Felt::new(3)];
171 let expected_ordering = vec![Felt::new(1), Felt::new(2), Felt::new(3)];
173
174 let note_inputs = NoteInputs::new(inputs).expect("note created should succeed");
175 assert_eq!(&expected_ordering, ¬e_inputs.values);
176 }
177
178 #[test]
179 fn test_input_serialization() {
180 let inputs = vec![Felt::new(1), Felt::new(2), Felt::new(3)];
181 let note_inputs = NoteInputs::new(inputs).unwrap();
182
183 let bytes = note_inputs.to_bytes();
184 let parsed_note_inputs = NoteInputs::read_from_bytes(&bytes).unwrap();
185 assert_eq!(note_inputs, parsed_note_inputs);
186 }
187}