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}