miden_protocol/block/
block_body.rs1use alloc::vec::Vec;
2
3use miden_core::Word;
4
5use crate::block::{
6 BlockAccountUpdate,
7 BlockNoteIndex,
8 BlockNoteTree,
9 OutputNoteBatch,
10 ProposedBlock,
11};
12use crate::note::Nullifier;
13use crate::transaction::{OrderedTransactionHeaders, OutputNote};
14use crate::utils::serde::{
15 ByteReader,
16 ByteWriter,
17 Deserializable,
18 DeserializationError,
19 Serializable,
20};
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.output_notes().map(|(note_index, note)| (note_index, note.into()));
116
117 BlockNoteTree::with_entries(entries)
122 .expect("the output notes of the block should not contain duplicates and contain at most the allowed maximum")
123 }
124
125 pub fn into_parts(
130 self,
131 ) -> (
132 Vec<BlockAccountUpdate>,
133 Vec<OutputNoteBatch>,
134 Vec<Nullifier>,
135 OrderedTransactionHeaders,
136 ) {
137 (
138 self.updated_accounts,
139 self.output_note_batches,
140 self.created_nullifiers,
141 self.transactions,
142 )
143 }
144}
145
146impl From<ProposedBlock> for BlockBody {
147 fn from(block: ProposedBlock) -> Self {
148 let (batches, account_updated_witnesses, output_note_batches, created_nullifiers, ..) =
150 block.into_parts();
151
152 let updated_accounts = account_updated_witnesses
154 .into_iter()
155 .map(|(account_id, update_witness)| {
156 let (
157 _initial_state_commitment,
158 final_state_commitment,
159 _initial_state_proof,
161 details,
162 ) = update_witness.into_parts();
163 BlockAccountUpdate::new(account_id, final_state_commitment, details)
164 })
165 .collect();
166 let created_nullifiers = created_nullifiers.keys().copied().collect::<Vec<_>>();
167 let transactions = batches.into_transactions();
169 Self {
170 updated_accounts,
171 output_note_batches,
172 created_nullifiers,
173 transactions,
174 }
175 }
176}
177
178impl Serializable for BlockBody {
182 fn write_into<W: ByteWriter>(&self, target: &mut W) {
183 self.updated_accounts.write_into(target);
184 self.output_note_batches.write_into(target);
185 self.created_nullifiers.write_into(target);
186 self.transactions.write_into(target);
187 }
188}
189
190impl Deserializable for BlockBody {
191 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
192 let block = Self {
193 updated_accounts: Vec::read_from(source)?,
194 output_note_batches: Vec::read_from(source)?,
195 created_nullifiers: Vec::read_from(source)?,
196 transactions: OrderedTransactionHeaders::read_from(source)?,
197 };
198 Ok(block)
199 }
200}