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