1//! Contains [`IncomingTx`] and [`IncomingTxBuilder`]
2use crate::{State, TxState};
34/// An incoming transaction that has gone through the preprocessing stage.
5pub struct IncomingTx<Tx, TxId, PeerId> {
6/// The transaction.
7pub(crate) tx: Tx,
8/// The transaction ID.
9pub(crate) tx_id: TxId,
10/// The routing state of the transaction.
11pub(crate) routing_state: TxState<PeerId>,
12}
1314/// An [`IncomingTx`] builder.
15///
16/// The const generics here are used to restrict what methods can be called.
17///
18/// - `RS`: routing state; a `bool` for if the routing state is set
19/// - `DBS`: database state; a `bool` for if the state in the DB is set
20pub struct IncomingTxBuilder<const RS: bool, const DBS: bool, Tx, TxId, PeerId> {
21/// The transaction.
22tx: Tx,
23/// The transaction ID.
24tx_id: TxId,
25/// The routing state of the transaction.
26routing_state: Option<TxState<PeerId>>,
27/// The state of this transaction in the DB.
28state_in_db: Option<State>,
29}
3031impl<Tx, TxId, PeerId> IncomingTxBuilder<false, false, Tx, TxId, PeerId> {
32/// Creates a new [`IncomingTxBuilder`].
33pub const fn new(tx: Tx, tx_id: TxId) -> Self {
34Self {
35 tx,
36 tx_id,
37 routing_state: None,
38 state_in_db: None,
39 }
40 }
41}
4243impl<const DBS: bool, Tx, TxId, PeerId> IncomingTxBuilder<false, DBS, Tx, TxId, PeerId> {
44/// Adds the routing state to the builder.
45 ///
46 /// The routing state is the origin of this transaction from our perspective.
47pub fn with_routing_state(
48self,
49 state: TxState<PeerId>,
50 ) -> IncomingTxBuilder<true, DBS, Tx, TxId, PeerId> {
51 IncomingTxBuilder {
52 tx: self.tx,
53 tx_id: self.tx_id,
54 routing_state: Some(state),
55 state_in_db: self.state_in_db,
56 }
57 }
58}
5960impl<const RS: bool, Tx, TxId, PeerId> IncomingTxBuilder<RS, false, Tx, TxId, PeerId> {
61/// Adds the database state to the builder.
62 ///
63 /// If the transaction is not in the DB already then the state should be [`None`].
64pub fn with_state_in_db(
65self,
66 state: Option<State>,
67 ) -> IncomingTxBuilder<RS, true, Tx, TxId, PeerId> {
68 IncomingTxBuilder {
69 tx: self.tx,
70 tx_id: self.tx_id,
71 routing_state: self.routing_state,
72 state_in_db: state,
73 }
74 }
75}
7677impl<Tx, TxId, PeerId> IncomingTxBuilder<true, true, Tx, TxId, PeerId> {
78/// Builds the [`IncomingTx`].
79 ///
80 /// If this returns [`None`] then the transaction does not need to be given to the dandelion pool
81 /// manager.
82pub fn build(self) -> Option<IncomingTx<Tx, TxId, PeerId>> {
83let routing_state = self.routing_state.unwrap();
8485if self.state_in_db == Some(State::Fluff) {
86return None;
87 }
8889Some(IncomingTx {
90 tx: self.tx,
91 tx_id: self.tx_id,
92 routing_state,
93 })
94 }
95}
9697#[cfg(test)]
98mod tests {
99use super::*;
100101#[test]
102fn test_builder() {
103 IncomingTxBuilder::new(1, 2)
104 .with_routing_state(TxState::Stem { from: 3 })
105 .with_state_in_db(None)
106 .build();
107108 IncomingTxBuilder::new(1, 2)
109 .with_state_in_db(None)
110 .with_routing_state(TxState::Stem { from: 3 })
111 .build();
112 }
113}