miden_objects/note/
inputs.rs1use alloc::vec::Vec;
2
3use crate::{
4 Digest, Felt, Hasher, MAX_INPUTS_PER_NOTE, WORD_SIZE, ZERO,
5 errors::NoteError,
6 utils::serde::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
7};
8
9#[derive(Clone, Debug)]
21pub struct NoteInputs {
22 values: Vec<Felt>,
23 commitment: 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.commitment
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 pad_inputs(&self.values)
76 }
77}
78
79impl Default for NoteInputs {
80 fn default() -> Self {
81 pad_and_build(vec![])
82 }
83}
84
85impl PartialEq for NoteInputs {
86 fn eq(&self, other: &Self) -> bool {
87 let NoteInputs { values: inputs, commitment: _ } = self;
88 inputs == &other.values
89 }
90}
91
92impl Eq for NoteInputs {}
93
94impl From<NoteInputs> for Vec<Felt> {
98 fn from(value: NoteInputs) -> Self {
99 value.values
100 }
101}
102
103impl TryFrom<Vec<Felt>> for NoteInputs {
104 type Error = NoteError;
105
106 fn try_from(value: Vec<Felt>) -> Result<Self, Self::Error> {
107 NoteInputs::new(value)
108 }
109}
110
111fn pad_inputs(inputs: &[Felt]) -> Vec<Felt> {
116 const BLOCK_SIZE: usize = WORD_SIZE * 2;
117
118 let padded_len = inputs.len().next_multiple_of(BLOCK_SIZE);
119 let mut padded_inputs = Vec::with_capacity(padded_len);
120 padded_inputs.extend(inputs.iter());
121 padded_inputs.resize(padded_len, ZERO);
122
123 padded_inputs
124}
125
126fn pad_and_build(values: Vec<Felt>) -> NoteInputs {
128 let commitment = {
129 let padded_values = pad_inputs(&values);
130 Hasher::hash_elements(&padded_values)
131 };
132
133 NoteInputs { values, commitment }
134}
135
136impl Serializable for NoteInputs {
140 fn write_into<W: ByteWriter>(&self, target: &mut W) {
141 let NoteInputs { values, commitment: _commitment } = self;
142 target.write_u8(values.len().try_into().expect("inputs len is not a u8 value"));
143 target.write_many(values);
144 }
145}
146
147impl Deserializable for NoteInputs {
148 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
149 let num_values = source.read_u8()? as usize;
150 let values = source.read_many::<Felt>(num_values)?;
151 Self::new(values).map_err(|v| DeserializationError::InvalidValue(format!("{v}")))
152 }
153}
154
155#[cfg(test)]
159mod tests {
160 use miden_crypto::utils::Deserializable;
161
162 use super::{Felt, NoteInputs, Serializable};
163
164 #[test]
165 fn test_input_ordering() {
166 let inputs = vec![Felt::new(1), Felt::new(2), Felt::new(3)];
168 let expected_ordering = vec![Felt::new(1), Felt::new(2), Felt::new(3)];
170
171 let note_inputs = NoteInputs::new(inputs).expect("note created should succeed");
172 assert_eq!(&expected_ordering, ¬e_inputs.values);
173 }
174
175 #[test]
176 fn test_input_serialization() {
177 let inputs = vec![Felt::new(1), Felt::new(2), Felt::new(3)];
178 let note_inputs = NoteInputs::new(inputs).unwrap();
179
180 let bytes = note_inputs.to_bytes();
181 let parsed_note_inputs = NoteInputs::read_from_bytes(&bytes).unwrap();
182 assert_eq!(note_inputs, parsed_note_inputs);
183 }
184}