Skip to main content

miden_node_proto/domain/
mempool.rs

1use std::collections::HashSet;
2
3use miden_protocol::account::delta::AccountUpdateDetails;
4use miden_protocol::block::BlockHeader;
5use miden_protocol::note::Nullifier;
6use miden_protocol::transaction::TransactionId;
7use miden_protocol::utils::{Deserializable, Serializable};
8
9use super::note::NetworkNote;
10use crate::errors::{ConversionError, MissingFieldHelper};
11use crate::generated as proto;
12
13#[derive(Debug, Clone)]
14pub enum MempoolEvent {
15    TransactionAdded {
16        id: TransactionId,
17        nullifiers: Vec<Nullifier>,
18        network_notes: Vec<NetworkNote>,
19        account_delta: Option<AccountUpdateDetails>,
20    },
21    BlockCommitted {
22        // Box'd as this struct is quite large and triggers clippy.
23        header: Box<BlockHeader>,
24        txs: Vec<TransactionId>,
25    },
26    TransactionsReverted(HashSet<TransactionId>),
27}
28
29impl MempoolEvent {
30    pub fn kind(&self) -> &'static str {
31        match self {
32            MempoolEvent::TransactionAdded { .. } => "TransactionAdded",
33            MempoolEvent::BlockCommitted { .. } => "BlockCommitted",
34            MempoolEvent::TransactionsReverted(_) => "TransactionsReverted",
35        }
36    }
37}
38
39impl From<MempoolEvent> for proto::block_producer::MempoolEvent {
40    fn from(event: MempoolEvent) -> Self {
41        let event = match event {
42            MempoolEvent::TransactionAdded {
43                id,
44                nullifiers,
45                network_notes,
46                account_delta,
47            } => {
48                let event = proto::block_producer::mempool_event::TransactionAdded {
49                    id: Some(id.into()),
50                    nullifiers: nullifiers.into_iter().map(Into::into).collect(),
51                    network_notes: network_notes.into_iter().map(Into::into).collect(),
52                    network_account_delta: account_delta
53                        .as_ref()
54                        .map(AccountUpdateDetails::to_bytes),
55                };
56
57                proto::block_producer::mempool_event::Event::TransactionAdded(event)
58            },
59            MempoolEvent::BlockCommitted { header, txs } => {
60                proto::block_producer::mempool_event::Event::BlockCommitted(
61                    proto::block_producer::mempool_event::BlockCommitted {
62                        block_header: Some(header.as_ref().into()),
63                        transactions: txs.into_iter().map(Into::into).collect(),
64                    },
65                )
66            },
67            MempoolEvent::TransactionsReverted(txs) => {
68                proto::block_producer::mempool_event::Event::TransactionsReverted(
69                    proto::block_producer::mempool_event::TransactionsReverted {
70                        reverted: txs.into_iter().map(Into::into).collect(),
71                    },
72                )
73            },
74        }
75        .into();
76
77        Self { event }
78    }
79}
80
81impl TryFrom<proto::block_producer::MempoolEvent> for MempoolEvent {
82    type Error = ConversionError;
83
84    fn try_from(event: proto::block_producer::MempoolEvent) -> Result<Self, Self::Error> {
85        let event =
86            event.event.ok_or(proto::block_producer::MempoolEvent::missing_field("event"))?;
87
88        match event {
89            proto::block_producer::mempool_event::Event::TransactionAdded(tx) => {
90                let id = tx
91                    .id
92                    .ok_or(proto::block_producer::mempool_event::TransactionAdded::missing_field(
93                        "id",
94                    ))?
95                    .try_into()?;
96                let nullifiers =
97                    tx.nullifiers.into_iter().map(TryInto::try_into).collect::<Result<_, _>>()?;
98                let network_notes = tx
99                    .network_notes
100                    .into_iter()
101                    .map(TryInto::try_into)
102                    .collect::<Result<_, _>>()?;
103                let account_delta = tx
104                    .network_account_delta
105                    .as_deref()
106                    .map(AccountUpdateDetails::read_from_bytes)
107                    .transpose()
108                    .map_err(|err| ConversionError::deserialization_error("account_delta", err))?;
109
110                Ok(Self::TransactionAdded {
111                    id,
112                    nullifiers,
113                    network_notes,
114                    account_delta,
115                })
116            },
117            proto::block_producer::mempool_event::Event::BlockCommitted(block_committed) => {
118                let header = block_committed
119                    .block_header
120                    .ok_or(proto::block_producer::mempool_event::BlockCommitted::missing_field(
121                        "block_header",
122                    ))?
123                    .try_into()?;
124                let header = Box::new(header);
125                let txs = block_committed
126                    .transactions
127                    .into_iter()
128                    .map(TransactionId::try_from)
129                    .collect::<Result<_, _>>()?;
130
131                Ok(Self::BlockCommitted { header, txs })
132            },
133            proto::block_producer::mempool_event::Event::TransactionsReverted(txs) => {
134                let txs = txs
135                    .reverted
136                    .into_iter()
137                    .map(TransactionId::try_from)
138                    .collect::<Result<_, _>>()?;
139
140                Ok(Self::TransactionsReverted(txs))
141            },
142        }
143    }
144}