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}