cuprated/rpc/service/
tx_handler.rs

1use anyhow::{anyhow, Error};
2use cuprate_consensus::ExtendedConsensusError;
3use cuprate_consensus_rules::{transactions::TransactionError, ConsensusError};
4use tower::{Service, ServiceExt};
5
6use cuprate_types::TxRelayChecks;
7
8use crate::txpool::{IncomingTxError, IncomingTxHandler, IncomingTxs, RelayRuleError};
9
10pub async fn handle_incoming_txs(
11    tx_handler: &mut IncomingTxHandler,
12    incoming_txs: IncomingTxs,
13) -> Result<TxRelayChecks, Error> {
14    let resp = tx_handler
15        .ready()
16        .await
17        .map_err(|e| anyhow!(e))?
18        .call(incoming_txs)
19        .await;
20
21    Ok(match resp {
22        Ok(()) => TxRelayChecks::empty(),
23        Err(e) => match e {
24            IncomingTxError::Consensus(ExtendedConsensusError::ConErr(
25                ConsensusError::Transaction(e),
26            )) => match e {
27                TransactionError::TooBig => TxRelayChecks::TOO_BIG,
28                TransactionError::KeyImageSpent => TxRelayChecks::DOUBLE_SPEND,
29
30                TransactionError::OutputNotValidPoint
31                | TransactionError::OutputTypeInvalid
32                | TransactionError::ZeroOutputForV1
33                | TransactionError::NonZeroOutputForV2
34                | TransactionError::OutputsOverflow
35                | TransactionError::OutputsTooHigh => TxRelayChecks::INVALID_OUTPUT,
36
37                TransactionError::MoreThanOneMixableInputWithUnmixable
38                | TransactionError::InvalidNumberOfOutputs
39                | TransactionError::InputDoesNotHaveExpectedNumbDecoys
40                | TransactionError::IncorrectInputType
41                | TransactionError::InputsAreNotOrdered
42                | TransactionError::InputsOverflow
43                | TransactionError::NoInputs => TxRelayChecks::INVALID_INPUT,
44
45                TransactionError::KeyImageIsNotInPrimeSubGroup
46                | TransactionError::AmountNotDecomposed
47                | TransactionError::DuplicateRingMember
48                | TransactionError::OneOrMoreRingMembersLocked
49                | TransactionError::RingMemberNotFoundOrInvalid
50                | TransactionError::RingSignatureIncorrect
51                | TransactionError::TransactionVersionInvalid
52                | TransactionError::RingCTError(_) => return Err(anyhow!("unreachable")),
53            },
54            IncomingTxError::Parse(_) | IncomingTxError::Consensus(_) => {
55                return Err(anyhow!("unreachable"))
56            }
57            IncomingTxError::RelayRule(RelayRuleError::NonZeroTimelock) => {
58                TxRelayChecks::NONZERO_UNLOCK_TIME
59            }
60            IncomingTxError::RelayRule(RelayRuleError::ExtraFieldTooLarge) => {
61                TxRelayChecks::TX_EXTRA_TOO_BIG
62            }
63            IncomingTxError::RelayRule(RelayRuleError::FeeBelowMinimum) => {
64                TxRelayChecks::FEE_TOO_LOW
65            }
66            IncomingTxError::DuplicateTransaction => TxRelayChecks::DOUBLE_SPEND,
67        },
68    })
69}