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
use alloc::vec::Vec;
use core::fmt::Debug;

use miden_crypto::Felt;

use super::{
    ByteReader, ByteWriter, Deserializable, DeserializationError, Digest, Hasher, NoteInputs,
    NoteScript, Serializable, Word,
};

/// Value that describes under which condition a note can be consumed.
///
/// The recipient is not an account address, instead it is a value that describes when a note
/// can be consumed. Because not all notes have predetermined consumer addresses, e.g. swap
/// notes can be consumed by anyone, the recipient is defined as the code and its inputs, that
/// when successfully executed results in the note's consumption.
///
/// Recipient is computed as:
///
/// > hash(hash(hash(serial_num, [0; 4]), script_hash), input_hash)
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct NoteRecipient {
    serial_num: Word,
    script: NoteScript,
    inputs: NoteInputs,
    digest: Digest,
}

impl NoteRecipient {
    pub fn new(serial_num: Word, script: NoteScript, inputs: NoteInputs) -> Self {
        let digest = compute_recipient_digest(serial_num, &script, &inputs);
        Self { serial_num, script, inputs, digest }
    }

    // PUBLIC ACCESSORS
    // --------------------------------------------------------------------------------------------

    /// The recipient's serial_num, the secret required to consume the note.
    pub fn serial_num(&self) -> Word {
        self.serial_num
    }

    /// The recipients's script which locks the assets of this note.
    pub fn script(&self) -> &NoteScript {
        &self.script
    }

    /// The recipient's inputs which customizes the script's behavior.
    pub fn inputs(&self) -> &NoteInputs {
        &self.inputs
    }

    /// The recipient's digest, which commits to its details.
    ///
    /// This is the public data required to create a note.
    pub fn digest(&self) -> Digest {
        self.digest
    }

    /// Returns the recipient encoded as [Felt]s.
    pub fn to_elements(&self) -> Vec<Felt> {
        let mut result = Vec::with_capacity(12);
        result.extend(self.inputs.commitment());
        result.extend(self.script.hash());
        result.extend(self.serial_num);
        result
    }
}

fn compute_recipient_digest(serial_num: Word, script: &NoteScript, inputs: &NoteInputs) -> Digest {
    let serial_num_hash = Hasher::merge(&[serial_num.into(), Digest::default()]);
    let merge_script = Hasher::merge(&[serial_num_hash, script.hash()]);
    Hasher::merge(&[merge_script, inputs.commitment()])
}

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

impl Serializable for NoteRecipient {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        let Self {
            script,
            inputs,
            serial_num,

            // These attributes don't have to be serialized, they can be re-computed from the rest
            // of the data
            digest: _,
        } = self;

        script.write_into(target);
        inputs.write_into(target);
        serial_num.write_into(target);
    }
}

impl Deserializable for NoteRecipient {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        let script = NoteScript::read_from(source)?;
        let inputs = NoteInputs::read_from(source)?;
        let serial_num = Word::read_from(source)?;

        Ok(Self::new(serial_num, script, inputs))
    }
}

#[cfg(feature = "serde")]
impl serde::Serialize for NoteRecipient {
    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let bytes = self.to_bytes();
        serializer.serialize_bytes(&bytes)
    }
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for NoteRecipient {
    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        let bytes: Vec<u8> = <Vec<u8> as serde::Deserialize>::deserialize(deserializer)?;
        Self::read_from_bytes(&bytes).map_err(serde::de::Error::custom)
    }
}