cfxcore/pos/mempool/shared_mempool/
transaction_validator.rs

1use diem_types::{
2    term_state::PosState,
3    transaction::{
4        authenticator::TransactionAuthenticator, SignedTransaction,
5        TransactionPayload,
6    },
7};
8use move_core_types::vm_status::DiscardedVMStatus;
9
10pub struct TransactionValidator {}
11
12impl TransactionValidator {
13    pub fn new() -> Self { Self {} }
14
15    /// Returns `None` if the transaction is accepted, or a
16    /// `DiscardedVMStatus` describing why it should be rejected.
17    pub fn validate_transaction(
18        &self, tx: &SignedTransaction, pos_state: &PosState,
19    ) -> Option<DiscardedVMStatus> {
20        let authenticator = tx.authenticator();
21        let auth_pk = match &authenticator {
22            TransactionAuthenticator::BLS { public_key, .. } => public_key,
23            _ => return Some(DiscardedVMStatus::INVALID_SIGNATURE),
24        };
25
26        let sender = tx.sender();
27        let result = match tx.payload() {
28            TransactionPayload::Election(election_payload) => pos_state
29                .validate_election_simple(&sender, auth_pk, election_payload),
30            TransactionPayload::PivotDecision(pivot_decision) => pos_state
31                .validate_pivot_decision_simple(
32                    &sender,
33                    auth_pk,
34                    pivot_decision,
35                ),
36            TransactionPayload::Dispute(_) => {
37                pos_state.validate_dispute_simple(&sender, auth_pk)
38            }
39            TransactionPayload::Register(_)
40            | TransactionPayload::Retire(_)
41            | TransactionPayload::UpdateVotingPower(_) => {
42                return Some(
43                    DiscardedVMStatus::PAYLOAD_NOT_ALLOWED_VIA_MEMPOOL,
44                );
45            }
46            _ => None,
47        };
48        if result.is_some() {
49            return result;
50        }
51
52        // PoS transactions never expire; `expiration_timestamp_secs` must be
53        // u64::MAX. Reject any other value before paying for signature
54        // verification.
55        if tx.expiration_timestamp_secs() != u64::MAX {
56            return Some(DiscardedVMStatus::INVALID_EXPIRATION_TIME);
57        }
58
59        if tx.verify_signature().is_err() {
60            return Some(DiscardedVMStatus::INVALID_SIGNATURE);
61        }
62
63        None
64    }
65}