miden_objects/block/
proven_block.rs

1use alloc::vec::Vec;
2
3use crate::{
4    Digest,
5    account::AccountId,
6    block::{BlockAccountUpdate, BlockHeader, BlockNoteIndex, BlockNoteTree, OutputNoteBatch},
7    note::Nullifier,
8    transaction::{OutputNote, TransactionId},
9    utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
10};
11
12// PROVEN BLOCK
13// ================================================================================================
14
15/// A block in the Miden chain.
16///
17/// A block is built from batches of transactions, i.e. multiple
18/// [`ProvenBatch`](crate::batch::ProvenBatch)es, and each batch contains multiple
19/// [`ProvenTransaction`](crate::transaction::ProvenTransaction)s.
20///
21/// It consists of the following components:
22/// - A [`BlockHeader`] committing to the current state of the chain and against which account, note
23///   or nullifier inclusion or absence can be proven. See its documentation for details on what it
24///   commits to. Eventually, it will also contain a ZK proof of the validity of the block.
25/// - A list of account updates for all accounts updated in this block. For private accounts, the
26///   update contains only the new account state commitments while for public accounts, the update
27///   also includes the delta which can be applied to the previous account state to get the new
28///   account state.
29/// - A list of new notes created in this block. For private notes, the block contains only note IDs
30///   and note metadata while for public notes the full note details are included.
31/// - A list of new nullifiers created for all notes that were consumed 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
47impl ProvenBlock {
48    /// Returns a new [`ProvenBlock`] instantiated from the provided components.
49    ///
50    /// # Warning
51    ///
52    /// This constructor does not do any validation, so passing incorrect values may lead to later
53    /// panics.
54    pub fn new_unchecked(
55        header: BlockHeader,
56        updated_accounts: Vec<BlockAccountUpdate>,
57        output_note_batches: Vec<OutputNoteBatch>,
58        created_nullifiers: Vec<Nullifier>,
59    ) -> Self {
60        Self {
61            header,
62            updated_accounts,
63            output_note_batches,
64            created_nullifiers,
65        }
66    }
67
68    /// Returns the commitment to this block.
69    pub fn commitment(&self) -> Digest {
70        self.header.commitment()
71    }
72
73    /// Returns the header of this block.
74    pub fn header(&self) -> &BlockHeader {
75        &self.header
76    }
77
78    /// Returns the slice of [`BlockAccountUpdate`]s for all accounts updated in this block.
79    pub fn updated_accounts(&self) -> &[BlockAccountUpdate] {
80        &self.updated_accounts
81    }
82
83    /// Returns the slice of [`OutputNoteBatch`]es for all output notes created in this block.
84    pub fn output_note_batches(&self) -> &[OutputNoteBatch] {
85        &self.output_note_batches
86    }
87
88    /// Returns an iterator over all [`OutputNote`]s created in this block.
89    ///
90    /// Each note is accompanied by a corresponding index specifying where the note is located
91    /// in the block's [`BlockNoteTree`].
92    pub fn output_notes(&self) -> impl Iterator<Item = (BlockNoteIndex, &OutputNote)> {
93        self.output_note_batches.iter().enumerate().flat_map(|(batch_idx, notes)| {
94            notes.iter().map(move |(note_idx_in_batch, note)| {
95                (
96                    // SAFETY: The proven block contains at most the max allowed number of batches
97                    // and each batch is guaranteed to contain at most the
98                    // max allowed number of output notes.
99                    BlockNoteIndex::new(batch_idx, *note_idx_in_batch)
100                        .expect("max batches in block and max notes in batches should be enforced"),
101                    note,
102                )
103            })
104        })
105    }
106
107    /// Returns the [`BlockNoteTree`] containing all [`OutputNote`]s created in this block.
108    pub fn build_output_note_tree(&self) -> BlockNoteTree {
109        let entries = self
110            .output_notes()
111            .map(|(note_index, note)| (note_index, note.id(), *note.metadata()));
112
113        // SAFETY: We only construct proven blocks that:
114        // - do not contain duplicates
115        // - contain at most the max allowed number of batches and each batch is guaranteed to
116        //   contain at most the max allowed number of output notes.
117        BlockNoteTree::with_entries(entries)
118            .expect("the output notes of the block should not contain duplicates and contain at most the allowed maximum")
119    }
120
121    /// Returns a reference to the slice of nullifiers for all notes consumed in the block.
122    pub fn created_nullifiers(&self) -> &[Nullifier] {
123        &self.created_nullifiers
124    }
125
126    /// Returns an iterator over all transactions which affected accounts in the block with
127    /// their corresponding account IDs.
128    pub fn transactions(&self) -> impl Iterator<Item = (TransactionId, AccountId)> + '_ {
129        self.updated_accounts.iter().flat_map(|update| {
130            update
131                .transactions()
132                .iter()
133                .map(|transaction_id| (*transaction_id, update.account_id()))
134        })
135    }
136}
137
138impl Serializable for ProvenBlock {
139    fn write_into<W: ByteWriter>(&self, target: &mut W) {
140        self.header.write_into(target);
141        self.updated_accounts.write_into(target);
142        self.output_note_batches.write_into(target);
143        self.created_nullifiers.write_into(target);
144    }
145}
146
147impl Deserializable for ProvenBlock {
148    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
149        let block = Self {
150            header: BlockHeader::read_from(source)?,
151            updated_accounts: <Vec<BlockAccountUpdate>>::read_from(source)?,
152            output_note_batches: <Vec<OutputNoteBatch>>::read_from(source)?,
153            created_nullifiers: <Vec<Nullifier>>::read_from(source)?,
154        };
155
156        Ok(block)
157    }
158}