miden_objects/block/
proven_block.rs

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