miden_objects/transaction/ordered_transactions.rs
1use alloc::vec::Vec;
2
3use crate::{
4 Digest, Felt, Hasher, ZERO,
5 account::AccountId,
6 transaction::{TransactionHeader, TransactionId},
7 utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
8};
9
10// ORDERED TRANSACTION HEADERS
11// ================================================================================================
12
13/// The ordered set of transaction headers in a [`ProvenBatch`](crate::batch::ProvenBatch) or
14/// [`ProvenBlock`](crate::block::ProvenBlock).
15///
16/// This is a newtype wrapper representing either:
17/// - the set of transactions in a **batch**,
18/// - or the flattened sets of transactions of each proven batch in a **block**.
19///
20/// This type cannot be constructed directly, but can be retrieved through:
21/// - [`ProposedBatch::transaction_headers`](crate::batch::ProposedBatch::transaction_headers),
22/// - [`OrderedBatches::into_transactions`](crate::batch::OrderedBatches::into_transactions).
23///
24/// The rationale for this requirement is that it allows a client to cheaply validate the
25/// correctness of the transactions in a proven block returned by a remote prover.
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct OrderedTransactionHeaders(Vec<TransactionHeader>);
28
29impl OrderedTransactionHeaders {
30 /// Creates a new set of ordered transaction headers from the provided vector.
31 ///
32 /// # Warning
33 ///
34 /// See the type-level documentation for the requirements of the passed transactions.
35 pub fn new_unchecked(transactions: Vec<TransactionHeader>) -> Self {
36 Self(transactions)
37 }
38
39 /// Computes a commitment to the list of transactions.
40 ///
41 /// This is a sequential hash over each transaction's ID and its account ID.
42 pub fn commitment(&self) -> Digest {
43 Self::compute_commitment(self.0.as_slice().iter().map(|tx| (tx.id(), tx.account_id())))
44 }
45
46 /// Returns a reference to the underlying transaction headers.
47 pub fn as_slice(&self) -> &[TransactionHeader] {
48 &self.0
49 }
50
51 /// Consumes self and returns the underlying vector of transaction headers.
52 pub fn into_vec(self) -> Vec<TransactionHeader> {
53 self.0
54 }
55
56 // PUBLIC HELPERS
57 // --------------------------------------------------------------------------------------------
58
59 /// Computes a commitment to the provided list of transactions.
60 ///
61 /// Each transaction is represented by a transaction ID and an account ID which it was executed
62 /// against. The commitment is a sequential hash over (transaction_id, account_id) tuples.
63 pub fn compute_commitment(
64 transactions: impl Iterator<Item = (TransactionId, AccountId)>,
65 ) -> Digest {
66 let mut elements = vec![];
67 for (transaction_id, account_id) in transactions {
68 let [account_id_prefix, account_id_suffix] = <[Felt; 2]>::from(account_id);
69 elements.extend_from_slice(transaction_id.as_elements());
70 elements.extend_from_slice(&[account_id_prefix, account_id_suffix, ZERO, ZERO]);
71 }
72
73 Hasher::hash_elements(&elements)
74 }
75}
76
77// SERIALIZATION
78// ================================================================================================
79
80impl Serializable for OrderedTransactionHeaders {
81 fn write_into<W: ByteWriter>(&self, target: &mut W) {
82 self.0.write_into(target)
83 }
84}
85
86impl Deserializable for OrderedTransactionHeaders {
87 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
88 source.read().map(OrderedTransactionHeaders::new_unchecked)
89 }
90}