Skip to main content

miden_protocol/batch/
batch_id.rs

1use alloc::string::String;
2use alloc::vec::Vec;
3
4use miden_protocol_macros::WordWrapper;
5
6use crate::account::AccountId;
7use crate::transaction::{ProvenTransaction, TransactionId};
8use crate::utils::serde::{
9    ByteReader,
10    ByteWriter,
11    Deserializable,
12    DeserializationError,
13    Serializable,
14};
15use crate::{Felt, Hasher, Word, ZERO};
16
17// BATCH ID
18// ================================================================================================
19
20/// Uniquely identifies a batch of transactions, i.e. both
21/// [`ProposedBatch`](crate::batch::ProposedBatch) and [`ProvenBatch`](crate::batch::ProvenBatch).
22///
23/// This is a sequential hash of the tuple `(TRANSACTION_ID || [account_id_prefix,
24/// account_id_suffix, 0, 0])` of all transactions and the accounts their executed against in the
25/// batch.
26#[derive(Debug, Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Hash, WordWrapper)]
27pub struct BatchId(Word);
28
29impl BatchId {
30    /// Calculates a batch ID from the given set of transactions.
31    pub fn from_transactions<'tx, T>(txs: T) -> Self
32    where
33        T: Iterator<Item = &'tx ProvenTransaction>,
34    {
35        Self::from_ids(txs.map(|tx| (tx.id(), tx.account_id())))
36    }
37
38    /// Calculates a batch ID from the given transaction ID and account ID tuple.
39    pub fn from_ids(iter: impl IntoIterator<Item = (TransactionId, AccountId)>) -> Self {
40        let mut elements: Vec<Felt> = Vec::new();
41        for (tx_id, account_id) in iter {
42            elements.extend_from_slice(tx_id.as_elements());
43            let [account_id_prefix, account_id_suffix] = <[Felt; 2]>::from(account_id);
44            elements.extend_from_slice(&[account_id_prefix, account_id_suffix, ZERO, ZERO]);
45        }
46
47        Self(Hasher::hash_elements(&elements))
48    }
49}
50
51impl core::fmt::Display for BatchId {
52    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
53        write!(f, "{}", self.to_hex())
54    }
55}
56
57// SERIALIZATION
58// ================================================================================================
59
60impl Serializable for BatchId {
61    fn write_into<W: ByteWriter>(&self, target: &mut W) {
62        self.0.write_into(target);
63    }
64}
65
66impl Deserializable for BatchId {
67    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
68        Ok(Self(Word::read_from(source)?))
69    }
70}