miden_protocol/block/
block_body.rs1use alloc::vec::Vec;
2
3use miden_core::Word;
4use miden_core::utils::{
5 ByteReader,
6 ByteWriter,
7 Deserializable,
8 DeserializationError,
9 Serializable,
10};
11
12use crate::block::{
13 BlockAccountUpdate,
14 BlockNoteIndex,
15 BlockNoteTree,
16 OutputNoteBatch,
17 ProposedBlock,
18};
19use crate::note::Nullifier;
20use crate::transaction::{OrderedTransactionHeaders, OutputNote};
21
22#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct BlockBody {
28 updated_accounts: Vec<BlockAccountUpdate>,
30
31 output_note_batches: Vec<OutputNoteBatch>,
33
34 created_nullifiers: Vec<Nullifier>,
36
37 transactions: OrderedTransactionHeaders,
40}
41
42impl BlockBody {
43 pub fn new_unchecked(
53 updated_accounts: Vec<BlockAccountUpdate>,
54 output_note_batches: Vec<OutputNoteBatch>,
55 created_nullifiers: Vec<Nullifier>,
56 transactions: OrderedTransactionHeaders,
57 ) -> Self {
58 Self {
59 updated_accounts,
60 output_note_batches,
61 created_nullifiers,
62 transactions,
63 }
64 }
65
66 pub fn updated_accounts(&self) -> &[BlockAccountUpdate] {
71 &self.updated_accounts
72 }
73
74 pub fn output_note_batches(&self) -> &[OutputNoteBatch] {
76 &self.output_note_batches
77 }
78
79 pub fn created_nullifiers(&self) -> &[Nullifier] {
81 &self.created_nullifiers
82 }
83
84 pub fn transactions(&self) -> &OrderedTransactionHeaders {
86 &self.transactions
87 }
88
89 pub fn transaction_commitment(&self) -> Word {
91 self.transactions.commitment()
92 }
93
94 pub fn output_notes(&self) -> impl Iterator<Item = (BlockNoteIndex, &OutputNote)> {
99 self.output_note_batches.iter().enumerate().flat_map(|(batch_idx, notes)| {
100 notes.iter().map(move |(note_idx_in_batch, note)| {
101 (
102 BlockNoteIndex::new(batch_idx, *note_idx_in_batch)
106 .expect("max batches in block and max notes in batches should be enforced"),
107 note,
108 )
109 })
110 })
111 }
112
113 pub fn compute_block_note_tree(&self) -> BlockNoteTree {
115 let entries = self
116 .output_notes()
117 .map(|(note_index, note)| (note_index, note.id(), note.metadata()));
118
119 BlockNoteTree::with_entries(entries)
124 .expect("the output notes of the block should not contain duplicates and contain at most the allowed maximum")
125 }
126
127 pub fn into_parts(
132 self,
133 ) -> (
134 Vec<BlockAccountUpdate>,
135 Vec<OutputNoteBatch>,
136 Vec<Nullifier>,
137 OrderedTransactionHeaders,
138 ) {
139 (
140 self.updated_accounts,
141 self.output_note_batches,
142 self.created_nullifiers,
143 self.transactions,
144 )
145 }
146}
147
148impl From<ProposedBlock> for BlockBody {
149 fn from(block: ProposedBlock) -> Self {
150 let (batches, account_updated_witnesses, output_note_batches, created_nullifiers, ..) =
152 block.into_parts();
153
154 let updated_accounts = account_updated_witnesses
156 .into_iter()
157 .map(|(account_id, update_witness)| {
158 let (
159 _initial_state_commitment,
160 final_state_commitment,
161 _initial_state_proof,
163 details,
164 ) = update_witness.into_parts();
165 BlockAccountUpdate::new(account_id, final_state_commitment, details)
166 })
167 .collect();
168 let created_nullifiers = created_nullifiers.keys().copied().collect::<Vec<_>>();
169 let transactions = batches.into_transactions();
171 Self {
172 updated_accounts,
173 output_note_batches,
174 created_nullifiers,
175 transactions,
176 }
177 }
178}
179
180impl Serializable for BlockBody {
184 fn write_into<W: ByteWriter>(&self, target: &mut W) {
185 self.updated_accounts.write_into(target);
186 self.output_note_batches.write_into(target);
187 self.created_nullifiers.write_into(target);
188 self.transactions.write_into(target);
189 }
190}
191
192impl Deserializable for BlockBody {
193 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
194 let block = Self {
195 updated_accounts: Vec::read_from(source)?,
196 output_note_batches: Vec::read_from(source)?,
197 created_nullifiers: Vec::read_from(source)?,
198 transactions: OrderedTransactionHeaders::read_from(source)?,
199 };
200 Ok(block)
201 }
202}