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}