miden_client/transaction/
store_update.rs1use alloc::vec::Vec;
2
3use miden_protocol::block::BlockNumber;
4use miden_protocol::note::{NoteDetails, NoteTag};
5use miden_protocol::transaction::ExecutedTransaction;
6use miden_tx::utils::serde::{
7 ByteReader,
8 ByteWriter,
9 Deserializable,
10 DeserializationError,
11 Serializable,
12};
13
14use crate::note::NoteUpdateTracker;
15use crate::sync::NoteTagRecord;
16
17#[derive(Debug, Clone, PartialEq)]
23pub struct TransactionStoreUpdate {
24 executed_transaction: ExecutedTransaction,
26 submission_height: BlockNumber,
28 future_notes: Vec<(NoteDetails, NoteTag)>,
30 note_updates: NoteUpdateTracker,
32 new_tags: Vec<NoteTagRecord>,
34}
35
36impl TransactionStoreUpdate {
37 pub fn new(
48 executed_transaction: ExecutedTransaction,
49 submission_height: BlockNumber,
50 note_updates: NoteUpdateTracker,
51 future_notes: Vec<(NoteDetails, NoteTag)>,
52 new_tags: Vec<NoteTagRecord>,
53 ) -> Self {
54 Self {
55 executed_transaction,
56 submission_height,
57 future_notes,
58 note_updates,
59 new_tags,
60 }
61 }
62 pub fn executed_transaction(&self) -> &ExecutedTransaction {
64 &self.executed_transaction
65 }
66
67 pub fn submission_height(&self) -> BlockNumber {
69 self.submission_height
70 }
71
72 pub fn future_notes(&self) -> &[(NoteDetails, NoteTag)] {
74 &self.future_notes
75 }
76
77 pub fn note_updates(&self) -> &NoteUpdateTracker {
79 &self.note_updates
80 }
81
82 pub fn new_tags(&self) -> &[NoteTagRecord] {
84 &self.new_tags
85 }
86}
87
88impl Serializable for TransactionStoreUpdate {
89 fn write_into<W: ByteWriter>(&self, target: &mut W) {
90 self.executed_transaction.write_into(target);
91 self.submission_height.write_into(target);
92 self.future_notes.write_into(target);
93 self.note_updates.write_into(target);
94 self.new_tags.write_into(target);
95 }
96}
97
98impl Deserializable for TransactionStoreUpdate {
99 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
100 let executed_transaction = ExecutedTransaction::read_from(source)?;
101 let submission_height = BlockNumber::read_from(source)?;
102 let future_notes = Vec::<(NoteDetails, NoteTag)>::read_from(source)?;
103 let note_updates = NoteUpdateTracker::read_from(source)?;
104 let new_tags = Vec::<NoteTagRecord>::read_from(source)?;
105
106 Ok(Self {
107 executed_transaction,
108 submission_height,
109 future_notes,
110 note_updates,
111 new_tags,
112 })
113 }
114}
115
116#[cfg(test)]
120mod tests {
121 use alloc::boxed::Box;
122
123 use miden_protocol::asset::{Asset, FungibleAsset};
124 use miden_protocol::note::NoteType;
125 use miden_protocol::testing::account_id::{
126 ACCOUNT_ID_PRIVATE_FUNGIBLE_FAUCET,
127 ACCOUNT_ID_SENDER,
128 };
129 use miden_testing::{MockChainBuilder, TxContextInput};
130
131 use super::*;
132 use crate::note::NoteUpdateTracker;
133 use crate::store::InputNoteRecord;
134 use crate::sync::NoteTagRecord;
135
136 #[tokio::test]
137 async fn transaction_store_update_serialization_roundtrip() {
138 let sender_id = ACCOUNT_ID_SENDER.try_into().unwrap();
141 let faucet_id = ACCOUNT_ID_PRIVATE_FUNGIBLE_FAUCET.try_into().unwrap();
142 let asset = Asset::Fungible(FungibleAsset::new(faucet_id, 100u64).unwrap());
143
144 let mut builder = MockChainBuilder::new();
145 let account = builder.add_existing_mock_account(miden_testing::Auth::IncrNonce).unwrap();
146 let note = builder
147 .add_p2id_note(sender_id, account.id(), &[asset], NoteType::Public)
148 .unwrap();
149 let mut chain = builder.build().unwrap();
150 chain.prove_next_block().unwrap();
151
152 let executed_tx = Box::pin(
153 chain
154 .build_tx_context(
155 TxContextInput::Account(account.clone()),
156 &[],
157 core::slice::from_ref(¬e),
158 )
159 .unwrap()
160 .build()
161 .unwrap()
162 .execute(),
163 )
164 .await
165 .unwrap();
166
167 let input_note = InputNoteRecord::from(note.clone());
170 let note_updates = NoteUpdateTracker::for_transaction_updates([input_note], [], []);
171
172 let tag = NoteTag::with_account_target(account.id());
173 let new_tags = vec![NoteTagRecord::with_account_source(tag, account.id())];
174
175 let future_notes = vec![(Into::<NoteDetails>::into(note.clone()), tag)];
176
177 let update = TransactionStoreUpdate::new(
178 executed_tx,
179 BlockNumber::from(42u32),
180 note_updates,
181 future_notes,
182 new_tags,
183 );
184
185 let bytes = update.to_bytes();
186 let deserialized = TransactionStoreUpdate::read_from_bytes(&bytes).unwrap();
187
188 assert_eq!(update, deserialized);
189 }
190}