7777
7878/// Decodes the plaintext from a private note message (i.e. one of type [`PRIVATE_NOTE_MSG_TYPE_ID`]).
7979///
80- /// Returns `None` if `msg_content` has too few fields. This plaintext is meant to have originated
81- /// from [`encode_private_note_message`].
80+ /// Returns `None` if `msg_content` is too short to contain the reserved fields. This plaintext is meant to have
81+ /// originated from [`encode_private_note_message`].
8282///
8383/// Note that while [`encode_private_note_message`] returns a fixed-size array, this function takes a [`BoundedVec`]
8484/// instead. This is because when decoding we're typically processing runtime-sized plaintexts, more specifically,
@@ -87,7 +87,7 @@ pub(crate) unconstrained fn decode_private_note_message(
8787 msg_metadata : u64 ,
8888 msg_content : BoundedVec <Field , MAX_MESSAGE_CONTENT_LEN >,
8989) -> Option <(Field , AztecAddress , Field , Field , BoundedVec <Field , MAX_NOTE_PACKED_LEN >)> {
90- if msg_content .len () <= PRIVATE_NOTE_MSG_PLAINTEXT_RESERVED_FIELDS_LEN {
90+ if msg_content .len () < PRIVATE_NOTE_MSG_PLAINTEXT_RESERVED_FIELDS_LEN {
9191 Option ::none ()
9292 } else {
9393 let note_type_id = msg_metadata as Field ; // TODO: make note type id not be a full field
@@ -117,7 +117,7 @@ mod test {
117117 },
118118 note::note_interface::NoteType ,
119119 };
120- use crate::protocol:: {address::AztecAddress , traits ::{FromField , Packable }};
120+ use crate::protocol:: {address::AztecAddress , traits ::{FromField , Packable , ToField }};
121121 use crate::test::mocks::mock_note::MockNote ;
122122
123123 global VALUE : Field = 7 ;
@@ -197,15 +197,53 @@ mod test {
197197 let _ = encode_private_note_message (note , OWNER , STORAGE_SLOT , RANDOMNESS );
198198 }
199199
200+ #[derive(Packable)]
201+ struct EmptyNote {}
202+
203+ impl NoteType for EmptyNote {
204+ fn get_id () -> Field {
205+ 0
206+ }
207+ }
208+
209+ #[test]
210+ unconstrained fn encode_decode_empty_note () {
211+ let encoded = encode_private_note_message (EmptyNote {}, OWNER , STORAGE_SLOT , RANDOMNESS );
212+ let (msg_type_id , msg_metadata , msg_content ) = decode_message (BoundedVec ::from_array (encoded )).unwrap ();
213+
214+ assert_eq (msg_type_id , PRIVATE_NOTE_MSG_TYPE_ID );
215+
216+ let (note_type_id , owner , storage_slot , randomness , packed_note ) =
217+ decode_private_note_message (msg_metadata , msg_content ).unwrap ();
218+
219+ assert_eq (note_type_id , EmptyNote ::get_id ());
220+ assert_eq (owner , OWNER );
221+ assert_eq (storage_slot , STORAGE_SLOT );
222+ assert_eq (randomness , RANDOMNESS );
223+ assert_eq (packed_note .len (), 0 );
224+ }
225+
200226 #[test]
201227 unconstrained fn decode_empty_content_returns_none () {
202228 let empty = BoundedVec ::new ();
203229 assert (decode_private_note_message (0 , empty ).is_none ());
204230 }
205231
206232 #[test]
207- unconstrained fn decode_with_only_reserved_fields_returns_none () {
208- let content = BoundedVec ::from_array ([0 , 0 , 0 ]);
233+ unconstrained fn decode_with_fewer_than_reserved_fields_returns_none () {
234+ let content = BoundedVec ::from_array ([0 , 0 ]);
209235 assert (decode_private_note_message (0 , content ).is_none ());
210236 }
237+
238+ #[test]
239+ unconstrained fn decode_succeeds_with_only_reserved_fields () {
240+ let content = BoundedVec ::from_array ([OWNER .to_field (), STORAGE_SLOT , RANDOMNESS ]);
241+
242+ let (_ , owner , storage_slot , randomness , packed_note ) = decode_private_note_message (0 , content ).unwrap ();
243+
244+ assert_eq (owner , OWNER );
245+ assert_eq (storage_slot , STORAGE_SLOT );
246+ assert_eq (randomness , RANDOMNESS );
247+ assert_eq (packed_note .len (), 0 );
248+ }
211249}
0 commit comments