miden_objects/block/
proven_block.rs

1use alloc::vec::Vec;
2
3use crate::{
4    Digest, MIN_PROOF_SECURITY_LEVEL,
5    block::{BlockAccountUpdate, BlockHeader, BlockNoteIndex, BlockNoteTree, OutputNoteBatch},
6    note::Nullifier,
7    transaction::{OrderedTransactionHeaders, OutputNote},
8    utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
9};
10
11// PROVEN BLOCK
12// ================================================================================================
13
14/// A block in the Miden chain.
15///
16/// A block is built from batches of transactions, i.e. multiple
17/// [`ProvenBatch`](crate::batch::ProvenBatch)es, and each batch contains multiple
18/// [`ProvenTransaction`](crate::transaction::ProvenTransaction)s.
19///
20/// It consists of the following components:
21/// - A [`BlockHeader`] committing to the current state of the chain and against which account, note
22///   or nullifier inclusion or absence can be proven. See its documentation for details on what it
23///   commits to. Eventually, it will also contain a ZK proof of the validity of the block.
24/// - A list of account updates for all accounts updated in this block. For private accounts, the
25///   update contains only the new account state commitments while for public accounts, the update
26///   also includes the delta which can be applied to the previous account state to get the new
27///   account state.
28/// - A list of new notes created in this block. For private notes, the block contains only note IDs
29///   and note metadata while for public notes the full note details are included.
30/// - A list of new nullifiers created for all notes that were consumed in the block.
31/// - A list of transaction headers that were included in the block.
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub struct ProvenBlock {
34    /// The header of the block, committing to the current state of the chain.
35    header: BlockHeader,
36
37    /// Account updates for the block.
38    updated_accounts: Vec<BlockAccountUpdate>,
39
40    /// Note batches created by the transactions in this block.
41    output_note_batches: Vec<OutputNoteBatch>,
42
43    /// Nullifiers created by the transactions in this block through the consumption of notes.
44    created_nullifiers: Vec<Nullifier>,
45
46    /// The aggregated and flattened transaction headers of all batches in the order in which they
47    /// appeared in the proposed block.
48    transactions: OrderedTransactionHeaders,
49}
50
51impl ProvenBlock {
52    /// Returns a new [`ProvenBlock`] instantiated from the provided components.
53    ///
54    /// # Warning
55    ///
56    /// This constructor does not do any validation, so passing incorrect values may lead to later
57    /// panics.
58    pub fn new_unchecked(
59        header: BlockHeader,
60        updated_accounts: Vec<BlockAccountUpdate>,
61        output_note_batches: Vec<OutputNoteBatch>,
62        created_nullifiers: Vec<Nullifier>,
63        transactions: OrderedTransactionHeaders,
64    ) -> Self {
65        Self {
66            header,
67            updated_accounts,
68            output_note_batches,
69            created_nullifiers,
70            transactions,
71        }
72    }
73
74    /// Returns the commitment to this block.
75    pub fn commitment(&self) -> Digest {
76        self.header.commitment()
77    }
78
79    /// Returns the header of this block.
80    pub fn header(&self) -> &BlockHeader {
81        &self.header
82    }
83
84    /// Returns the slice of [`BlockAccountUpdate`]s for all accounts updated in this block.
85    pub fn updated_accounts(&self) -> &[BlockAccountUpdate] {
86        &self.updated_accounts
87    }
88
89    /// Returns the slice of [`OutputNoteBatch`]es for all output notes created in this block.
90    pub fn output_note_batches(&self) -> &[OutputNoteBatch] {
91        &self.output_note_batches
92    }
93
94    /// Returns the proof security level of the block.
95    pub fn proof_security_level(&self) -> u32 {
96        MIN_PROOF_SECURITY_LEVEL
97    }
98
99    /// Returns an iterator over all [`OutputNote`]s created in this block.
100    ///
101    /// Each note is accompanied by a corresponding index specifying where the note is located
102    /// in the block's [`BlockNoteTree`].
103    pub fn output_notes(&self) -> impl Iterator<Item = (BlockNoteIndex, &OutputNote)> {
104        self.output_note_batches.iter().enumerate().flat_map(|(batch_idx, notes)| {
105            notes.iter().map(move |(note_idx_in_batch, note)| {
106                (
107                    // SAFETY: The proven block contains at most the max allowed number of batches
108                    // and each batch is guaranteed to contain at most the
109                    // max allowed number of output notes.
110                    BlockNoteIndex::new(batch_idx, *note_idx_in_batch)
111                        .expect("max batches in block and max notes in batches should be enforced"),
112                    note,
113                )
114            })
115        })
116    }
117
118    /// Returns the [`BlockNoteTree`] containing all [`OutputNote`]s created in this block.
119    pub fn build_output_note_tree(&self) -> BlockNoteTree {
120        let entries = self
121            .output_notes()
122            .map(|(note_index, note)| (note_index, note.id(), *note.metadata()));
123
124        // SAFETY: We only construct proven blocks that:
125        // - do not contain duplicates
126        // - contain at most the max allowed number of batches and each batch is guaranteed to
127        //   contain at most the max allowed number of output notes.
128        BlockNoteTree::with_entries(entries)
129            .expect("the output notes of the block should not contain duplicates and contain at most the allowed maximum")
130    }
131
132    /// Returns a reference to the slice of nullifiers for all notes consumed in the block.
133    pub fn created_nullifiers(&self) -> &[Nullifier] {
134        &self.created_nullifiers
135    }
136
137    /// Returns the [`OrderedTransactionHeaders`] of all transactions included in this block.
138    pub fn transactions(&self) -> &OrderedTransactionHeaders {
139        &self.transactions
140    }
141}
142
143// SERIALIZATION
144// ================================================================================================
145
146impl Serializable for ProvenBlock {
147    fn write_into<W: ByteWriter>(&self, target: &mut W) {
148        self.header.write_into(target);
149        self.updated_accounts.write_into(target);
150        self.output_note_batches.write_into(target);
151        self.created_nullifiers.write_into(target);
152        self.transactions.write_into(target);
153    }
154}
155
156impl Deserializable for ProvenBlock {
157    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
158        let block = Self {
159            header: BlockHeader::read_from(source)?,
160            updated_accounts: <Vec<BlockAccountUpdate>>::read_from(source)?,
161            output_note_batches: <Vec<OutputNoteBatch>>::read_from(source)?,
162            created_nullifiers: <Vec<Nullifier>>::read_from(source)?,
163            transactions: OrderedTransactionHeaders::read_from(source)?,
164        };
165
166        Ok(block)
167    }
168}
169
170// TESTING
171// ================================================================================================
172
173#[cfg(any(feature = "testing", test))]
174impl ProvenBlock {
175    /// Returns a mutable reference to the block's account updates for testing purposes.
176    pub fn updated_accounts_mut(&mut self) -> &mut Vec<BlockAccountUpdate> {
177        &mut self.updated_accounts
178    }
179
180    /// Returns a mutable reference to the block's nullifiers for testing purposes.
181    pub fn created_nullifiers_mut(&mut self) -> &mut Vec<Nullifier> {
182        &mut self.created_nullifiers
183    }
184
185    /// Returns a mutable reference to the block's output note batches for testing purposes.
186    pub fn output_note_batches_mut(&mut self) -> &mut Vec<OutputNoteBatch> {
187        &mut self.output_note_batches
188    }
189
190    /// Sets the block's header for testing purposes.
191    pub fn set_block_header(&mut self, header: BlockHeader) {
192        self.header = header;
193    }
194}