From 2952ea1b854d0e5f8d3f69ed14320014887bad59 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 15 Dec 2016 18:19:19 +0100 Subject: [PATCH 1/7] Delayed transactions --- ethcore/light/src/client.rs | 6 +- ethcore/light/src/net/tests/mod.rs | 4 +- ethcore/light/src/provider.rs | 8 +- ethcore/res/ethereum/tests | 2 +- ethcore/src/client/client.rs | 4 +- ethcore/src/client/test_client.rs | 4 +- ethcore/src/client/traits.rs | 4 +- ethcore/src/miner/banning_queue.rs | 4 +- ethcore/src/miner/miner.rs | 57 ++-- ethcore/src/miner/mod.rs | 13 +- ethcore/src/miner/transaction_queue.rs | 341 +++++++++++++--------- ethcore/src/types/transaction.rs | 28 ++ rpc/src/v1/helpers/dispatch.rs | 11 +- rpc/src/v1/helpers/requests.rs | 5 + rpc/src/v1/helpers/signing_queue.rs | 1 + rpc/src/v1/impls/eth.rs | 4 +- rpc/src/v1/impls/parity.rs | 6 + rpc/src/v1/impls/signer.rs | 8 +- rpc/src/v1/tests/helpers/miner_service.rs | 20 +- rpc/src/v1/tests/mocked/eth.rs | 3 +- rpc/src/v1/tests/mocked/signer.rs | 8 +- rpc/src/v1/tests/mocked/signing.rs | 1 + rpc/src/v1/traits/parity.rs | 4 + rpc/src/v1/types/block.rs | 2 +- rpc/src/v1/types/confirmations.rs | 15 +- rpc/src/v1/types/transaction.rs | 17 +- rpc/src/v1/types/transaction_request.rs | 15 +- sync/src/chain.rs | 10 +- sync/src/tests/consensus.rs | 4 +- 29 files changed, 387 insertions(+), 222 deletions(-) diff --git a/ethcore/light/src/client.rs b/ethcore/light/src/client.rs index 73e85b31c..80100f17c 100644 --- a/ethcore/light/src/client.rs +++ b/ethcore/light/src/client.rs @@ -24,7 +24,7 @@ use ethcore::service::ClientIoMessage; use ethcore::block_import_error::BlockImportError; use ethcore::block_status::BlockStatus; use ethcore::verification::queue::{HeaderQueue, QueueInfo}; -use ethcore::transaction::SignedTransaction; +use ethcore::transaction::{SignedTransaction, PendingTransaction}; use ethcore::blockchain_info::BlockChainInfo; use io::IoChannel; @@ -114,7 +114,7 @@ impl Provider for Client { Vec::new() } - fn pending_transactions(&self) -> Vec { + fn pending_transactions(&self) -> Vec { Vec::new() } -} \ No newline at end of file +} diff --git a/ethcore/light/src/net/tests/mod.rs b/ethcore/light/src/net/tests/mod.rs index 99f695b81..f9551fc9a 100644 --- a/ethcore/light/src/net/tests/mod.rs +++ b/ethcore/light/src/net/tests/mod.rs @@ -20,7 +20,7 @@ use ethcore::blockchain_info::BlockChainInfo; use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient}; use ethcore::ids::BlockId; -use ethcore::transaction::SignedTransaction; +use ethcore::transaction::PendingTransaction; use network::{PeerId, NodeId}; use net::buffer_flow::FlowParams; @@ -169,7 +169,7 @@ impl Provider for TestProvider { req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect() } - fn pending_transactions(&self) -> Vec { + fn pending_transactions(&self) -> Vec { self.0.client.pending_transactions() } } diff --git a/ethcore/light/src/provider.rs b/ethcore/light/src/provider.rs index d820ee6d0..ce80929c2 100644 --- a/ethcore/light/src/provider.rs +++ b/ethcore/light/src/provider.rs @@ -19,7 +19,7 @@ use ethcore::blockchain_info::BlockChainInfo; use ethcore::client::{BlockChainClient, ProvingBlockChainClient}; -use ethcore::transaction::SignedTransaction; +use ethcore::transaction::PendingTransaction; use ethcore::ids::BlockId; use util::{Bytes, H256}; @@ -79,7 +79,7 @@ pub trait Provider: Send + Sync { fn header_proofs(&self, req: request::HeaderProofs) -> Vec; /// Provide pending transactions. - fn pending_transactions(&self) -> Vec; + fn pending_transactions(&self) -> Vec; } // Implementation of a light client data provider for a client. @@ -178,7 +178,7 @@ impl Provider for T { req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect() } - fn pending_transactions(&self) -> Vec { + fn pending_transactions(&self) -> Vec { BlockChainClient::pending_transactions(self) } -} \ No newline at end of file +} diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests index 9028c4801..e8f4624b7 160000 --- a/ethcore/res/ethereum/tests +++ b/ethcore/res/ethereum/tests @@ -1 +1 @@ -Subproject commit 9028c4801fd39fbb71a9796979182549a24e81c8 +Subproject commit e8f4624b7f1a15c63674eecf577c7ab76c3b16be diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index dce594617..39f7420f8 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -42,7 +42,7 @@ use env_info::LastHashes; use verification; use verification::{PreverifiedBlock, Verifier}; use block::*; -use transaction::{LocalizedTransaction, SignedTransaction, Action}; +use transaction::{LocalizedTransaction, SignedTransaction, PendingTransaction, Action}; use blockchain::extras::TransactionAddress; use types::filter::Filter; use types::mode::Mode as IpcMode; @@ -1286,7 +1286,7 @@ impl BlockChainClient for Client { } } - fn pending_transactions(&self) -> Vec { + fn pending_transactions(&self) -> Vec { self.miner.pending_transactions(self.chain.read().best_block_number()) } diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 44954f99d..f730c7d9c 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -21,7 +21,7 @@ use util::*; use rlp::*; use ethkey::{Generator, Random}; use devtools::*; -use transaction::{Transaction, LocalizedTransaction, SignedTransaction, Action}; +use transaction::{Transaction, LocalizedTransaction, SignedTransaction, PendingTransaction, Action}; use blockchain::TreeRoute; use client::{ BlockChainClient, MiningBlockChainClient, BlockChainInfo, BlockStatus, BlockId, @@ -663,7 +663,7 @@ impl BlockChainClient for TestBlockChainClient { self.miner.import_external_transactions(self, txs); } - fn pending_transactions(&self) -> Vec { + fn pending_transactions(&self) -> Vec { self.miner.pending_transactions(self.chain_info().best_block_number) } diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index f44a4496f..7afe96f57 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -21,7 +21,7 @@ use blockchain::TreeRoute; use verification::queue::QueueInfo as BlockQueueInfo; use block::{OpenBlock, SealedBlock}; use header::{BlockNumber}; -use transaction::{LocalizedTransaction, SignedTransaction}; +use transaction::{LocalizedTransaction, SignedTransaction, PendingTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; use views::{BlockView}; @@ -203,7 +203,7 @@ pub trait BlockChainClient : Sync + Send { fn queue_transactions(&self, transactions: Vec, peer_id: usize); /// list all transactions - fn pending_transactions(&self) -> Vec; + fn pending_transactions(&self) -> Vec; /// Sorted list of transaction gas prices from at least last sample_size blocks. fn gas_price_corpus(&self, sample_size: usize) -> Vec { diff --git a/ethcore/src/miner/banning_queue.rs b/ethcore/src/miner/banning_queue.rs index d8b038c15..1fe345614 100644 --- a/ethcore/src/miner/banning_queue.rs +++ b/ethcore/src/miner/banning_queue.rs @@ -115,7 +115,7 @@ impl BanningTransactionQueue { } } } - self.queue.add(transaction, TransactionOrigin::External, account_details, gas_estimator) + self.queue.add(transaction, TransactionOrigin::External, None, account_details, gas_estimator) } /// Ban transaction with given hash. @@ -263,7 +263,7 @@ mod tests { let mut txq = queue(); // when - txq.queue().add(tx, TransactionOrigin::External, &default_account_details, &gas_required).unwrap(); + txq.queue().add(tx, TransactionOrigin::External, None, &default_account_details, &gas_required).unwrap(); // then // should also deref to queue diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index a6a63ccaf..a01f16523 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -28,7 +28,7 @@ use client::TransactionImportResult; use executive::contract_address; use block::{ClosedBlock, SealedBlock, IsBlock, Block}; use error::*; -use transaction::{Action, SignedTransaction}; +use transaction::{Action, SignedTransaction, PendingTransaction}; use receipt::{Receipt, RichReceipt}; use spec::Spec; use engines::Engine; @@ -320,11 +320,12 @@ impl Miner { } let _timer = PerfTimer::new("prepare_block"); + let chain_info = chain.chain_info(); let (transactions, mut open_block, original_work_hash) = { - let transactions = {self.transaction_queue.lock().top_transactions()}; + let transactions = {self.transaction_queue.lock().top_transactions_at(chain_info.best_block_number)}; let mut sealing_work = self.sealing_work.lock(); let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().fields().header.hash()); - let best_hash = chain.best_block_header().sha3(); + let best_hash = chain_info.best_block_hash; /* // check to see if last ClosedBlock in would_seals is actually same parent block. // if so @@ -568,8 +569,14 @@ impl Miner { prepare_new } - fn add_transactions_to_queue(&self, chain: &MiningBlockChainClient, transactions: Vec, default_origin: TransactionOrigin, transaction_queue: &mut BanningTransactionQueue) -> - Vec> { + fn add_transactions_to_queue( + &self, + chain: &MiningBlockChainClient, + transactions: Vec, + default_origin: TransactionOrigin, + min_block: Option, + transaction_queue: &mut BanningTransactionQueue) + -> Vec> { let fetch_account = |a: &Address| AccountDetails { nonce: chain.latest_nonce(a), @@ -604,7 +611,7 @@ impl Miner { match origin { TransactionOrigin::Local | TransactionOrigin::RetractedBlock => { - transaction_queue.add(tx, origin, &fetch_account, &gas_required) + transaction_queue.add(tx, origin, min_block, &fetch_account, &gas_required) }, TransactionOrigin::External => { transaction_queue.add_with_banlist(tx, &fetch_account, &gas_required) @@ -830,7 +837,7 @@ impl MinerService for Miner { let results = { let mut transaction_queue = self.transaction_queue.lock(); self.add_transactions_to_queue( - chain, transactions, TransactionOrigin::External, &mut transaction_queue + chain, transactions, TransactionOrigin::External, None, &mut transaction_queue ) }; @@ -848,17 +855,17 @@ impl MinerService for Miner { fn import_own_transaction( &self, chain: &MiningBlockChainClient, - transaction: SignedTransaction, + pending: PendingTransaction, ) -> Result { - let hash = transaction.hash(); - trace!(target: "own_tx", "Importing transaction: {:?}", transaction); + let hash = pending.transaction.hash(); + trace!(target: "own_tx", "Importing transaction: {:?}", pending); let imported = { // Be sure to release the lock before we call prepare_work_sealing let mut transaction_queue = self.transaction_queue.lock(); let import = self.add_transactions_to_queue( - chain, vec![transaction], TransactionOrigin::Local, &mut transaction_queue + chain, vec![pending.transaction], TransactionOrigin::Local, pending.min_block, &mut transaction_queue ).pop().expect("one result returned per added transaction; one added => one result; qed"); match import { @@ -893,9 +900,9 @@ impl MinerService for Miner { imported } - fn all_transactions(&self) -> Vec { + fn all_transactions(&self) -> Vec { let queue = self.transaction_queue.lock(); - queue.top_transactions() + queue.pending_transactions(BlockNumber::max_value()) } fn local_transactions(&self) -> BTreeMap { @@ -906,22 +913,26 @@ impl MinerService for Miner { .collect() } - fn pending_transactions(&self, best_block: BlockNumber) -> Vec { + fn future_transactions(&self) -> Vec { + self.transaction_queue.lock().future_transactions() + } + + fn pending_transactions(&self, best_block: BlockNumber) -> Vec { let queue = self.transaction_queue.lock(); match self.options.pending_set { - PendingSet::AlwaysQueue => queue.top_transactions(), + PendingSet::AlwaysQueue => queue.pending_transactions(best_block), PendingSet::SealingOrElseQueue => { self.from_pending_block( best_block, - || queue.top_transactions(), - |sealing| sealing.transactions().to_owned() + || queue.pending_transactions(best_block), + |sealing| sealing.transactions().iter().map(|t| t.clone().into()).collect() ) }, PendingSet::AlwaysSealing => { self.from_pending_block( best_block, || vec![], - |sealing| sealing.transactions().to_owned() + |sealing| sealing.transactions().iter().map(|t| t.clone().into()).collect() ) }, } @@ -1116,7 +1127,7 @@ impl MinerService for Miner { }).for_each(|txs| { let mut transaction_queue = self.transaction_queue.lock(); let _ = self.add_transactions_to_queue( - chain, txs, TransactionOrigin::RetractedBlock, &mut transaction_queue + chain, txs, TransactionOrigin::RetractedBlock, None, &mut transaction_queue ); }); } @@ -1149,7 +1160,7 @@ mod tests { use ethkey::{Generator, Random}; use client::{BlockChainClient, TestBlockChainClient, EachBlockWith, TransactionImportResult}; use header::BlockNumber; - use types::transaction::{Transaction, SignedTransaction, Action}; + use types::transaction::{Transaction, SignedTransaction, PendingTransaction, Action}; use spec::Spec; use tests::helpers::{generate_dummy_client}; @@ -1228,7 +1239,7 @@ mod tests { let transaction = transaction(); let best_block = 0; // when - let res = miner.import_own_transaction(&client, transaction); + let res = miner.import_own_transaction(&client, PendingTransaction::new(transaction, None)); // then assert_eq!(res.unwrap(), TransactionImportResult::Current); @@ -1248,7 +1259,7 @@ mod tests { let transaction = transaction(); let best_block = 10; // when - let res = miner.import_own_transaction(&client, transaction); + let res = miner.import_own_transaction(&client, PendingTransaction::new(transaction, None)); // then assert_eq!(res.unwrap(), TransactionImportResult::Current); @@ -1305,7 +1316,7 @@ mod tests { assert!(miner.pending_block().is_none()); assert_eq!(client.chain_info().best_block_number, 3 as BlockNumber); - assert_eq!(miner.import_own_transaction(client, transaction()).unwrap(), TransactionImportResult::Current); + assert_eq!(miner.import_own_transaction(client, PendingTransaction::new(transaction(), None)).unwrap(), TransactionImportResult::Current); miner.update_sealing(client); client.flush_queue(); diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 814953c81..fa8e7df0a 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -62,7 +62,7 @@ use block::ClosedBlock; use header::BlockNumber; use receipt::{RichReceipt, Receipt}; use error::{Error, CallError}; -use transaction::SignedTransaction; +use transaction::{SignedTransaction, PendingTransaction}; /// Miner client API pub trait MinerService : Send + Sync { @@ -118,7 +118,7 @@ pub trait MinerService : Send + Sync { Vec>; /// Imports own (node owner) transaction to queue. - fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction) -> + fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: PendingTransaction) -> Result; /// Returns hashes of transactions currently in pending @@ -144,11 +144,14 @@ pub trait MinerService : Send + Sync { /// Query pending transactions for hash. fn transaction(&self, best_block: BlockNumber, hash: &H256) -> Option; - /// Get a list of all transactions. - fn all_transactions(&self) -> Vec; + /// Get a list of all ready transactions in the queue. + fn all_transactions(&self) -> Vec; /// Get a list of all pending transactions. - fn pending_transactions(&self, best_block: BlockNumber) -> Vec; + fn pending_transactions(&self, best_block: BlockNumber) -> Vec; + + /// Get a list of all future transactions. + fn future_transactions(&self) -> Vec; /// Get a list of local transactions with statuses. fn local_transactions(&self) -> BTreeMap; diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 28b39c7e6..a13fc01c4 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -51,8 +51,8 @@ //! let gas_estimator = |_tx: &SignedTransaction| 2.into(); //! //! let mut txq = TransactionQueue::default(); -//! txq.add(st2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); -//! txq.add(st1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); +//! txq.add(st2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); +//! txq.add(st1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); //! //! // Check status //! assert_eq!(txq.status().pending, 2); @@ -94,6 +94,7 @@ use util::table::Table; use transaction::*; use error::{Error, TransactionError}; use client::TransactionImportResult; +use header::BlockNumber; use miner::local_transactions::{LocalTransactionsList, Status as LocalTransactionStatus}; /// Transaction origin @@ -253,18 +254,21 @@ impl Ord for TransactionOrder { /// Verified transaction (with sender) #[derive(Debug)] struct VerifiedTransaction { - /// Transaction + /// Transaction. transaction: SignedTransaction, - /// transaction origin + /// Transaction origin. origin: TransactionOrigin, + /// Delay until specifid block. + min_block: Option, } impl VerifiedTransaction { - fn new(transaction: SignedTransaction, origin: TransactionOrigin) -> Result { + fn new(transaction: SignedTransaction, origin: TransactionOrigin, min_block: Option) -> Result { try!(transaction.sender()); Ok(VerifiedTransaction { transaction: transaction, origin: origin, + min_block: min_block, }) } @@ -620,6 +624,7 @@ impl TransactionQueue { &mut self, tx: SignedTransaction, origin: TransactionOrigin, + min_block: Option, fetch_account: &F, gas_estimator: &G, ) -> Result where @@ -630,7 +635,7 @@ impl TransactionQueue { let hash = tx.hash(); let cloned_tx = tx.clone(); - let result = self.add_internal(tx, origin, fetch_account, gas_estimator); + let result = self.add_internal(tx, origin, min_block, fetch_account, gas_estimator); match result { Ok(TransactionImportResult::Current) => { self.local_transactions.mark_pending(hash); @@ -651,7 +656,7 @@ impl TransactionQueue { } result } else { - self.add_internal(tx, origin, fetch_account, gas_estimator) + self.add_internal(tx, origin, min_block, fetch_account, gas_estimator) } } @@ -660,6 +665,7 @@ impl TransactionQueue { &mut self, tx: SignedTransaction, origin: TransactionOrigin, + min_block: Option, fetch_account: &F, gas_estimator: &G, ) -> Result where @@ -728,7 +734,7 @@ impl TransactionQueue { // Verify signature try!(tx.check_low_s()); - let vtx = try!(VerifiedTransaction::new(tx, origin)); + let vtx = try!(VerifiedTransaction::new(tx, origin, min_block)); let client_account = fetch_account(&vtx.sender()); let cost = vtx.transaction.value + vtx.transaction.gas_price * vtx.transaction.gas; @@ -968,10 +974,48 @@ impl TransactionQueue { /// Returns top transactions from the queue ordered by priority. pub fn top_transactions(&self) -> Vec { - self.current.by_priority + self.top_transactions_at(BlockNumber::max_value()) + + } + + fn collect_pending_transaction(&self, best_block: BlockNumber, mut f: F) + where F: FnMut(&VerifiedTransaction) { + + let mut delayed = HashSet::new(); + for t in self.current.by_priority.iter() { + let tx = self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`"); + let sender = tx.transaction.sender().expect("Queue only contains transactions with valid sender"); + if delayed.contains(&sender) { + continue; + } + if tx.min_block.unwrap_or(0) > best_block { + delayed.insert(sender); + continue; + } + f(&tx); + } + } + + /// Returns top transactions from the queue ordered by priority. + pub fn top_transactions_at(&self, best_block: BlockNumber) -> Vec { + let mut r = Vec::new(); + self.collect_pending_transaction(best_block, |tx| r.push(tx.transaction.clone())); + r + } + + /// Return all ready transactions. + pub fn pending_transactions(&self, best_block: BlockNumber) -> Vec { + let mut r = Vec::new(); + self.collect_pending_transaction(best_block, |tx| r.push(PendingTransaction::new(tx.transaction.clone(), tx.min_block))); + r + } + + /// Return all ready transactions. + pub fn future_transactions(&self) -> Vec { + self.future.by_priority .iter() .map(|t| self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`")) - .map(|t| t.transaction.clone()) + .map(|t| PendingTransaction { transaction: t.transaction.clone(), min_block: t.min_block }) .collect() } @@ -980,15 +1024,6 @@ impl TransactionQueue { self.local_transactions.all_transactions() } - #[cfg(test)] - fn future_transactions(&self) -> Vec { - self.future.by_priority - .iter() - .map(|t| self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`")) - .map(|t| t.transaction.clone()) - .collect() - } - /// Returns hashes of all transactions from current, ordered by priority. pub fn pending_hashes(&self) -> Vec { self.current.by_priority @@ -1353,14 +1388,14 @@ mod test { let (tx1, tx2) = new_tx_pair(123.into(), 1.into(), 1.into(), 0.into()); let sender = tx1.sender().unwrap(); let nonce = tx1.nonce; - txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().pending, 2); assert_eq!(txq.last_nonce(&sender), Some(nonce + 1.into())); // when let tx = new_tx(123.into(), 1.into()); - let res = txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator); + let res = txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator); // then // No longer the case as we don't even consider a transaction that isn't above a full @@ -1392,12 +1427,12 @@ mod test { gas_limit: !U256::zero(), }; let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); - let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External).unwrap(); - let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External).unwrap(); + let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, None).unwrap(); + let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, None).unwrap(); let mut by_hash = { let mut x = HashMap::new(); - let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External).unwrap(); - let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External).unwrap(); + let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External, None).unwrap(); + let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External, None).unwrap(); x.insert(tx1.hash(), tx1); x.insert(tx2.hash(), tx2); x @@ -1435,12 +1470,12 @@ mod test { // Create two transactions with same nonce // (same hash) let (tx1, tx2) = new_tx_pair_default(0.into(), 0.into()); - let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External).unwrap(); - let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External).unwrap(); + let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, None).unwrap(); + let tx2 = VerifiedTransaction::new(tx2, TransactionOrigin::External, None).unwrap(); let by_hash = { let mut x = HashMap::new(); - let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External).unwrap(); - let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External).unwrap(); + let tx1 = VerifiedTransaction::new(tx1.transaction.clone(), TransactionOrigin::External, None).unwrap(); + let tx2 = VerifiedTransaction::new(tx2.transaction.clone(), TransactionOrigin::External, None).unwrap(); x.insert(tx1.hash(), tx1); x.insert(tx2.hash(), tx2); x @@ -1482,10 +1517,10 @@ mod test { gas_limit: !U256::zero(), }; let tx = new_tx_default(); - let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External).unwrap(); + let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External, None).unwrap(); let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly); assert!(set.insert(tx1.sender(), tx1.nonce(), order1).is_none()); - let tx2 = VerifiedTransaction::new(tx, TransactionOrigin::External).unwrap(); + let tx2 = VerifiedTransaction::new(tx, TransactionOrigin::External, None).unwrap(); let order2 = TransactionOrder::for_transaction(&tx2, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly); assert!(set.insert(tx2.sender(), tx2.nonce(), order2).is_some()); } @@ -1502,7 +1537,7 @@ mod test { assert_eq!(set.gas_price_entry_limit(), 0.into()); let tx = new_tx_default(); - let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External).unwrap(); + let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External, None).unwrap(); let order1 = TransactionOrder::for_transaction(&tx1, 0.into(), 1.into(), PrioritizationStrategy::GasPriceOnly); assert!(set.insert(tx1.sender(), tx1.nonce(), order1.clone()).is_none()); assert_eq!(set.gas_price_entry_limit(), 2.into()); @@ -1517,12 +1552,12 @@ mod test { !U256::zero() }; // First insert one transaction to future - let res = txq.add(tx, TransactionOrigin::External, &prev_nonce, &gas_estimator); + let res = txq.add(tx, TransactionOrigin::External, None, &prev_nonce, &gas_estimator); assert_eq!(res.unwrap(), TransactionImportResult::Future); assert_eq!(txq.status().future, 1); // now import second transaction to current - let res = txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator); + let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator); // and then there should be only one transaction in current (the one with higher gas_price) assert_eq!(res.unwrap(), TransactionImportResult::Current); @@ -1542,12 +1577,12 @@ mod test { !U256::zero() }; // First insert one transaction to future - let res = txq.add(tx.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator); + let res = txq.add(tx.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator); assert_eq!(res.unwrap(), TransactionImportResult::Future); assert_eq!(txq.status().future, 1); // now import second transaction to current - let res = txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator); + let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator); // then assert_eq!(res.unwrap(), TransactionImportResult::Current); @@ -1566,7 +1601,7 @@ mod test { let tx = new_tx_default(); // when - let res = txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator); + let res = txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator); // then assert_eq!(res.unwrap(), TransactionImportResult::Current); @@ -1585,10 +1620,10 @@ mod test { txq.set_minimal_gas_price(15.into()); // when - let res1 = txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator); - let res2 = txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator); - let res3 = txq.add(tx3, TransactionOrigin::External, &default_account_details, &gas_estimator); - let res4 = txq.add(tx4, TransactionOrigin::External, &default_account_details, &gas_estimator); + let res1 = txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator); + let res2 = txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator); + let res3 = txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator); + let res4 = txq.add(tx4, TransactionOrigin::External, None, &default_account_details, &gas_estimator); // then assert_eq!(res1.unwrap(), TransactionImportResult::Current); @@ -1619,10 +1654,10 @@ mod test { txq.set_minimal_gas_price(15.into()); // when - let res1 = txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator); - let res2 = txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator); - let res3 = txq.add(tx3, TransactionOrigin::External, &default_account_details, &gas_estimator); - let res4 = txq.add(tx4, TransactionOrigin::External, &default_account_details, &gas_estimator); + let res1 = txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator); + let res2 = txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator); + let res3 = txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator); + let res4 = txq.add(tx4, TransactionOrigin::External, None, &default_account_details, &gas_estimator); // then assert_eq!(res1.unwrap(), TransactionImportResult::Current); @@ -1665,7 +1700,7 @@ mod test { txq.set_gas_limit(limit); // when - let res = txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator); + let res = txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator); // then assert_eq!(unwrap_tx_err(res), TransactionError::GasLimitExceeded { @@ -1689,7 +1724,7 @@ mod test { }; // when - let res = txq.add(tx, TransactionOrigin::External, &account, &gas_estimator); + let res = txq.add(tx, TransactionOrigin::External, None, &account, &gas_estimator); // then assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientBalance { @@ -1709,7 +1744,7 @@ mod test { txq.set_minimal_gas_price(tx.gas_price + U256::one()); // when - let res = txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator); + let res = txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator); // then assert_eq!(unwrap_tx_err(res), TransactionError::InsufficientGasPrice { @@ -1729,7 +1764,7 @@ mod test { txq.set_minimal_gas_price(tx.gas_price + U256::one()); // when - let res = txq.add(tx, TransactionOrigin::Local, &default_account_details, &gas_estimator); + let res = txq.add(tx, TransactionOrigin::Local, None, &default_account_details, &gas_estimator); // then assert_eq!(res.unwrap(), TransactionImportResult::Current); @@ -1759,7 +1794,7 @@ mod test { rlp::decode(s.as_raw()) }; // when - let res = txq.add(stx, TransactionOrigin::External, &default_account_details, &gas_estimator); + let res = txq.add(stx, TransactionOrigin::External, None, &default_account_details, &gas_estimator); // then assert!(res.is_err()); @@ -1773,8 +1808,8 @@ mod test { let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); // when - txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); // then let top = txq.top_transactions(); @@ -1793,9 +1828,9 @@ mod test { // when // first insert the one with higher gas price - txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); // then the one with lower gas price, but local - txq.add(tx.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); // then let top = txq.top_transactions(); @@ -1812,15 +1847,15 @@ mod test { // the second one has same nonce but higher `gas_price` let (_, tx0) = new_similar_tx_pair(); - txq.add(tx0.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx0.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); // the one with higher gas price is first assert_eq!(txq.top_transactions()[0], tx0); assert_eq!(txq.top_transactions()[1], tx1); // when // insert second as local - txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); // then // the order should be updated @@ -1839,9 +1874,9 @@ mod test { // when // first insert local one with higher gas price - txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); // then the one with lower gas price, but from retracted block - txq.add(tx.clone(), TransactionOrigin::RetractedBlock, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx.clone(), TransactionOrigin::RetractedBlock, None, &default_account_details, &gas_estimator).unwrap(); // then let top = txq.top_transactions(); @@ -1857,8 +1892,8 @@ mod test { let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); // when - txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); // then let top = txq.top_transactions(); @@ -1877,10 +1912,10 @@ mod test { let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into()); // insert everything - txq.add(txa.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); - txq.add(txb.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); - txq.add(tx1.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); - txq.add(tx2.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); + txq.add(txa.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); + txq.add(txb.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); + txq.add(tx1.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); assert_eq!(txq.status().future, 4); @@ -1889,10 +1924,10 @@ mod test { // then let top = txq.future_transactions(); - assert_eq!(top[0], txa); - assert_eq!(top[1], txb); - assert_eq!(top[2], tx1); - assert_eq!(top[3], tx2); + assert_eq!(top[0].transaction, txa); + assert_eq!(top[1].transaction, txb); + assert_eq!(top[2].transaction, tx1); + assert_eq!(top[3].transaction, tx2); assert_eq!(top.len(), 4); } @@ -1905,10 +1940,10 @@ mod test { let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into()); // insert everything - txq.add(txa.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); - txq.add(txb.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx1.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); + txq.add(txa.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(txb.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); let top = txq.top_transactions(); assert_eq!(top[0], tx1); @@ -1938,10 +1973,10 @@ mod test { let (tx1, tx2) = new_tx_pair_with_gas_price_increment(3.into()); // insert everything - txq.add(txa.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(txb.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(txa.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(txb.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); let top = txq.top_transactions(); assert_eq!(top[0], tx1); @@ -1970,8 +2005,8 @@ mod test { let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); // when - txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); // then let top = txq.pending_hashes(); @@ -1988,8 +2023,8 @@ mod test { let (tx, tx2) = new_tx_pair_default(2.into(), 0.into()); // when - let res1 = txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - let res2 = txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + let res1 = txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + let res2 = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); // then assert_eq!(res1, TransactionImportResult::Current); @@ -2002,6 +2037,26 @@ mod test { assert_eq!(top[0], tx); } + #[test] + fn should_handle_min_block() { + // given + let mut txq = TransactionQueue::default(); + + let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); + + // when + let res1 = txq.add(tx.clone(), TransactionOrigin::External, Some(1), &default_account_details, &gas_estimator).unwrap(); + let res2 = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + + // then + assert_eq!(res1, TransactionImportResult::Current); + assert_eq!(res2, TransactionImportResult::Current); + let top = txq.top_transactions_at(0); + assert_eq!(top.len(), 0); + let top = txq.top_transactions_at(1); + assert_eq!(top.len(), 2); + } + #[test] fn should_correctly_update_futures_when_removing() { // given @@ -2012,8 +2067,8 @@ mod test { let mut txq = TransactionQueue::default(); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); - txq.add(tx.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); - txq.add(tx2.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(); + txq.add(tx.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(); assert_eq!(txq.status().future, 2); // when @@ -2035,13 +2090,13 @@ mod test { let tx1 = new_unsigned_tx(124.into(), default_gas_val(), 1.into()).sign(secret, None); let tx2 = new_unsigned_tx(125.into(), default_gas_val(), 1.into()).sign(secret, None); - txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().pending, 1); - txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().future, 1); // when - txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); // then let stats = txq.status(); @@ -2057,8 +2112,8 @@ mod test { // given let mut txq2 = TransactionQueue::default(); let (tx, tx2) = new_tx_pair_default(3.into(), 0.into()); - txq2.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq2.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq2.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq2.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq2.status().pending, 1); assert_eq!(txq2.status().future, 1); @@ -2079,10 +2134,10 @@ mod test { let mut txq = TransactionQueue::default(); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let tx3 = new_tx_default(); - txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().future, 1); - txq.add(tx3.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().pending, 3); // when @@ -2101,8 +2156,8 @@ mod test { let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); // add - txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); let stats = txq.status(); assert_eq!(stats.pending, 2); @@ -2121,11 +2176,11 @@ mod test { let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let sender = tx.sender().unwrap(); let nonce = tx.nonce; - txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().pending, 1); // when - let res = txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator); + let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator); // then let t = txq.top_transactions(); @@ -2142,14 +2197,14 @@ mod test { txq.current.set_limit(10); let (tx1, tx2) = new_tx_pair_default(4.into(), 1.into()); let (tx3, tx4) = new_tx_pair_default(4.into(), 2.into()); - txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx3.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().pending, 2); // when - txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().future, 1); - txq.add(tx4.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx4.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); // then assert_eq!(txq.status().future, 1); @@ -2160,11 +2215,11 @@ mod test { let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 100, default_gas_val() * U256::from(2), !U256::zero()); let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1)); let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2)); - txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx3.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); // limited by gas - txq.add(tx4.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap_err(); + txq.add(tx4.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap_err(); assert_eq!(txq.status().pending, 2); } @@ -2174,12 +2229,12 @@ mod test { let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1)); let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2)); let (tx5, _) = new_tx_pair_default(U256::from(1), U256::from(2)); - txq.add(tx1.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); // Not accepted because of limit - txq.add(tx5.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap_err(); - txq.add(tx3.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx4.clone(), TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx5.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap_err(); + txq.add(tx3.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx4.clone(), TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().pending, 4); } @@ -2191,7 +2246,7 @@ mod test { let fetch_last_nonce = |_a: &Address| AccountDetails { nonce: last_nonce, balance: !U256::zero() }; // when - let res = txq.add(tx, TransactionOrigin::External, &fetch_last_nonce, &gas_estimator); + let res = txq.add(tx, TransactionOrigin::External, None, &fetch_last_nonce, &gas_estimator); // then assert_eq!(unwrap_tx_err(res), TransactionError::Old); @@ -2207,12 +2262,12 @@ mod test { balance: !U256::zero() }; let mut txq = TransactionQueue::default(); let (_tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); - txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().future, 1); assert_eq!(txq.status().pending, 0); // when - let res = txq.add(tx2.clone(), TransactionOrigin::External, &nonce, &gas_estimator); + let res = txq.add(tx2.clone(), TransactionOrigin::External, None, &nonce, &gas_estimator); // then assert_eq!(unwrap_tx_err(res), TransactionError::AlreadyImported); @@ -2226,15 +2281,15 @@ mod test { // given let mut txq = TransactionQueue::default(); let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); - txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().pending, 2); // when txq.remove_invalid(&tx1.hash(), &default_account_details); assert_eq!(txq.status().pending, 0); assert_eq!(txq.status().future, 1); - txq.add(tx1.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); // then let stats = txq.status(); @@ -2248,10 +2303,10 @@ mod test { let mut txq = TransactionQueue::default(); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let tx3 = new_tx_default(); - txq.add(tx2.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().future, 1); - txq.add(tx3.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx.clone(), TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx3.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx.clone(), TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().pending, 3); // when @@ -2278,8 +2333,8 @@ mod test { }; // when - txq.add(tx, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); // then let stats = txq.status(); @@ -2306,10 +2361,10 @@ mod test { }; // when - txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.status().future, 1); - txq.add(tx0, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx0, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); // then let stats = txq.status(); @@ -2327,8 +2382,8 @@ mod test { !U256::zero() }; let mut txq = TransactionQueue::default(); let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); - txq.add(tx1.clone(), TransactionOrigin::External, &previous_nonce, &gas_estimator).unwrap(); - txq.add(tx2, TransactionOrigin::External, &previous_nonce, &gas_estimator).unwrap(); + txq.add(tx1.clone(), TransactionOrigin::External, None, &previous_nonce, &gas_estimator).unwrap(); + txq.add(tx2, TransactionOrigin::External, None, &previous_nonce, &gas_estimator).unwrap(); assert_eq!(txq.status().future, 2); // when @@ -2359,7 +2414,7 @@ mod test { let details = |_a: &Address| AccountDetails { nonce: nonce, balance: !U256::zero() }; // when - txq.add(tx, TransactionOrigin::External, &details, &gas_estimator).unwrap(); + txq.add(tx, TransactionOrigin::External, None, &details, &gas_estimator).unwrap(); // then assert_eq!(txq.last_nonce(&from), Some(nonce)); @@ -2374,7 +2429,7 @@ mod test { let details1 = |_a: &Address| AccountDetails { nonce: nonce1, balance: !U256::zero() }; // Insert first transaction - txq.add(tx1, TransactionOrigin::External, &details1, &gas_estimator).unwrap(); + txq.add(tx1, TransactionOrigin::External, None, &details1, &gas_estimator).unwrap(); // when txq.remove_all(tx2.sender().unwrap(), nonce2 + U256::one()); @@ -2394,9 +2449,9 @@ mod test { // when // Insert first transaction - assert_eq!(txq.add(tx1, TransactionOrigin::External, &details1, &gas_estimator).unwrap(), TransactionImportResult::Current); + assert_eq!(txq.add(tx1, TransactionOrigin::External, None, &details1, &gas_estimator).unwrap(), TransactionImportResult::Current); // Second should go to future - assert_eq!(txq.add(tx2, TransactionOrigin::External, &details1, &gas_estimator).unwrap(), TransactionImportResult::Future); + assert_eq!(txq.add(tx2, TransactionOrigin::External, None, &details1, &gas_estimator).unwrap(), TransactionImportResult::Future); // Now block is imported txq.remove_all(sender, nonce2 - U256::from(1)); // tx2 should be not be promoted to current @@ -2415,9 +2470,9 @@ mod test { assert_eq!(txq.has_local_pending_transactions(), false); // when - assert_eq!(txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current); + assert_eq!(txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current); assert_eq!(txq.has_local_pending_transactions(), false); - assert_eq!(txq.add(tx2, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current); + assert_eq!(txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(), TransactionImportResult::Current); // then assert_eq!(txq.has_local_pending_transactions(), true); @@ -2432,8 +2487,8 @@ mod test { default_account_details(a).balance }; // when - assert_eq!(txq.add(tx2, TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future); - assert_eq!(txq.add(tx1.clone(), TransactionOrigin::External, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future); + assert_eq!(txq.add(tx2, TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future); + assert_eq!(txq.add(tx1.clone(), TransactionOrigin::External, None, &prev_nonce, &gas_estimator).unwrap(), TransactionImportResult::Future); // then assert_eq!(txq.future.by_priority.len(), 1); @@ -2458,14 +2513,14 @@ mod test { (tx.sign(secret, None), tx2.sign(secret, None), tx2_2.sign(secret, None), tx3.sign(secret, None)) }; let sender = tx1.sender().unwrap(); - txq.add(tx1, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx3, TransactionOrigin::Local, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx3, TransactionOrigin::Local, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.future.by_priority.len(), 0); assert_eq!(txq.current.by_priority.len(), 3); // when - let res = txq.add(tx2_2, TransactionOrigin::Local, &default_account_details, &gas_estimator); + let res = txq.add(tx2_2, TransactionOrigin::Local, None, &default_account_details, &gas_estimator); // then assert_eq!(txq.last_nonce(&sender).unwrap(), 125.into()); @@ -2481,8 +2536,8 @@ mod test { let high_gas = |_: &SignedTransaction| 100_001.into(); // when - let res1 = txq.add(tx1, TransactionOrigin::Local, &default_account_details, &gas_estimator); - let res2 = txq.add(tx2, TransactionOrigin::Local, &default_account_details, &high_gas); + let res1 = txq.add(tx1, TransactionOrigin::Local, None, &default_account_details, &gas_estimator); + let res2 = txq.add(tx2, TransactionOrigin::Local, None, &default_account_details, &high_gas); // then assert_eq!(res1.unwrap(), TransactionImportResult::Current); @@ -2502,10 +2557,10 @@ mod test { let nonce1 = tx1.nonce; // Insert all transactions - txq.add(tx1, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx2, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx3, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); - txq.add(tx4, TransactionOrigin::External, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx1, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx2, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx3, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); + txq.add(tx4, TransactionOrigin::External, None, &default_account_details, &gas_estimator).unwrap(); assert_eq!(txq.top_transactions().len(), 4); // when diff --git a/ethcore/src/types/transaction.rs b/ethcore/src/types/transaction.rs index 6388120c3..681e38fcc 100644 --- a/ethcore/src/types/transaction.rs +++ b/ethcore/src/types/transaction.rs @@ -390,6 +390,34 @@ impl Deref for LocalizedTransaction { } } +/// Queued information with additional information. +#[derive(Debug, Clone, PartialEq, Eq, Binary)] +pub struct PendingTransaction { + /// Signed transaction data. + pub transaction: SignedTransaction, + /// Gas price. + pub min_block: Option, +} + +impl PendingTransaction { + /// Create a new pending transaction from signed transaction. + pub fn new(signed: SignedTransaction, min_block: Option) -> Self { + PendingTransaction { + transaction: signed, + min_block: min_block, + } + } +} + +impl From for PendingTransaction { + fn from(t: SignedTransaction) -> Self { + PendingTransaction { + transaction: t, + min_block: None, + } + } +} + #[test] fn sender_test() { let t: SignedTransaction = decode(&::rustc_serialize::hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index 93e99646b..79727f50e 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -21,7 +21,7 @@ use util::bytes::ToPretty; use ethkey::Signature; use ethcore::miner::MinerService; use ethcore::client::MiningBlockChainClient; -use ethcore::transaction::{Action, SignedTransaction, Transaction}; +use ethcore::transaction::{Action, SignedTransaction, PendingTransaction, Transaction}; use ethcore::account_provider::AccountProvider; use jsonrpc_core::Error; @@ -79,9 +79,9 @@ fn decrypt(accounts: &AccountProvider, address: Address, msg: Bytes, password: O }) } -pub fn dispatch_transaction(client: &C, miner: &M, signed_transaction: SignedTransaction) -> Result +pub fn dispatch_transaction(client: &C, miner: &M, signed_transaction: PendingTransaction) -> Result where C: MiningBlockChainClient, M: MinerService { - let hash = signed_transaction.hash(); + let hash = signed_transaction.transaction.hash(); miner.import_own_transaction(client, signed_transaction) .map_err(errors::from_transaction_error) @@ -120,10 +120,12 @@ pub fn sign_and_dispatch(client: &C, miner: &M, accounts: &AccountProvider { let network_id = client.signing_network_id(); + let min_block = filled.min_block.clone(); let signed_transaction = try!(sign_no_dispatch(client, miner, accounts, filled, password)); trace!(target: "miner", "send_transaction: dispatching tx: {} for network ID {:?}", rlp::encode(&signed_transaction).to_vec().pretty(), network_id); - dispatch_transaction(&*client, &*miner, signed_transaction) + let pending_transaction = PendingTransaction::new(signed_transaction, min_block); + dispatch_transaction(&*client, &*miner, pending_transaction) } pub fn fill_optional_fields(request: TransactionRequest, client: &C, miner: &M) -> FilledTransactionRequest @@ -137,6 +139,7 @@ pub fn fill_optional_fields(request: TransactionRequest, client: &C, miner gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()), value: request.value.unwrap_or_else(|| 0.into()), data: request.data.unwrap_or_else(Vec::new), + min_block: request.min_block, } } diff --git a/rpc/src/v1/helpers/requests.rs b/rpc/src/v1/helpers/requests.rs index 7249e4c4a..2c14a4b99 100644 --- a/rpc/src/v1/helpers/requests.rs +++ b/rpc/src/v1/helpers/requests.rs @@ -33,6 +33,8 @@ pub struct TransactionRequest { pub data: Option, /// Transaction's nonce pub nonce: Option, + /// Delay until this block if specified. + pub min_block: Option, } /// Transaction request coming from RPC with default values filled in. @@ -52,6 +54,8 @@ pub struct FilledTransactionRequest { pub data: Bytes, /// Transaction's nonce pub nonce: Option, + /// Delay until this block if specified. + pub min_block: Option, } impl From for TransactionRequest { @@ -64,6 +68,7 @@ impl From for TransactionRequest { value: Some(r.value), data: Some(r.data), nonce: r.nonce, + min_block: r.min_block, } } } diff --git a/rpc/src/v1/helpers/signing_queue.rs b/rpc/src/v1/helpers/signing_queue.rs index 03489bad7..7f5d3a6d1 100644 --- a/rpc/src/v1/helpers/signing_queue.rs +++ b/rpc/src/v1/helpers/signing_queue.rs @@ -328,6 +328,7 @@ mod test { value: 10_000_000.into(), data: vec![], nonce: None, + min_block: None, }) } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 1364af033..4bb5458cb 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -38,7 +38,7 @@ use ethcore::header::{Header as BlockHeader, BlockNumber as EthBlockNumber}; use ethcore::block::IsBlock; use ethcore::views::*; use ethcore::ethereum::Ethash; -use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, Action}; +use ethcore::transaction::{Transaction as EthTransaction, SignedTransaction, PendingTransaction, Action}; use ethcore::log_entry::LogEntry; use ethcore::filter::Filter as EthcoreFilter; use ethcore::snapshot::SnapshotService; @@ -613,7 +613,7 @@ impl Eth for EthClient where let raw_transaction = raw.to_vec(); match UntrustedRlp::new(&raw_transaction).as_val() { - Ok(signed_transaction) => dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), signed_transaction).map(Into::into), + Ok(signed_transaction) => dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), PendingTransaction::new(signed_transaction, None)).map(Into::into), Err(e) => Err(errors::from_rlp_error(e)), } } diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 2c6a498a1..a2781b1c6 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -265,6 +265,12 @@ impl Parity for ParityClient where Ok(take_weak!(self.miner).all_transactions().into_iter().map(Into::into).collect::>()) } + fn future_transactions(&self) -> Result, Error> { + try!(self.active()); + + Ok(take_weak!(self.miner).future_transactions().into_iter().map(Into::into).collect::>()) + } + fn pending_transactions_stats(&self) -> Result, Error> { try!(self.active()); diff --git a/rpc/src/v1/impls/signer.rs b/rpc/src/v1/impls/signer.rs index 6e09a5ec8..5a81b8205 100644 --- a/rpc/src/v1/impls/signer.rs +++ b/rpc/src/v1/impls/signer.rs @@ -21,7 +21,7 @@ use std::sync::{Arc, Weak}; use rlp::{UntrustedRlp, View}; use ethcore::account_provider::AccountProvider; use ethcore::client::MiningBlockChainClient; -use ethcore::transaction::SignedTransaction; +use ethcore::transaction::{SignedTransaction, PendingTransaction}; use ethcore::miner::MinerService; use jsonrpc_core::Error; @@ -96,6 +96,9 @@ impl Signer for SignerClient where C: MiningBlockC if let Some(gas) = modification.gas { request.gas = gas.into(); } + if let Some(min_block) = modification.min_block { + request.min_block = min_block; + } } // Execute let result = dispatch::execute(&*client, &*miner, &*accounts, payload, Some(pass)); @@ -135,7 +138,8 @@ impl Signer for SignerClient where C: MiningBlockC // Dispatch if everything is ok if sender_matches && data_matches && value_matches && nonce_matches { - dispatch_transaction(&*client, &*miner, signed_transaction) + let pending_transaction = PendingTransaction::new(signed_transaction, request.min_block); + dispatch_transaction(&*client, &*miner, pending_transaction) .map(Into::into) .map(ConfirmationResponse::SendTransaction) } else { diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 132e2a5e0..0ef0ee0a9 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -22,7 +22,7 @@ use ethcore::error::{Error, CallError}; use ethcore::client::{MiningBlockChainClient, Executed, CallAnalytics}; use ethcore::block::{ClosedBlock, IsBlock}; use ethcore::header::BlockNumber; -use ethcore::transaction::SignedTransaction; +use ethcore::transaction::{SignedTransaction, PendingTransaction}; use ethcore::receipt::{Receipt, RichReceipt}; use ethcore::miner::{MinerService, MinerStatus, TransactionImportResult, LocalTransactionStatus}; use ethcore::account_provider::Error as AccountError; @@ -160,17 +160,17 @@ impl MinerService for TestMinerService { } /// Imports transactions to transaction queue. - fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: SignedTransaction) -> + fn import_own_transaction(&self, chain: &MiningBlockChainClient, pending: PendingTransaction) -> Result { // keep the pending nonces up to date - if let Ok(ref sender) = transaction.sender() { + if let Ok(ref sender) = pending.transaction.sender() { let nonce = self.last_nonce(sender).unwrap_or(chain.latest_nonce(sender)); self.last_nonces.write().insert(sender.clone(), nonce + U256::from(1)); } // lets assume that all txs are valid - self.imported_transactions.lock().push(transaction); + self.imported_transactions.lock().push(pending.transaction); Ok(TransactionImportResult::Current) } @@ -204,16 +204,20 @@ impl MinerService for TestMinerService { self.pending_transactions.lock().get(hash).cloned() } - fn all_transactions(&self) -> Vec { - self.pending_transactions.lock().values().cloned().collect() + fn all_transactions(&self) -> Vec { + self.pending_transactions.lock().values().cloned().map(Into::into).collect() } fn local_transactions(&self) -> BTreeMap { self.local_transactions.lock().iter().map(|(hash, stats)| (*hash, stats.clone())).collect() } - fn pending_transactions(&self, _best_block: BlockNumber) -> Vec { - self.pending_transactions.lock().values().cloned().collect() + fn pending_transactions(&self, _best_block: BlockNumber) -> Vec { + self.pending_transactions.lock().values().cloned().map(Into::into).collect() + } + + fn future_transactions(&self) -> Vec { + vec![] } fn pending_receipt(&self, _best_block: BlockNumber, hash: &H256) -> Option { diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index ea8409ef2..b8707a159 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -494,7 +494,7 @@ fn rpc_eth_pending_transaction_by_hash() { tester.miner.pending_transactions.lock().insert(H256::zero(), tx); } - let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","networkId":null,"nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#; + let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"creates":null,"from":"0x0f65fe9276bc9a24ae7083ae28e2660ef72df99e","gas":"0x5208","gasPrice":"0x1","hash":"0x41df922fd0d4766fcc02e161f8295ec28522f329ae487f14d811e4b64c8d6e31","input":"0x","minBlock":null,"networkId":null,"nonce":"0x0","publicKey":"0x7ae46da747962c2ee46825839c1ef9298e3bd2e70ca2938495c3693a485ec3eaa8f196327881090ff64cf4fbb0a48485d4f83098e189ed3b7a87d5941b59f789","r":"0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353","raw":"0xf85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","s":"0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804","standardV":"0x0","to":"0x095e7baea6a6c7c4c2dfeb977efac326af552d87","transactionIndex":null,"v":"0x1b","value":"0xa"},"id":1}"#; let request = r#"{ "jsonrpc": "2.0", "method": "eth_getTransactionByHash", @@ -810,6 +810,7 @@ fn rpc_eth_sign_transaction() { r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# + &format!("\"hash\":\"0x{:?}\",", t.hash()) + r#""input":"0x","# + + r#""minBlock":null,"# + &format!("\"networkId\":{},", t.network_id().map_or("null".to_owned(), |n| format!("{}", n))) + r#""nonce":"0x1","# + &format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) + diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index 3537717d4..7ec023a96 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -82,6 +82,7 @@ fn should_return_list_of_items_to_confirm() { value: U256::from(1), data: vec![], nonce: None, + min_block: None, })).unwrap(); tester.signer.add_request(ConfirmationPayload::Signature(1.into(), 5.into())).unwrap(); @@ -89,7 +90,7 @@ fn should_return_list_of_items_to_confirm() { let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#; let response = concat!( r#"{"jsonrpc":"2.0","result":["#, - r#"{"id":"0x1","payload":{"sendTransaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#, + r#"{"id":"0x1","payload":{"sendTransaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","minBlock":null,"nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#, r#"{"id":"0x2","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","hash":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#, r#"],"id":1}"# ); @@ -111,6 +112,7 @@ fn should_reject_transaction_from_queue_without_dispatching() { value: U256::from(1), data: vec![], nonce: None, + min_block: None, })).unwrap(); assert_eq!(tester.signer.requests().len(), 1); @@ -136,6 +138,7 @@ fn should_not_remove_transaction_if_password_is_invalid() { value: U256::from(1), data: vec![], nonce: None, + min_block: None, })).unwrap(); assert_eq!(tester.signer.requests().len(), 1); @@ -178,6 +181,7 @@ fn should_confirm_transaction_and_dispatch() { value: U256::from(1), data: vec![], nonce: None, + min_block: None, })).unwrap(); let t = Transaction { @@ -223,6 +227,7 @@ fn should_confirm_transaction_with_rlp() { value: U256::from(1), data: vec![], nonce: None, + min_block: None, })).unwrap(); let t = Transaction { @@ -270,6 +275,7 @@ fn should_return_error_when_sender_does_not_match() { value: U256::from(1), data: vec![], nonce: None, + min_block: None, })).unwrap(); let t = Transaction { diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index 5217ad402..4040b57b1 100644 --- a/rpc/src/v1/tests/mocked/signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -285,6 +285,7 @@ fn should_add_sign_transaction_to_the_queue() { r#""gas":"0x76c0","gasPrice":"0x9184e72a000","# + &format!("\"hash\":\"0x{:?}\",", t.hash()) + r#""input":"0x","# + + r#""minBlock":null,"# + &format!("\"networkId\":{},", t.network_id().map_or("null".to_owned(), |n| format!("{}", n))) + r#""nonce":"0x1","# + &format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) + diff --git a/rpc/src/v1/traits/parity.rs b/rpc/src/v1/traits/parity.rs index fecc05667..da7125f16 100644 --- a/rpc/src/v1/traits/parity.rs +++ b/rpc/src/v1/traits/parity.rs @@ -122,6 +122,10 @@ build_rpc_trait! { #[rpc(name = "parity_pendingTransactions")] fn pending_transactions(&self) -> Result, Error>; + /// Returns all future transactions from transaction queue. + #[rpc(name = "parity_futureTransactions")] + fn future_transactions(&self) -> Result, Error>; + /// Returns propagation statistics on transactions pending in the queue. #[rpc(name = "parity_pendingTransactionsStats")] fn pending_transactions_stats(&self) -> Result, Error>; diff --git a/rpc/src/v1/types/block.rs b/rpc/src/v1/types/block.rs index 6dd441ee8..680cbd562 100644 --- a/rpc/src/v1/types/block.rs +++ b/rpc/src/v1/types/block.rs @@ -139,7 +139,7 @@ mod tests { fn test_serialize_block_transactions() { let t = BlockTransactions::Full(vec![Transaction::default()]); let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0"}]"#); + assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","minBlock":null}]"#); let t = BlockTransactions::Hashes(vec![H256::default().into()]); let serialized = serde_json::to_string(&t).unwrap(); diff --git a/rpc/src/v1/types/confirmations.rs b/rpc/src/v1/types/confirmations.rs index fd81bf6e7..92567575e 100644 --- a/rpc/src/v1/types/confirmations.rs +++ b/rpc/src/v1/types/confirmations.rs @@ -144,6 +144,9 @@ pub struct TransactionModification { pub gas_price: Option, /// Modified gas pub gas: Option, + /// Modified min block + #[serde(rename="minBlock")] + pub min_block: Option>, } /// Represents two possible return values. @@ -218,12 +221,13 @@ mod tests { value: 100_000.into(), data: vec![1, 2, 3], nonce: Some(1.into()), + min_block: None, }), }; // when let res = serde_json::to_string(&ConfirmationRequest::from(request)); - let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#; + let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","minBlock":null}}}"#; // then assert_eq!(res.unwrap(), expected.to_owned()); @@ -242,12 +246,13 @@ mod tests { value: 100_000.into(), data: vec![1, 2, 3], nonce: Some(1.into()), + min_block: None, }), }; // when let res = serde_json::to_string(&ConfirmationRequest::from(request)); - let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1"}}}"#; + let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","minBlock":null}}}"#; // then assert_eq!(res.unwrap(), expected.to_owned()); @@ -275,7 +280,8 @@ mod tests { fn should_deserialize_modification() { // given let s1 = r#"{ - "gasPrice":"0xba43b7400" + "gasPrice":"0xba43b7400", + "minBlock":42 }"#; let s2 = r#"{"gas": "0x1233"}"#; let s3 = r#"{}"#; @@ -289,14 +295,17 @@ mod tests { assert_eq!(res1, TransactionModification { gas_price: Some(U256::from_str("0ba43b7400").unwrap()), gas: None, + min_block: Some(Some(42)), }); assert_eq!(res2, TransactionModification { gas_price: None, gas: Some(U256::from_str("1233").unwrap()), + min_block: None, }); assert_eq!(res3, TransactionModification { gas_price: None, gas: None, + min_block: None, }); } } diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index 31374e912..04275323d 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -17,7 +17,7 @@ use serde::{Serialize, Serializer}; use ethcore::miner; use ethcore::contract_address; -use ethcore::transaction::{LocalizedTransaction, Action, SignedTransaction}; +use ethcore::transaction::{LocalizedTransaction, Action, PendingTransaction, SignedTransaction}; use v1::helpers::errors; use v1::types::{Bytes, H160, H256, U256, H512}; @@ -69,6 +69,9 @@ pub struct Transaction { pub r: U256, /// The S field of the signature. pub s: U256, + /// Transaction activates at specified block. + #[serde(rename="minBlock")] + pub min_block: Option, } /// Local Transaction Status @@ -187,6 +190,7 @@ impl From for Transaction { v: t.original_v().into(), r: signature.r().into(), s: signature.s().into(), + min_block: None, } } } @@ -220,10 +224,19 @@ impl From for Transaction { v: t.original_v().into(), r: signature.r().into(), s: signature.s().into(), + min_block: None, } } } +impl From for Transaction { + fn from(t: PendingTransaction) -> Transaction { + let mut r = Transaction::from(t.transaction); + r.min_block = t.min_block; + r + } +} + impl From for LocalTransactionStatus { fn from(s: miner::LocalTransactionStatus) -> Self { use ethcore::miner::LocalTransactionStatus::*; @@ -248,7 +261,7 @@ mod tests { fn test_transaction_serialize() { let t = Transaction::default(); let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0"}"#); + assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"networkId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","minBlock":null}"#); } #[test] diff --git a/rpc/src/v1/types/transaction_request.rs b/rpc/src/v1/types/transaction_request.rs index 258346d56..389efa467 100644 --- a/rpc/src/v1/types/transaction_request.rs +++ b/rpc/src/v1/types/transaction_request.rs @@ -38,6 +38,9 @@ pub struct TransactionRequest { pub data: Option, /// Transaction's nonce pub nonce: Option, + /// Delay until this block if specified. + #[serde(rename="minBlock")] + pub min_block: Option, } impl From for TransactionRequest { @@ -50,6 +53,7 @@ impl From for TransactionRequest { value: r.value.map(Into::into), data: r.data.map(Into::into), nonce: r.nonce.map(Into::into), + min_block: r.min_block, } } } @@ -64,6 +68,7 @@ impl From for TransactionRequest { value: Some(r.value.into()), data: Some(r.data.into()), nonce: r.nonce.map(Into::into), + min_block: r.min_block, } } } @@ -78,6 +83,7 @@ impl Into for TransactionRequest { value: self.value.map(Into::into), data: self.data.map(Into::into), nonce: self.nonce.map(Into::into), + min_block: self.min_block, } } } @@ -100,7 +106,8 @@ mod tests { "gas":"0x2", "value":"0x3", "data":"0x123456", - "nonce":"0x4" + "nonce":"0x4", + "minBlock":13 }"#; let deserialized: TransactionRequest = serde_json::from_str(s).unwrap(); @@ -112,6 +119,7 @@ mod tests { value: Some(U256::from(3)), data: Some(vec![0x12, 0x34, 0x56].into()), nonce: Some(U256::from(4)), + min_block: Some(13), }); } @@ -134,7 +142,8 @@ mod tests { gas: Some(U256::from_str("76c0").unwrap()), value: Some(U256::from_str("9184e72a").unwrap()), data: Some("d46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675".from_hex().unwrap().into()), - nonce: None + nonce: None, + min_block: None, }); } @@ -151,6 +160,7 @@ mod tests { value: None, data: None, nonce: None, + min_block: None, }); } @@ -174,6 +184,7 @@ mod tests { value: None, data: Some(vec![0x85, 0x95, 0xba, 0xb1].into()), nonce: None, + min_block: None, }); } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 350a42d0e..67d65ad84 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1901,10 +1901,10 @@ impl ChainSync { return 0; } - let all_transactions_hashes = transactions.iter().map(|tx| tx.hash()).collect::>(); + let all_transactions_hashes = transactions.iter().map(|tx| tx.transaction.hash()).collect::>(); let all_transactions_rlp = { let mut packet = RlpStream::new_list(transactions.len()); - for tx in &transactions { packet.append(tx); } + for tx in &transactions { packet.append(&tx.transaction); } packet.out() }; @@ -1942,11 +1942,11 @@ impl ChainSync { // Construct RLP let mut packet = RlpStream::new_list(to_send.len()); for tx in &transactions { - if to_send.contains(&tx.hash()) { - packet.append(tx); + if to_send.contains(&tx.transaction.hash()) { + packet.append(&tx.transaction); // update stats let id = io.peer_session_info(*peer_id).and_then(|info| info.id); - stats.propagated(tx.hash(), id, block_number); + stats.propagated(tx.transaction.hash(), id, block_number); } } diff --git a/sync/src/tests/consensus.rs b/sync/src/tests/consensus.rs index b96997d1e..78da9258b 100644 --- a/sync/src/tests/consensus.rs +++ b/sync/src/tests/consensus.rs @@ -55,7 +55,7 @@ fn test_authority_round() { }.sign(s1.secret(), None); // exhange statuses net.sync_steps(5); - net.peer(0).chain.miner().import_own_transaction(&net.peer(0).chain, tx1).unwrap(); + net.peer(0).chain.miner().import_own_transaction(&net.peer(0).chain, PendingTransaction::new(tx1, None)).unwrap(); net.sync(); assert_eq!(net.peer(0).chain.chain_info().best_block_number, 1); assert_eq!(net.peer(1).chain.chain_info().best_block_number, 1); @@ -68,7 +68,7 @@ fn test_authority_round() { value: 0.into(), data: Vec::new(), }.sign(s2.secret(), None); - net.peer(1).chain.miner().import_own_transaction(&net.peer(1).chain, tx2).unwrap(); + net.peer(1).chain.miner().import_own_transaction(&net.peer(1).chain, PendingTransaction::new(tx2, None)).unwrap(); net.peer(1).chain.engine().step(); net.peer(1).chain.miner().update_sealing(&net.peer(1).chain); net.sync(); From 3ac0794d2862288dcce12a5f56d689aa186e81b7 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 15 Dec 2016 19:31:26 +0100 Subject: [PATCH 2/7] Bump jsonrpc-core for rpc_cli --- Cargo.lock | 27 +-------------------------- rpc_client/Cargo.toml | 2 +- rpc_client/src/client.rs | 8 ++++---- 3 files changed, 6 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0caea9b8e..6285f159b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -880,18 +880,6 @@ name = "itoa" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "jsonrpc-core" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_codegen 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "jsonrpc-core" version = "4.0.0" @@ -1332,7 +1320,7 @@ dependencies = [ "ethcore-signer 1.5.0", "ethcore-util 1.5.0", "futures 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1368,17 +1356,6 @@ dependencies = [ "parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot" version = "0.3.6" @@ -2182,7 +2159,6 @@ dependencies = [ "checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c" "checksum itertools 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "086e1fa5fe48840b1cfdef3a20c7e3115599f8d5c4c87ef32a794a7cdd184d76" "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" -"checksum jsonrpc-core 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3c5094610b07f28f3edaf3947b732dadb31dbba4941d4d0c1c7a8350208f4414" "checksum jsonrpc-core 4.0.0 (git+https://github.com/ethcore/jsonrpc.git)" = "" "checksum jsonrpc-http-server 6.1.1 (git+https://github.com/ethcore/jsonrpc.git)" = "" "checksum jsonrpc-ipc-server 0.2.4 (git+https://github.com/ethcore/jsonrpc.git)" = "" @@ -2230,7 +2206,6 @@ dependencies = [ "checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7" "checksum parity-dapps-glue 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98378dec0a185da2b7180308752f0bad73aaa949c3e0a3b0528d0e067945f7ab" "checksum parity-ui-precompiled 1.4.0 (git+https://github.com/ethcore/js-precompiled.git)" = "" -"checksum parking_lot 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "968f685642555d2f7e202c48b8b11de80569e9bfea817f7f12d7c61aac62d4e6" "checksum parking_lot 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e1435e7a2a00dfebededd6c6bdbd54008001e94b4a2aadd6aef0dc4c56317621" "checksum parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1b97670a2ffadce7c397fb80a3d687c4f3060140b885621ef1653d0e5d5068" "checksum phf 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "447d9d45f2e0b4a9b532e808365abf18fc211be6ca217202fcd45236ef12f026" diff --git a/rpc_client/Cargo.toml b/rpc_client/Cargo.toml index 9b93a1a5b..e5c8e9b12 100644 --- a/rpc_client/Cargo.toml +++ b/rpc_client/Cargo.toml @@ -8,7 +8,6 @@ version = "1.4.0" [dependencies] futures = "0.1" -jsonrpc-core = "3.0.2" lazy_static = "0.2.1" log = "0.3.6" matches = "0.1.2" @@ -17,6 +16,7 @@ serde = "0.8" serde_json = "0.8" tempdir = "0.3.5" url = "1.2.0" +jsonrpc-core = { git = "https://github.com/ethcore/jsonrpc.git" } ws = { git = "https://github.com/ethcore/ws-rs.git", branch = "mio-upstream-stable" } ethcore-rpc = { path = "../rpc" } ethcore-signer = { path = "../signer" } diff --git a/rpc_client/src/client.rs b/rpc_client/src/client.rs index 9ee9f5c9d..c32b5be7a 100644 --- a/rpc_client/src/client.rs +++ b/rpc_client/src/client.rs @@ -36,7 +36,7 @@ use futures::{BoxFuture, Canceled, Complete, Future, oneshot, done}; use jsonrpc_core::{Id, Version, Params, Error as JsonRpcError}; use jsonrpc_core::request::MethodCall; -use jsonrpc_core::response::{SyncOutput, Success, Failure}; +use jsonrpc_core::response::{Output, Success, Failure}; /// The actual websocket connection handler, passed into the /// event loop of ws-rs @@ -107,13 +107,13 @@ impl Handler for RpcHandler { let ret: Result; let response_id; let string = &msg.to_string(); - match json::from_str::(&string) { - Ok(SyncOutput::Success(Success { result, id: Id::Num(id), .. })) => + match json::from_str::(&string) { + Ok(Output::Success(Success { result, id: Id::Num(id), .. })) => { ret = Ok(result); response_id = id as usize; } - Ok(SyncOutput::Failure(Failure { error, id: Id::Num(id), .. })) => { + Ok(Output::Failure(Failure { error, id: Id::Num(id), .. })) => { ret = Err(error); response_id = id as usize; } From 27580586e00c97de272fe0237629e2a778a5f40b Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 15 Dec 2016 20:09:05 +0100 Subject: [PATCH 3/7] Minor tweaks --- ethcore/src/miner/transaction_queue.rs | 2 +- ethcore/src/types/transaction.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index a13fc01c4..1c8a3d17d 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -984,7 +984,7 @@ impl TransactionQueue { let mut delayed = HashSet::new(); for t in self.current.by_priority.iter() { let tx = self.by_hash.get(&t.hash).expect("All transactions in `current` and `future` are always included in `by_hash`"); - let sender = tx.transaction.sender().expect("Queue only contains transactions with valid sender"); + let sender = tx.sender(); if delayed.contains(&sender) { continue; } diff --git a/ethcore/src/types/transaction.rs b/ethcore/src/types/transaction.rs index 681e38fcc..25e91afe5 100644 --- a/ethcore/src/types/transaction.rs +++ b/ethcore/src/types/transaction.rs @@ -390,7 +390,7 @@ impl Deref for LocalizedTransaction { } } -/// Queued information with additional information. +/// Queued transaction with additional information. #[derive(Debug, Clone, PartialEq, Eq, Binary)] pub struct PendingTransaction { /// Signed transaction data. From e1dd986c413e9a20177d2fcbe42580886858fc2f Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 15 Dec 2016 21:16:32 +0100 Subject: [PATCH 4/7] Hex-encoded block numbers --- rpc/src/v1/impls/signer.rs | 4 ++-- rpc/src/v1/types/block_number.rs | 25 +++++++++++++++++++++++-- rpc/src/v1/types/confirmations.rs | 10 +++++----- rpc/src/v1/types/transaction.rs | 6 +++--- rpc/src/v1/types/transaction_request.rs | 16 ++++++++-------- 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/rpc/src/v1/impls/signer.rs b/rpc/src/v1/impls/signer.rs index 6dc813b73..375cfdf6e 100644 --- a/rpc/src/v1/impls/signer.rs +++ b/rpc/src/v1/impls/signer.rs @@ -82,8 +82,8 @@ impl SignerClient where C: MiningBlockChainClient, if let Some(gas) = modification.gas { request.gas = gas.into(); } - if let Some(min_block) = modification.min_block { - request.min_block = min_block; + if let Some(ref min_block) = modification.min_block { + request.min_block = min_block.as_ref().and_then(|b| b.to_min_block_num()); } } let result = f(&*client, &*miner, &*accounts, payload); diff --git a/rpc/src/v1/types/block_number.rs b/rpc/src/v1/types/block_number.rs index 00ee1f22b..65ebd76be 100644 --- a/rpc/src/v1/types/block_number.rs +++ b/rpc/src/v1/types/block_number.rs @@ -14,12 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use serde::{Deserialize, Deserializer, Error}; +use serde::{Deserialize, Deserializer, Error, Serialize, Serializer}; use serde::de::Visitor; use ethcore::client::BlockId; /// Represents rpc api block number param. -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Hash, Eq)] pub enum BlockNumber { /// Number Num(u64), @@ -44,6 +44,27 @@ impl Deserialize for BlockNumber { } } +impl BlockNumber { + /// Convert block number to min block target. + pub fn to_min_block_num(&self) -> Option { + match *self { + BlockNumber::Num(ref x) => Some(*x), + _ => None, + } + } +} + +impl Serialize for BlockNumber { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { + match *self { + BlockNumber::Num(ref x) => serializer.serialize_str(&format!("0x{:x}", x)), + BlockNumber::Latest => serializer.serialize_str("latest"), + BlockNumber::Earliest => serializer.serialize_str("earliest"), + BlockNumber::Pending => serializer.serialize_str("pending"), + } + } +} + struct BlockNumberVisitor; impl Visitor for BlockNumberVisitor { diff --git a/rpc/src/v1/types/confirmations.rs b/rpc/src/v1/types/confirmations.rs index 0df3e4b52..5f79f675d 100644 --- a/rpc/src/v1/types/confirmations.rs +++ b/rpc/src/v1/types/confirmations.rs @@ -20,7 +20,7 @@ use std::fmt; use serde::{Serialize, Serializer}; use util::log::Colour; -use v1::types::{U256, TransactionRequest, RichRawTransaction, H160, H256, H520, Bytes}; +use v1::types::{U256, TransactionRequest, RichRawTransaction, H160, H256, H520, Bytes, BlockNumber}; use v1::helpers; /// Confirmation waiting in a queue @@ -195,7 +195,7 @@ pub struct TransactionModification { pub gas: Option, /// Modified min block #[serde(rename="minBlock")] - pub min_block: Option>, + pub min_block: Option>, } /// Represents two possible return values. @@ -237,7 +237,7 @@ impl Serialize for Either where mod tests { use std::str::FromStr; use serde_json; - use v1::types::{U256, H256}; + use v1::types::{U256, H256, BlockNumber}; use v1::helpers; use super::*; @@ -330,7 +330,7 @@ mod tests { // given let s1 = r#"{ "gasPrice":"0xba43b7400", - "minBlock":42 + "minBlock":"0x42" }"#; let s2 = r#"{"gas": "0x1233"}"#; let s3 = r#"{}"#; @@ -344,7 +344,7 @@ mod tests { assert_eq!(res1, TransactionModification { gas_price: Some(U256::from_str("0ba43b7400").unwrap()), gas: None, - min_block: Some(Some(42)), + min_block: Some(Some(BlockNumber::Num(0x42))), }); assert_eq!(res2, TransactionModification { gas_price: None, diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index 04275323d..0db614887 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -19,7 +19,7 @@ use ethcore::miner; use ethcore::contract_address; use ethcore::transaction::{LocalizedTransaction, Action, PendingTransaction, SignedTransaction}; use v1::helpers::errors; -use v1::types::{Bytes, H160, H256, U256, H512}; +use v1::types::{Bytes, H160, H256, U256, H512, BlockNumber}; /// Transaction #[derive(Debug, Default, Clone, PartialEq, Serialize)] @@ -71,7 +71,7 @@ pub struct Transaction { pub s: U256, /// Transaction activates at specified block. #[serde(rename="minBlock")] - pub min_block: Option, + pub min_block: Option, } /// Local Transaction Status @@ -232,7 +232,7 @@ impl From for Transaction { impl From for Transaction { fn from(t: PendingTransaction) -> Transaction { let mut r = Transaction::from(t.transaction); - r.min_block = t.min_block; + r.min_block = t.min_block.map(|b| BlockNumber::Num(b)); r } } diff --git a/rpc/src/v1/types/transaction_request.rs b/rpc/src/v1/types/transaction_request.rs index 07ab88588..49cf37ce0 100644 --- a/rpc/src/v1/types/transaction_request.rs +++ b/rpc/src/v1/types/transaction_request.rs @@ -16,7 +16,7 @@ //! `TransactionRequest` type -use v1::types::{Bytes, H160, U256}; +use v1::types::{Bytes, H160, U256, BlockNumber}; use v1::helpers; use util::log::Colour; @@ -43,7 +43,7 @@ pub struct TransactionRequest { pub nonce: Option, /// Delay until this block if specified. #[serde(rename="minBlock")] - pub min_block: Option, + pub min_block: Option, } pub fn format_ether(i: U256) -> String { @@ -93,7 +93,7 @@ impl From for TransactionRequest { value: r.value.map(Into::into), data: r.data.map(Into::into), nonce: r.nonce.map(Into::into), - min_block: r.min_block, + min_block: r.min_block.map(|b| BlockNumber::Num(b)), } } } @@ -108,7 +108,7 @@ impl From for TransactionRequest { value: Some(r.value.into()), data: Some(r.data.into()), nonce: r.nonce.map(Into::into), - min_block: r.min_block, + min_block: r.min_block.map(|b| BlockNumber::Num(b)), } } } @@ -123,7 +123,7 @@ impl Into for TransactionRequest { value: self.value.map(Into::into), data: self.data.map(Into::into), nonce: self.nonce.map(Into::into), - min_block: self.min_block, + min_block: self.min_block.and_then(|b| b.to_min_block_num()), } } } @@ -134,7 +134,7 @@ mod tests { use std::str::FromStr; use rustc_serialize::hex::FromHex; use serde_json; - use v1::types::{U256, H160}; + use v1::types::{U256, H160, BlockNumber}; use super::*; #[test] @@ -147,7 +147,7 @@ mod tests { "value":"0x3", "data":"0x123456", "nonce":"0x4", - "minBlock":13 + "minBlock":"0x13" }"#; let deserialized: TransactionRequest = serde_json::from_str(s).unwrap(); @@ -159,7 +159,7 @@ mod tests { value: Some(U256::from(3)), data: Some(vec![0x12, 0x34, 0x56].into()), nonce: Some(U256::from(4)), - min_block: Some(13), + min_block: Some(BlockNumber::Num(0x13)), }); } From 060cc799a627392578efd164e831786e50b94cf5 Mon Sep 17 00:00:00 2001 From: arkpar Date: Thu, 15 Dec 2016 21:44:31 +0100 Subject: [PATCH 5/7] Minor tweaks --- ethcore/src/miner/transaction_queue.rs | 6 +++--- rpc_client/src/signer_client.rs | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ethcore/src/miner/transaction_queue.rs b/ethcore/src/miner/transaction_queue.rs index 1c8a3d17d..9f5b6399a 100644 --- a/ethcore/src/miner/transaction_queue.rs +++ b/ethcore/src/miner/transaction_queue.rs @@ -978,7 +978,7 @@ impl TransactionQueue { } - fn collect_pending_transaction(&self, best_block: BlockNumber, mut f: F) + fn filter_pending_transaction(&self, best_block: BlockNumber, mut f: F) where F: FnMut(&VerifiedTransaction) { let mut delayed = HashSet::new(); @@ -999,14 +999,14 @@ impl TransactionQueue { /// Returns top transactions from the queue ordered by priority. pub fn top_transactions_at(&self, best_block: BlockNumber) -> Vec { let mut r = Vec::new(); - self.collect_pending_transaction(best_block, |tx| r.push(tx.transaction.clone())); + self.filter_pending_transaction(best_block, |tx| r.push(tx.transaction.clone())); r } /// Return all ready transactions. pub fn pending_transactions(&self, best_block: BlockNumber) -> Vec { let mut r = Vec::new(); - self.collect_pending_transaction(best_block, |tx| r.push(PendingTransaction::new(tx.transaction.clone(), tx.min_block))); + self.filter_pending_transaction(best_block, |tx| r.push(PendingTransaction::new(tx.transaction.clone(), tx.min_block))); r } diff --git a/rpc_client/src/signer_client.rs b/rpc_client/src/signer_client.rs index 996fb0787..6284111ca 100644 --- a/rpc_client/src/signer_client.rs +++ b/rpc_client/src/signer_client.rs @@ -1,7 +1,5 @@ use client::{Rpc, RpcError}; -use rpc::v1::types::{ConfirmationRequest, - TransactionModification, - U256}; +use rpc::v1::types::{ConfirmationRequest, TransactionModification, U256, BlockNumber}; use serde_json::{Value as JsonValue, to_value}; use std::path::PathBuf; use futures::{BoxFuture, Canceled}; @@ -24,7 +22,7 @@ impl SignerRpc { id: U256, new_gas: Option, new_gas_price: Option, - new_min_block: Option>, + new_min_block: Option>, pwd: &str ) -> BoxFuture, Canceled> { From f967713d0815b96e2316bf7904cd60c26185fbd6 Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 16 Dec 2016 13:27:14 +0100 Subject: [PATCH 6/7] Added a test --- ethcore/src/tests/client.rs | 37 ++++++++++++++++++++++++++++++++ ethcore/src/types/transaction.rs | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 51c7086b6..2e9087133 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -28,6 +28,9 @@ use rlp::{Rlp, View}; use spec::Spec; use views::BlockView; use util::stats::Histogram; +use ethkey::KeyPair; +use transaction::{PendingTransaction, Transaction, Action}; +use miner::MinerService; #[test] fn imports_from_empty() { @@ -284,3 +287,37 @@ fn change_history_size() { let client = Client::new(config, &test_spec, dir.as_path(), Arc::new(Miner::with_spec(&test_spec)), IoChannel::disconnected(), &db_config).unwrap(); assert_eq!(client.state().balance(&address), 100.into()); } + +#[test] +fn does_not_propagate_delayed_transactions() { + let key = KeyPair::from_secret("test".sha3()).unwrap(); + let secret = key.secret(); + let tx0 = PendingTransaction::new(Transaction { + nonce: 0.into(), + gas_price: 0.into(), + gas: 21000.into(), + action: Action::Call(Address::default()), + value: 0.into(), + data: Vec::new(), + }.sign(secret, None), Some(2)); + let tx1 = PendingTransaction::new(Transaction { + nonce: 1.into(), + gas_price: 0.into(), + gas: 21000.into(), + action: Action::Call(Address::default()), + value: 0.into(), + data: Vec::new(), + }.sign(secret, None), None); + let client_result = generate_dummy_client(1); + let client = client_result.reference(); + + client.miner().import_own_transaction(&**client, tx0).unwrap(); + client.miner().import_own_transaction(&**client, tx1).unwrap(); + assert_eq!(0, client.pending_transactions().len()); + assert_eq!(2, client.miner().all_transactions().len()); + push_blocks_to_client(client, 53, 2, 1); + client.import_verified_blocks(); + assert_eq!(2, client.pending_transactions().len()); + assert_eq!(2, client.miner().all_transactions().len()); +} + diff --git a/ethcore/src/types/transaction.rs b/ethcore/src/types/transaction.rs index 25e91afe5..2cd001bdb 100644 --- a/ethcore/src/types/transaction.rs +++ b/ethcore/src/types/transaction.rs @@ -395,7 +395,7 @@ impl Deref for LocalizedTransaction { pub struct PendingTransaction { /// Signed transaction data. pub transaction: SignedTransaction, - /// Gas price. + /// To be activated at this block. `None` for immediately. pub min_block: Option, } From 65f07e5aa73b9c5635dc7c14771e003231f60cba Mon Sep 17 00:00:00 2001 From: arkpar Date: Fri, 16 Dec 2016 14:54:26 +0100 Subject: [PATCH 7/7] Renamed some functions --- ethcore/light/src/client.rs | 2 +- ethcore/light/src/net/tests/mod.rs | 4 ++-- ethcore/light/src/provider.rs | 6 +++--- ethcore/src/client/client.rs | 4 ++-- ethcore/src/client/test_client.rs | 4 ++-- ethcore/src/client/traits.rs | 4 ++-- ethcore/src/miner/miner.rs | 16 ++++++++-------- ethcore/src/miner/mod.rs | 8 ++++---- ethcore/src/tests/client.rs | 10 +++++----- rpc/src/v1/impls/parity.rs | 2 +- rpc/src/v1/tests/helpers/miner_service.rs | 4 ++-- sync/src/chain.rs | 2 +- 12 files changed, 33 insertions(+), 33 deletions(-) diff --git a/ethcore/light/src/client.rs b/ethcore/light/src/client.rs index 80100f17c..edadc440c 100644 --- a/ethcore/light/src/client.rs +++ b/ethcore/light/src/client.rs @@ -114,7 +114,7 @@ impl Provider for Client { Vec::new() } - fn pending_transactions(&self) -> Vec { + fn ready_transactions(&self) -> Vec { Vec::new() } } diff --git a/ethcore/light/src/net/tests/mod.rs b/ethcore/light/src/net/tests/mod.rs index f9551fc9a..64d53d9c8 100644 --- a/ethcore/light/src/net/tests/mod.rs +++ b/ethcore/light/src/net/tests/mod.rs @@ -169,8 +169,8 @@ impl Provider for TestProvider { req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect() } - fn pending_transactions(&self) -> Vec { - self.0.client.pending_transactions() + fn ready_transactions(&self) -> Vec { + self.0.client.ready_transactions() } } diff --git a/ethcore/light/src/provider.rs b/ethcore/light/src/provider.rs index ce80929c2..1f9bbf8aa 100644 --- a/ethcore/light/src/provider.rs +++ b/ethcore/light/src/provider.rs @@ -79,7 +79,7 @@ pub trait Provider: Send + Sync { fn header_proofs(&self, req: request::HeaderProofs) -> Vec; /// Provide pending transactions. - fn pending_transactions(&self) -> Vec; + fn ready_transactions(&self) -> Vec; } // Implementation of a light client data provider for a client. @@ -178,7 +178,7 @@ impl Provider for T { req.requests.into_iter().map(|_| ::rlp::EMPTY_LIST_RLP.to_vec()).collect() } - fn pending_transactions(&self) -> Vec { - BlockChainClient::pending_transactions(self) + fn ready_transactions(&self) -> Vec { + BlockChainClient::ready_transactions(self) } } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 4e54f22b1..25f000c89 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1334,8 +1334,8 @@ impl BlockChainClient for Client { } } - fn pending_transactions(&self) -> Vec { - self.miner.pending_transactions(self.chain.read().best_block_number()) + fn ready_transactions(&self) -> Vec { + self.miner.ready_transactions(self.chain.read().best_block_number()) } fn queue_consensus_message(&self, message: Bytes) { diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index a3344dab7..a384f1227 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -688,8 +688,8 @@ impl BlockChainClient for TestBlockChainClient { fn broadcast_consensus_message(&self, _message: Bytes) {} - fn pending_transactions(&self) -> Vec { - self.miner.pending_transactions(self.chain_info().best_block_number) + fn ready_transactions(&self) -> Vec { + self.miner.ready_transactions(self.chain_info().best_block_number) } fn signing_network_id(&self) -> Option { None } diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 4c3b2a37e..caba647d1 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -211,8 +211,8 @@ pub trait BlockChainClient : Sync + Send { /// Used by PoA to communicate with peers. fn broadcast_consensus_message(&self, message: Bytes); - /// list all transactions - fn pending_transactions(&self) -> Vec; + /// List all transactions that are allowed into the next block. + fn ready_transactions(&self) -> Vec; /// Sorted list of transaction gas prices from at least last sample_size blocks. fn gas_price_corpus(&self, sample_size: usize) -> Vec { diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 3002a1ffc..c7bff4784 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -909,7 +909,7 @@ impl MinerService for Miner { imported } - fn all_transactions(&self) -> Vec { + fn pending_transactions(&self) -> Vec { let queue = self.transaction_queue.lock(); queue.pending_transactions(BlockNumber::max_value()) } @@ -926,7 +926,7 @@ impl MinerService for Miner { self.transaction_queue.lock().future_transactions() } - fn pending_transactions(&self, best_block: BlockNumber) -> Vec { + fn ready_transactions(&self, best_block: BlockNumber) -> Vec { let queue = self.transaction_queue.lock(); match self.options.pending_set { PendingSet::AlwaysQueue => queue.pending_transactions(best_block), @@ -1253,8 +1253,8 @@ mod tests { // then assert_eq!(res.unwrap(), TransactionImportResult::Current); - assert_eq!(miner.all_transactions().len(), 1); - assert_eq!(miner.pending_transactions(best_block).len(), 1); + assert_eq!(miner.pending_transactions().len(), 1); + assert_eq!(miner.ready_transactions(best_block).len(), 1); assert_eq!(miner.pending_transactions_hashes(best_block).len(), 1); assert_eq!(miner.pending_receipts(best_block).len(), 1); // This method will let us know if pending block was created (before calling that method) @@ -1273,8 +1273,8 @@ mod tests { // then assert_eq!(res.unwrap(), TransactionImportResult::Current); - assert_eq!(miner.all_transactions().len(), 1); - assert_eq!(miner.pending_transactions(best_block).len(), 0); + assert_eq!(miner.pending_transactions().len(), 1); + assert_eq!(miner.ready_transactions(best_block).len(), 0); assert_eq!(miner.pending_transactions_hashes(best_block).len(), 0); assert_eq!(miner.pending_receipts(best_block).len(), 0); } @@ -1291,9 +1291,9 @@ mod tests { // then assert_eq!(res.unwrap(), TransactionImportResult::Current); - assert_eq!(miner.all_transactions().len(), 1); + assert_eq!(miner.pending_transactions().len(), 1); assert_eq!(miner.pending_transactions_hashes(best_block).len(), 0); - assert_eq!(miner.pending_transactions(best_block).len(), 0); + assert_eq!(miner.ready_transactions(best_block).len(), 0); assert_eq!(miner.pending_receipts(best_block).len(), 0); // This method will let us know if pending block was created (before calling that method) assert!(miner.prepare_work_sealing(&client)); diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index fa8e7df0a..563e068a6 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -144,11 +144,11 @@ pub trait MinerService : Send + Sync { /// Query pending transactions for hash. fn transaction(&self, best_block: BlockNumber, hash: &H256) -> Option; - /// Get a list of all ready transactions in the queue. - fn all_transactions(&self) -> Vec; + /// Get a list of all pending transactions in the queue. + fn pending_transactions(&self) -> Vec; - /// Get a list of all pending transactions. - fn pending_transactions(&self, best_block: BlockNumber) -> Vec; + /// Get a list of all transactions that can go into the given block. + fn ready_transactions(&self, best_block: BlockNumber) -> Vec; /// Get a list of all future transactions. fn future_transactions(&self) -> Vec; diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 2e9087133..b56feef05 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -313,11 +313,11 @@ fn does_not_propagate_delayed_transactions() { client.miner().import_own_transaction(&**client, tx0).unwrap(); client.miner().import_own_transaction(&**client, tx1).unwrap(); - assert_eq!(0, client.pending_transactions().len()); - assert_eq!(2, client.miner().all_transactions().len()); - push_blocks_to_client(client, 53, 2, 1); + assert_eq!(0, client.ready_transactions().len()); + assert_eq!(2, client.miner().pending_transactions().len()); + push_blocks_to_client(client, 53, 2, 2); client.import_verified_blocks(); - assert_eq!(2, client.pending_transactions().len()); - assert_eq!(2, client.miner().all_transactions().len()); + assert_eq!(2, client.ready_transactions().len()); + assert_eq!(2, client.miner().pending_transactions().len()); } diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 0cfc1ba4d..326dc9c2b 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -270,7 +270,7 @@ impl Parity for ParityClient where fn pending_transactions(&self) -> Result, Error> { try!(self.active()); - Ok(take_weak!(self.miner).all_transactions().into_iter().map(Into::into).collect::>()) + Ok(take_weak!(self.miner).pending_transactions().into_iter().map(Into::into).collect::>()) } fn future_transactions(&self) -> Result, Error> { diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 0ef0ee0a9..b25bcc39c 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -204,7 +204,7 @@ impl MinerService for TestMinerService { self.pending_transactions.lock().get(hash).cloned() } - fn all_transactions(&self) -> Vec { + fn pending_transactions(&self) -> Vec { self.pending_transactions.lock().values().cloned().map(Into::into).collect() } @@ -212,7 +212,7 @@ impl MinerService for TestMinerService { self.local_transactions.lock().iter().map(|(hash, stats)| (*hash, stats.clone())).collect() } - fn pending_transactions(&self, _best_block: BlockNumber) -> Vec { + fn ready_transactions(&self, _best_block: BlockNumber) -> Vec { self.pending_transactions.lock().values().cloned().map(Into::into).collect() } diff --git a/sync/src/chain.rs b/sync/src/chain.rs index 375cf6595..968107ba5 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -1919,7 +1919,7 @@ impl ChainSync { return 0; } - let transactions = io.chain().pending_transactions(); + let transactions = io.chain().ready_transactions(); if transactions.is_empty() { return 0; }