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
126
127
128
129
130
131
132
133
use alloc::vec::Vec;

use super::{
    ByteReader, ByteWriter, Deserializable, DeserializationError, Digest, Felt, NoteId,
    NoteMetadata, Serializable, Word,
};
use crate::Hasher;

// NOTE HEADER
// ================================================================================================

/// Holds the strictly required, public information of a note.
///
/// See [NoteId] and [NoteMetadata] for additional details.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct NoteHeader {
    note_id: NoteId,
    note_metadata: NoteMetadata,
}

impl NoteHeader {
    /// Returns a new [NoteHeader] instantiated from the specified note ID and metadata.
    pub fn new(note_id: NoteId, note_metadata: NoteMetadata) -> Self {
        Self { note_id, note_metadata }
    }

    /// Returns the note's identifier.
    ///
    /// The [NoteId] value is both an unique identifier and a commitment to the note.
    pub fn id(&self) -> NoteId {
        self.note_id
    }

    /// Returns the note's metadata.
    pub fn metadata(&self) -> &NoteMetadata {
        &self.note_metadata
    }

    /// Returns a commitment to the note and its metadata.
    ///
    /// > hash(NOTE_ID || NOTE_METADATA)
    ///
    /// This value is used primarily for authenticating notes consumed when they are consumed
    /// in a transaction.
    pub fn hash(&self) -> Digest {
        compute_note_hash(self.id(), self.metadata())
    }
}

// UTILITIES
// ================================================================================================

/// Returns a commitment to the note and its metadata.
///
/// > hash(NOTE_ID || NOTE_METADATA)
///
/// This value is used primarily for authenticating notes consumed when they are consumed
/// in a transaction.
pub fn compute_note_hash(id: NoteId, metadata: &NoteMetadata) -> Digest {
    Hasher::merge(&[id.inner(), Word::from(metadata).into()])
}

// CONVERSIONS FROM NOTE HEADER
// ================================================================================================

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

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

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

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

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

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

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

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

impl Deserializable for NoteHeader {
    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 })
    }
}