1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use super::{
    ByteReader, ByteWriter, Deserializable, DeserializationError, Felt, Note, NoteId, NoteMetadata,
    Serializable, Word,
};
use crate::utils::collections::*;

// NOTE ENVELOPE
// ================================================================================================

/// Holds information that is relevant to the recipient of a note.
///
/// Contains:
/// - note_id: ID of the note that was created
/// - note_metadata: metadata of the note that was created. Metadata is padded with ZERO such that
///   it is four elements in size (a word). The metadata includes the following elements:
///     - sender
///     - tag
///     - num assets
///     - ZERO
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct NoteEnvelope {
    note_id: NoteId,
    note_metadata: NoteMetadata,
}

impl NoteEnvelope {
    /// Creates a new [NoteEnvelope] object.
    pub fn new(note_id: NoteId, note_metadata: NoteMetadata) -> Self {
        Self { note_id, note_metadata }
    }

    /// Returns a unique identifier of the note that was created.
    pub fn note_id(&self) -> NoteId {
        self.note_id
    }

    /// Returns the metadata of the note that was created.
    pub fn metadata(&self) -> &NoteMetadata {
        &self.note_metadata
    }
}

impl From<NoteEnvelope> for [Felt; 8] {
    fn from(note_envelope: NoteEnvelope) -> Self {
        (&note_envelope).into()
    }
}

impl From<NoteEnvelope> for [Word; 2] {
    fn from(note_envelope: NoteEnvelope) -> Self {
        (&note_envelope).into()
    }
}

impl From<NoteEnvelope> for [u8; 64] {
    fn from(note_envelope: NoteEnvelope) -> Self {
        (&note_envelope).into()
    }
}

impl From<&NoteEnvelope> for [Felt; 8] {
    fn from(note_envelope: &NoteEnvelope) -> Self {
        let mut elements: [Felt; 8] = Default::default();
        elements[..4].copy_from_slice(note_envelope.note_id.as_elements());
        elements[4..].copy_from_slice(&Word::from(note_envelope.metadata()));
        elements
    }
}

impl From<&NoteEnvelope> for [Word; 2] {
    fn from(note_envelope: &NoteEnvelope) -> Self {
        let mut elements: [Word; 2] = Default::default();
        elements[0].copy_from_slice(note_envelope.note_id.as_elements());
        elements[1].copy_from_slice(&Word::from(note_envelope.metadata()));
        elements
    }
}

impl From<&NoteEnvelope> for [u8; 64] {
    fn from(note_envelope: &NoteEnvelope) -> Self {
        let mut elements: [u8; 64] = [0; 64];
        let note_metadata_bytes = Word::from(note_envelope.metadata())
            .iter()
            .flat_map(|x| x.as_int().to_le_bytes())
            .collect::<Vec<u8>>();
        elements[..32].copy_from_slice(&note_envelope.note_id.as_bytes());
        elements[32..].copy_from_slice(&note_metadata_bytes);
        elements
    }
}

impl From<Note> for NoteEnvelope {
    fn from(note: Note) -> Self {
        (&note).into()
    }
}

impl From<&Note> for NoteEnvelope {
    fn from(note: &Note) -> Self {
        Self {
            note_id: note.id(),
            note_metadata: *note.metadata(),
        }
    }
}

// SERIALIZATION
// ================================================================================================

impl Serializable for NoteEnvelope {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        self.note_id.write_into(target);
        self.note_metadata.write_into(target);
    }
}

impl Deserializable for NoteEnvelope {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        let note_id = NoteId::read_from(source)?;
        let note_metadata = NoteMetadata::read_from(source)?;

        Ok(Self { note_id, note_metadata })
    }
}