1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

//! Transaction Pool

use ethereum_types::{U256, H256, Address};
use heapsize::HeapSizeOf;
use transaction;
use txpool;

mod listener;
mod queue;
mod ready;
mod scoring;

pub mod client;
pub mod local_transactions;
pub mod verifier;

#[cfg(test)]
mod tests;

pub use self::queue::{TransactionQueue, Status as QueueStatus};
pub use self::txpool::{VerifiedTransaction as PoolVerifiedTransaction, Options};

/// How to prioritize transactions in the pool
///
/// TODO [ToDr] Implement more strategies.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PrioritizationStrategy {
	/// Simple gas-price based prioritization.
	GasPriceOnly,
}

/// Transaction ordering when requesting pending set.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PendingOrdering {
	/// Get pending transactions ordered by their priority (potentially expensive)
	Priority,
	/// Get pending transactions without any care of particular ordering (cheaper).
	Unordered,
}

/// Pending set query settings
#[derive(Debug, Clone)]
pub struct PendingSettings {
	/// Current block number (affects readiness of some transactions).
	pub block_number: u64,
	/// Current timestamp (affects readiness of some transactions).
	pub current_timestamp: u64,
	/// Nonce cap (for dust protection; EIP-168)
	pub nonce_cap: Option<U256>,
	/// Maximal number of transactions in pending the set.
	pub max_len: usize,
	/// Ordering of transactions.
	pub ordering: PendingOrdering,
}

impl PendingSettings {
	/// Get all transactions (no cap or len limit) prioritized.
	pub fn all_prioritized(block_number: u64, current_timestamp: u64) -> Self {
		PendingSettings {
			block_number,
			current_timestamp,
			nonce_cap: None,
			max_len: usize::max_value(),
			ordering: PendingOrdering::Priority,
		}
	}
}

/// Transaction priority.
#[derive(Debug, PartialEq, Eq, PartialOrd,  Clone, Copy)]
pub(crate) enum Priority {
	/// Regular transactions received over the network. (no priority boost)
	Regular,
	/// Transactions from retracted blocks (medium priority)
	///
	/// When block becomes non-canonical we re-import the transactions it contains
	/// to the queue and boost their priority.
	Retracted,
	/// Local transactions (high priority)
	///
	/// Transactions either from a local account or
	/// submitted over local RPC connection via `eth_sendRawTransaction`
	Local,
}

impl Priority {
	fn is_local(&self) -> bool {
		match *self {
			Priority::Local => true,
			_ => false,
		}
	}
}

/// Verified transaction stored in the pool.
#[derive(Debug, PartialEq, Eq)]
pub struct VerifiedTransaction {
	transaction: transaction::PendingTransaction,
	// TODO [ToDr] hash and sender should go directly from the transaction
	hash: H256,
	sender: Address,
	priority: Priority,
	insertion_id: usize,
}

impl VerifiedTransaction {
	/// Create `VerifiedTransaction` directly from `SignedTransaction`.
	///
	/// This method should be used only:
	/// 1. for tests
	/// 2. In case we are converting pending block transactions that are already in the queue to match the function signature.
	pub fn from_pending_block_transaction(tx: transaction::SignedTransaction) -> Self {
		let hash = tx.hash();
		let sender = tx.sender();
		VerifiedTransaction {
			transaction: tx.into(),
			hash,
			sender,
			priority: Priority::Retracted,
			insertion_id: 0,
		}
	}

	/// Gets transaction priority.
	pub(crate) fn priority(&self) -> Priority {
		self.priority
	}

	/// Gets transaction insertion id.
	pub(crate) fn insertion_id(&self) -> usize {
		self.insertion_id
	}

	/// Gets wrapped `SignedTransaction`
	pub fn signed(&self) -> &transaction::SignedTransaction {
		&self.transaction
	}

	/// Gets wrapped `PendingTransaction`
	pub fn pending(&self) -> &transaction::PendingTransaction {
		&self.transaction
	}

}

impl txpool::VerifiedTransaction for VerifiedTransaction {
	type Hash = H256;
	type Sender = Address;

	fn hash(&self) -> &H256 {
		&self.hash
	}

	fn mem_usage(&self) -> usize {
		self.transaction.heap_size_of_children()
	}

	fn sender(&self) -> &Address {
		&self.sender
	}
}