Separate status for canceled local transactions. (#5319)
This commit is contained in:
parent
5fa088114c
commit
d4684d6302
@ -17,7 +17,7 @@
|
|||||||
//! Local Transactions List.
|
//! Local Transactions List.
|
||||||
|
|
||||||
use linked_hash_map::LinkedHashMap;
|
use linked_hash_map::LinkedHashMap;
|
||||||
use transaction::SignedTransaction;
|
use transaction::{SignedTransaction, PendingTransaction};
|
||||||
use error::TransactionError;
|
use error::TransactionError;
|
||||||
use util::{U256, H256};
|
use util::{U256, H256};
|
||||||
|
|
||||||
@ -40,6 +40,8 @@ pub enum Status {
|
|||||||
Rejected(SignedTransaction, TransactionError),
|
Rejected(SignedTransaction, TransactionError),
|
||||||
/// Transaction is invalid.
|
/// Transaction is invalid.
|
||||||
Invalid(SignedTransaction),
|
Invalid(SignedTransaction),
|
||||||
|
/// Transaction was canceled.
|
||||||
|
Canceled(PendingTransaction),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Status {
|
impl Status {
|
||||||
@ -99,6 +101,12 @@ impl LocalTransactionsList {
|
|||||||
self.clear_old();
|
self.clear_old();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mark_canceled(&mut self, tx: PendingTransaction) {
|
||||||
|
warn!(target: "own_tx", "Transaction canceled (hash {:?})", tx.hash());
|
||||||
|
self.transactions.insert(tx.hash(), Status::Canceled(tx));
|
||||||
|
self.clear_old();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mark_dropped(&mut self, tx: SignedTransaction) {
|
pub fn mark_dropped(&mut self, tx: SignedTransaction) {
|
||||||
warn!(target: "own_tx", "Transaction dropped (hash {:?})", tx.hash());
|
warn!(target: "own_tx", "Transaction dropped (hash {:?})", tx.hash());
|
||||||
self.transactions.insert(tx.hash(), Status::Dropped(tx));
|
self.transactions.insert(tx.hash(), Status::Dropped(tx));
|
||||||
|
@ -29,7 +29,7 @@ use transaction::{Action, UnverifiedTransaction, PendingTransaction, SignedTrans
|
|||||||
use receipt::{Receipt, RichReceipt};
|
use receipt::{Receipt, RichReceipt};
|
||||||
use spec::Spec;
|
use spec::Spec;
|
||||||
use engines::{Engine, Seal};
|
use engines::{Engine, Seal};
|
||||||
use miner::{MinerService, MinerStatus, TransactionQueue, TransactionQueueDetailsProvider, PrioritizationStrategy,
|
use miner::{MinerService, MinerStatus, TransactionQueue, RemovalReason, TransactionQueueDetailsProvider, PrioritizationStrategy,
|
||||||
AccountDetails, TransactionOrigin};
|
AccountDetails, TransactionOrigin};
|
||||||
use miner::banning_queue::{BanningTransactionQueue, Threshold};
|
use miner::banning_queue::{BanningTransactionQueue, Threshold};
|
||||||
use miner::work_notify::{WorkPoster, NotifyWork};
|
use miner::work_notify::{WorkPoster, NotifyWork};
|
||||||
@ -430,7 +430,7 @@ impl Miner {
|
|||||||
{
|
{
|
||||||
let mut queue = self.transaction_queue.write();
|
let mut queue = self.transaction_queue.write();
|
||||||
for hash in invalid_transactions {
|
for hash in invalid_transactions {
|
||||||
queue.remove_invalid(&hash, &fetch_nonce);
|
queue.remove(&hash, &fetch_nonce, RemovalReason::Invalid);
|
||||||
}
|
}
|
||||||
for hash in transactions_to_penalize {
|
for hash in transactions_to_penalize {
|
||||||
queue.penalize(&hash);
|
queue.penalize(&hash);
|
||||||
@ -1021,7 +1021,7 @@ impl MinerService for Miner {
|
|||||||
let tx = queue.find(hash);
|
let tx = queue.find(hash);
|
||||||
if tx.is_some() {
|
if tx.is_some() {
|
||||||
let fetch_nonce = |a: &Address| chain.latest_nonce(a);
|
let fetch_nonce = |a: &Address| chain.latest_nonce(a);
|
||||||
queue.remove_invalid(hash, &fetch_nonce);
|
queue.remove(hash, &fetch_nonce, RemovalReason::Canceled);
|
||||||
}
|
}
|
||||||
tx
|
tx
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ mod stratum;
|
|||||||
pub use self::external::{ExternalMiner, ExternalMinerService};
|
pub use self::external::{ExternalMiner, ExternalMinerService};
|
||||||
|
|
||||||
pub use self::miner::{Miner, MinerOptions, Banning, PendingSet, GasPricer, GasPriceCalibratorOptions, GasLimit};
|
pub use self::miner::{Miner, MinerOptions, Banning, PendingSet, GasPricer, GasPriceCalibratorOptions, GasLimit};
|
||||||
pub use self::transaction_queue::{TransactionQueue, TransactionDetailsProvider as TransactionQueueDetailsProvider,
|
pub use self::transaction_queue::{TransactionQueue, RemovalReason, TransactionDetailsProvider as TransactionQueueDetailsProvider,
|
||||||
PrioritizationStrategy, AccountDetails, TransactionOrigin};
|
PrioritizationStrategy, AccountDetails, TransactionOrigin};
|
||||||
pub use self::local_transactions::{Status as LocalTransactionStatus};
|
pub use self::local_transactions::{Status as LocalTransactionStatus};
|
||||||
pub use client::TransactionImportResult;
|
pub use client::TransactionImportResult;
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
//!
|
//!
|
||||||
//! use util::{Uint, U256, Address};
|
//! use util::{Uint, U256, Address};
|
||||||
//! use ethkey::{Random, Generator};
|
//! use ethkey::{Random, Generator};
|
||||||
//! use ethcore::miner::{TransactionQueue, TransactionQueueDetailsProvider, AccountDetails, TransactionOrigin};
|
//! use ethcore::miner::{TransactionQueue, RemovalReason, TransactionQueueDetailsProvider, AccountDetails, TransactionOrigin};
|
||||||
//! use ethcore::transaction::*;
|
//! use ethcore::transaction::*;
|
||||||
//! use rustc_serialize::hex::FromHex;
|
//! use rustc_serialize::hex::FromHex;
|
||||||
//!
|
//!
|
||||||
@ -80,7 +80,7 @@
|
|||||||
//!
|
//!
|
||||||
//! // And when transaction is removed (but nonce haven't changed)
|
//! // And when transaction is removed (but nonce haven't changed)
|
||||||
//! // it will move subsequent transactions to future
|
//! // it will move subsequent transactions to future
|
||||||
//! txq.remove_invalid(&st1.hash(), &|_| 10.into());
|
//! txq.remove(&st1.hash(), &|_| 10.into(), RemovalReason::Invalid);
|
||||||
//! assert_eq!(txq.status().pending, 0);
|
//! assert_eq!(txq.status().pending, 0);
|
||||||
//! assert_eq!(txq.status().future, 1);
|
//! assert_eq!(txq.status().future, 1);
|
||||||
//! assert_eq!(txq.top_transactions().len(), 0);
|
//! assert_eq!(txq.top_transactions().len(), 0);
|
||||||
@ -510,6 +510,15 @@ pub enum PrioritizationStrategy {
|
|||||||
GasFactorAndGasPrice,
|
GasFactorAndGasPrice,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reason to remove single transaction from the queue.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum RemovalReason {
|
||||||
|
/// Transaction is invalid
|
||||||
|
Invalid,
|
||||||
|
/// Transaction was canceled
|
||||||
|
Canceled,
|
||||||
|
}
|
||||||
|
|
||||||
/// Point in time when transaction was inserted.
|
/// Point in time when transaction was inserted.
|
||||||
pub type QueuingInstant = BlockNumber;
|
pub type QueuingInstant = BlockNumber;
|
||||||
const DEFAULT_QUEUING_PERIOD: BlockNumber = 128;
|
const DEFAULT_QUEUING_PERIOD: BlockNumber = 128;
|
||||||
@ -897,7 +906,7 @@ impl TransactionQueue {
|
|||||||
.expect("We fetch details for all senders from both current and future")
|
.expect("We fetch details for all senders from both current and future")
|
||||||
.nonce;
|
.nonce;
|
||||||
for hash in invalid {
|
for hash in invalid {
|
||||||
self.remove_invalid(&hash, &fetch_nonce);
|
self.remove(&hash, &fetch_nonce, RemovalReason::Invalid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -945,7 +954,7 @@ impl TransactionQueue {
|
|||||||
/// so transactions left in queue are processed according to client nonce.
|
/// so transactions left in queue are processed according to client nonce.
|
||||||
///
|
///
|
||||||
/// If gap is introduced marks subsequent transactions as future
|
/// If gap is introduced marks subsequent transactions as future
|
||||||
pub fn remove_invalid<F>(&mut self, transaction_hash: &H256, fetch_nonce: &F)
|
pub fn remove<F>(&mut self, transaction_hash: &H256, fetch_nonce: &F, reason: RemovalReason)
|
||||||
where F: Fn(&Address) -> U256 {
|
where F: Fn(&Address) -> U256 {
|
||||||
|
|
||||||
assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len());
|
assert_eq!(self.future.by_priority.len() + self.current.by_priority.len(), self.by_hash.len());
|
||||||
@ -964,7 +973,14 @@ impl TransactionQueue {
|
|||||||
|
|
||||||
// Mark in locals
|
// Mark in locals
|
||||||
if self.local_transactions.contains(transaction_hash) {
|
if self.local_transactions.contains(transaction_hash) {
|
||||||
self.local_transactions.mark_invalid(transaction.transaction.into());
|
match reason {
|
||||||
|
RemovalReason::Invalid => self.local_transactions.mark_invalid(
|
||||||
|
transaction.transaction.into()
|
||||||
|
),
|
||||||
|
RemovalReason::Canceled => self.local_transactions.mark_canceled(
|
||||||
|
PendingTransaction::new(transaction.transaction, transaction.condition)
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from future
|
// Remove from future
|
||||||
@ -2277,7 +2293,7 @@ pub mod test {
|
|||||||
assert_eq!(txq.status().pending, 3);
|
assert_eq!(txq.status().pending, 3);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
txq.remove_invalid(&tx.hash(), &|_| default_nonce());
|
txq.remove(&tx.hash(), &|_| default_nonce(), RemovalReason::Invalid);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let stats = txq.status();
|
let stats = txq.status();
|
||||||
@ -2420,7 +2436,7 @@ pub mod test {
|
|||||||
assert_eq!(txq.status().pending, 2);
|
assert_eq!(txq.status().pending, 2);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
txq.remove_invalid(&tx1.hash(), &|_| default_nonce());
|
txq.remove(&tx1.hash(), &|_| default_nonce(), RemovalReason::Invalid);
|
||||||
assert_eq!(txq.status().pending, 0);
|
assert_eq!(txq.status().pending, 0);
|
||||||
assert_eq!(txq.status().future, 1);
|
assert_eq!(txq.status().future, 1);
|
||||||
txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_tx_provider()).unwrap();
|
txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_tx_provider()).unwrap();
|
||||||
@ -2518,7 +2534,7 @@ pub mod test {
|
|||||||
assert_eq!(txq.status().future, 2);
|
assert_eq!(txq.status().future, 2);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
txq.remove_invalid(&tx1.hash(), &|_| default_nonce() + 1.into());
|
txq.remove(&tx1.hash(), &|_| default_nonce() + 1.into(), RemovalReason::Invalid);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
let stats = txq.status();
|
let stats = txq.status();
|
||||||
|
@ -91,6 +91,8 @@ pub enum LocalTransactionStatus {
|
|||||||
Rejected(Transaction, String),
|
Rejected(Transaction, String),
|
||||||
/// Transaction is invalid.
|
/// Transaction is invalid.
|
||||||
Invalid(Transaction),
|
Invalid(Transaction),
|
||||||
|
/// Transaction was canceled.
|
||||||
|
Canceled(Transaction),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for LocalTransactionStatus {
|
impl Serialize for LocalTransactionStatus {
|
||||||
@ -101,7 +103,7 @@ impl Serialize for LocalTransactionStatus {
|
|||||||
|
|
||||||
let elems = match *self {
|
let elems = match *self {
|
||||||
Pending | Future => 1,
|
Pending | Future => 1,
|
||||||
Mined(..) | Dropped(..) | Invalid(..) => 2,
|
Mined(..) | Dropped(..) | Invalid(..) | Canceled(..) => 2,
|
||||||
Rejected(..) => 3,
|
Rejected(..) => 3,
|
||||||
Replaced(..) => 4,
|
Replaced(..) => 4,
|
||||||
};
|
};
|
||||||
@ -121,6 +123,10 @@ impl Serialize for LocalTransactionStatus {
|
|||||||
struc.serialize_field(status, "dropped")?;
|
struc.serialize_field(status, "dropped")?;
|
||||||
struc.serialize_field(transaction, tx)?;
|
struc.serialize_field(transaction, tx)?;
|
||||||
},
|
},
|
||||||
|
Canceled(ref tx) => {
|
||||||
|
struc.serialize_field(status, "canceled")?;
|
||||||
|
struc.serialize_field(transaction, tx)?;
|
||||||
|
},
|
||||||
Invalid(ref tx) => {
|
Invalid(ref tx) => {
|
||||||
struc.serialize_field(status, "invalid")?;
|
struc.serialize_field(status, "invalid")?;
|
||||||
struc.serialize_field(transaction, tx)?;
|
struc.serialize_field(transaction, tx)?;
|
||||||
@ -249,6 +255,7 @@ impl From<miner::LocalTransactionStatus> for LocalTransactionStatus {
|
|||||||
Rejected(tx, err) => LocalTransactionStatus::Rejected(tx.into(), errors::transaction_message(err)),
|
Rejected(tx, err) => LocalTransactionStatus::Rejected(tx.into(), errors::transaction_message(err)),
|
||||||
Replaced(tx, gas_price, hash) => LocalTransactionStatus::Replaced(tx.into(), gas_price.into(), hash.into()),
|
Replaced(tx, gas_price, hash) => LocalTransactionStatus::Replaced(tx.into(), gas_price.into(), hash.into()),
|
||||||
Invalid(tx) => LocalTransactionStatus::Invalid(tx.into()),
|
Invalid(tx) => LocalTransactionStatus::Invalid(tx.into()),
|
||||||
|
Canceled(tx) => LocalTransactionStatus::Canceled(tx.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user