miden_objects/note/
recipient.rs

1use core::fmt::Debug;
2
3use super::{
4    ByteReader,
5    ByteWriter,
6    Deserializable,
7    DeserializationError,
8    Hasher,
9    NoteInputs,
10    NoteScript,
11    Serializable,
12    Word,
13};
14
15/// Value that describes under which condition a note can be consumed.
16///
17/// The recipient is not an account address, instead it is a value that describes when a note
18/// can be consumed. Because not all notes have predetermined consumer addresses, e.g. swap
19/// notes can be consumed by anyone, the recipient is defined as the code and its inputs, that
20/// when successfully executed results in the note's consumption.
21///
22/// Recipient is computed as:
23///
24/// > hash(hash(hash(serial_num, [0; 4]), script_root), input_commitment)
25#[derive(Clone, Debug, PartialEq, Eq)]
26pub struct NoteRecipient {
27    serial_num: Word,
28    script: NoteScript,
29    inputs: NoteInputs,
30    digest: Word,
31}
32
33impl NoteRecipient {
34    pub fn new(serial_num: Word, script: NoteScript, inputs: NoteInputs) -> Self {
35        let digest = compute_recipient_digest(serial_num, &script, &inputs);
36        Self { serial_num, script, inputs, digest }
37    }
38
39    // PUBLIC ACCESSORS
40    // --------------------------------------------------------------------------------------------
41
42    /// The recipient's serial_num, the secret required to consume the note.
43    pub fn serial_num(&self) -> Word {
44        self.serial_num
45    }
46
47    /// The recipients's script which locks the assets of this note.
48    pub fn script(&self) -> &NoteScript {
49        &self.script
50    }
51
52    /// The recipient's inputs which customizes the script's behavior.
53    pub fn inputs(&self) -> &NoteInputs {
54        &self.inputs
55    }
56
57    /// The recipient's digest, which commits to its details.
58    ///
59    /// This is the public data required to create a note.
60    pub fn digest(&self) -> Word {
61        self.digest
62    }
63}
64
65fn compute_recipient_digest(serial_num: Word, script: &NoteScript, inputs: &NoteInputs) -> Word {
66    let serial_num_hash = Hasher::merge(&[serial_num, Word::empty()]);
67    let merge_script = Hasher::merge(&[serial_num_hash, script.root()]);
68    Hasher::merge(&[merge_script, inputs.commitment()])
69}
70
71// SERIALIZATION
72// ================================================================================================
73
74impl Serializable for NoteRecipient {
75    fn write_into<W: ByteWriter>(&self, target: &mut W) {
76        let Self {
77            script,
78            inputs,
79            serial_num,
80
81            // These attributes don't have to be serialized, they can be re-computed from the rest
82            // of the data
83            digest: _,
84        } = self;
85
86        script.write_into(target);
87        inputs.write_into(target);
88        serial_num.write_into(target);
89    }
90}
91
92impl Deserializable for NoteRecipient {
93    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
94        let script = NoteScript::read_from(source)?;
95        let inputs = NoteInputs::read_from(source)?;
96        let serial_num = Word::read_from(source)?;
97
98        Ok(Self::new(serial_num, script, inputs))
99    }
100}