New Transaction Queue implementation (#8074)

* Implementation of Verifier, Scoring and Ready.

* Queue in progress.

* TransactionPool.

* Prepare for txpool release.

* Miner refactor [WiP]

* WiP reworking miner.

* Make it compile.

* Add some docs.

* Split blockchain access to a separate file.

* Work on miner API.

* Fix ethcore tests.

* Refactor miner interface for sealing/work packages.

* Implement next nonce.

* RPC compiles.

* Implement couple of missing methdods for RPC.

* Add transaction queue listeners.

* Compiles!

* Clean-up and parallelize.

* Get rid of RefCell in header.

* Revert "Get rid of RefCell in header."

This reverts commit 0f2424c9b7319a786e1565ea2a8a6d801a21b4fb.

* Override Sync requirement.

* Fix status display.

* Unify logging.

* Extract some cheap checks.

* Measurements and optimizations.

* Fix scoring bug, heap size of bug and add cache

* Disable tx queueing and parallel verification.

* Make ethcore and ethcore-miner compile again.

* Make RPC compile again.

* Bunch of txpool tests.

* Migrate transaction queue tests.

* Nonce Cap

* Nonce cap cache and tests.

* Remove stale future transactions from the queue.

* Optimize scoring and write some tests.

* Simple penalization.

* Clean up and support for different scoring algorithms.

* Add CLI parameters for the new queue.

* Remove banning queue.

* Disable debug build.

* Change per_sender limit to be 1% instead of 5%

* Avoid cloning when propagating transactions.

* Remove old todo.

* Post-review fixes.

* Fix miner options default.

* Implement back ready transactions for light client.

* Get rid of from_pending_block

* Pass rejection reason.

* Add more details to drop.

* Rollback heap size of.

* Avoid cloning hashes when propagating and include more details on rejection.

* Fix tests.

* Introduce nonces cache.

* Remove uneccessary hashes allocation.

* Lower the mem limit.

* Re-enable parallel verification.

* Add miner log. Don't check the type if not below min_gas_price.

* Add more traces, fix disabling miner.

* Fix creating pending blocks twice on AuRa authorities.

* Fix tests.

* re-use pending blocks in AuRa

* Use reseal_min_period to prevent too frequent update_sealing.

* Fix log to contain hash not sender.

* Optimize local transactions.

* Fix aura tests.

* Update locks comments.

* Get rid of unsafe Sync impl.

* Review fixes.

* Remove excessive matches.

* Fix compilation errors.

* Use new pool in private transactions.

* Fix private-tx test.

* Fix secret store tests.

* Actually use gas_floor_target

* Fix config tests.

* Fix pool tests.

* Address grumbles.
This commit is contained in:
Tomasz Drwięga
2018-04-13 17:34:27 +02:00
committed by Marek Kotewicz
parent 03b96a7c0a
commit 1cd93e4ceb
105 changed files with 5185 additions and 5784 deletions

View File

@@ -17,15 +17,14 @@
//! rpc integration tests.
use std::env;
use std::sync::Arc;
use std::time::Duration;
use ethereum_types::{U256, H256, Address};
use ethereum_types::{H256, Address};
use ethcore::account_provider::AccountProvider;
use ethcore::block::Block;
use ethcore::client::{BlockChainClient, Client, ClientConfig, ChainInfo, ImportBlock};
use ethcore::ethereum;
use ethcore::ids::BlockId;
use ethcore::miner::{MinerOptions, Banning, GasPricer, Miner, PendingSet, GasLimit};
use ethcore::miner::Miner;
use ethcore::spec::{Genesis, Spec};
use ethcore::views::BlockView;
use ethjson::blockchain::BlockChain;
@@ -33,7 +32,6 @@ use ethjson::state::test::ForkSpec;
use io::IoChannel;
use kvdb_memorydb;
use miner::external::ExternalMiner;
use miner::transaction_queue::PrioritizationStrategy;
use parking_lot::Mutex;
use jsonrpc_core::IoHandler;
@@ -58,30 +56,7 @@ fn sync_provider() -> Arc<TestSyncProvider> {
}
fn miner_service(spec: &Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
Miner::new(
MinerOptions {
force_sealing: true,
reseal_on_external_tx: true,
reseal_on_own_tx: true,
reseal_on_uncle: false,
tx_queue_size: 1024,
tx_gas_limit: !U256::zero(),
tx_queue_strategy: PrioritizationStrategy::GasPriceOnly,
tx_queue_gas_limit: GasLimit::None,
tx_queue_banning: Banning::Disabled,
tx_queue_memory_limit: None,
pending_set: PendingSet::SealingOrElseQueue,
reseal_min_period: Duration::from_secs(0),
reseal_max_period: Duration::from_secs(120),
work_queue_size: 50,
enable_resubmission: true,
refuse_service_transactions: false,
infinite_pending_block: false,
},
GasPricer::new_fixed(20_000_000_000u64.into()),
&spec,
Some(accounts),
)
Arc::new(Miner::new_for_tests(spec, Some(accounts)))
}
fn snapshot_service() -> Arc<TestSnapshotService> {

View File

@@ -16,82 +16,68 @@
//! Test implementation of miner service.
use std::sync::Arc;
use std::collections::{BTreeMap, HashMap};
use std::collections::hash_map::Entry;
use bytes::Bytes;
use ethcore::account_provider::SignError as AccountError;
use ethcore::block::{Block, ClosedBlock};
use ethcore::block::{Block, SealedBlock, IsBlock};
use ethcore::client::{Nonce, PrepareOpenBlock, StateClient, EngineInfo};
use ethcore::engines::EthEngine;
use ethcore::error::Error;
use ethcore::header::{BlockNumber, Header};
use ethcore::ids::BlockId;
use ethcore::miner::{MinerService, MinerStatus};
use ethcore::miner::{MinerService, AuthoringParams};
use ethcore::receipt::{Receipt, RichReceipt};
use ethereum_types::{H256, U256, Address};
use miner::local_transactions::Status as LocalTransactionStatus;
use miner::pool::local_transactions::Status as LocalTransactionStatus;
use miner::pool::{verifier, VerifiedTransaction, QueueStatus};
use parking_lot::{RwLock, Mutex};
use transaction::{UnverifiedTransaction, SignedTransaction, PendingTransaction, ImportResult as TransactionImportResult};
use transaction::{self, UnverifiedTransaction, SignedTransaction, PendingTransaction};
use txpool;
/// Test miner service.
pub struct TestMinerService {
/// Imported transactions.
pub imported_transactions: Mutex<Vec<SignedTransaction>>,
/// Latest closed block.
pub latest_closed_block: Mutex<Option<ClosedBlock>>,
/// Pre-existed pending transactions
pub pending_transactions: Mutex<HashMap<H256, SignedTransaction>>,
/// Pre-existed local transactions
pub local_transactions: Mutex<BTreeMap<H256, LocalTransactionStatus>>,
/// Pre-existed pending receipts
pub pending_receipts: Mutex<BTreeMap<H256, Receipt>>,
/// Last nonces.
pub last_nonces: RwLock<HashMap<Address, U256>>,
/// Next nonces.
pub next_nonces: RwLock<HashMap<Address, U256>>,
/// Password held by Engine.
pub password: RwLock<String>,
min_gas_price: RwLock<U256>,
gas_range_target: RwLock<(U256, U256)>,
author: RwLock<Address>,
extra_data: RwLock<Bytes>,
limit: RwLock<usize>,
tx_gas_limit: RwLock<U256>,
authoring_params: RwLock<AuthoringParams>,
}
impl Default for TestMinerService {
fn default() -> TestMinerService {
TestMinerService {
imported_transactions: Mutex::new(Vec::new()),
latest_closed_block: Mutex::new(None),
pending_transactions: Mutex::new(HashMap::new()),
local_transactions: Mutex::new(BTreeMap::new()),
pending_receipts: Mutex::new(BTreeMap::new()),
last_nonces: RwLock::new(HashMap::new()),
min_gas_price: RwLock::new(U256::from(20_000_000)),
gas_range_target: RwLock::new((U256::from(12345), U256::from(54321))),
author: RwLock::new(Address::zero()),
next_nonces: RwLock::new(HashMap::new()),
password: RwLock::new(String::new()),
extra_data: RwLock::new(vec![1, 2, 3, 4]),
limit: RwLock::new(1024),
tx_gas_limit: RwLock::new(!U256::zero()),
authoring_params: RwLock::new(AuthoringParams {
author: Address::zero(),
gas_range_target: (12345.into(), 54321.into()),
extra_data: vec![1, 2, 3, 4],
}),
}
}
}
impl TestMinerService {
/// Increments last nonce for given address.
pub fn increment_last_nonce(&self, address: Address) {
let mut last_nonces = self.last_nonces.write();
match last_nonces.entry(address) {
Entry::Occupied(mut occupied) => {
let val = *occupied.get();
*occupied.get_mut() = val + 1.into();
},
Entry::Vacant(vacant) => {
vacant.insert(0.into());
},
}
/// Increments nonce for given address.
pub fn increment_nonce(&self, address: &Address) {
let mut next_nonces = self.next_nonces.write();
let nonce = next_nonces.entry(*address).or_insert_with(|| 0.into());
*nonce = *nonce + 1.into();
}
}
@@ -129,164 +115,112 @@ impl MinerService for TestMinerService {
None
}
/// Returns miner's status.
fn status(&self) -> MinerStatus {
MinerStatus {
transactions_in_pending_queue: 0,
transactions_in_future_queue: 0,
transactions_in_pending_block: 1
fn authoring_params(&self) -> AuthoringParams {
self.authoring_params.read().clone()
}
fn set_author(&self, author: Address, password: Option<String>) -> Result<(), AccountError> {
self.authoring_params.write().author = author;
if let Some(password) = password {
*self.password.write() = password;
}
}
fn set_author(&self, author: Address) {
*self.author.write() = author;
}
fn set_engine_signer(&self, address: Address, password: String) -> Result<(), AccountError> {
*self.author.write() = address;
*self.password.write() = password;
Ok(())
}
fn set_extra_data(&self, extra_data: Bytes) {
*self.extra_data.write() = extra_data;
self.authoring_params.write().extra_data = extra_data;
}
/// Set the lower gas limit we wish to target when sealing a new block.
fn set_gas_floor_target(&self, target: U256) {
self.gas_range_target.write().0 = target;
}
/// Set the upper gas limit we wish to target when sealing a new block.
fn set_gas_ceil_target(&self, target: U256) {
self.gas_range_target.write().1 = target;
}
fn set_minimal_gas_price(&self, min_gas_price: U256) {
*self.min_gas_price.write() = min_gas_price;
}
fn set_transactions_limit(&self, limit: usize) {
*self.limit.write() = limit;
}
fn set_tx_gas_limit(&self, limit: U256) {
*self.tx_gas_limit.write() = limit;
}
fn transactions_limit(&self) -> usize {
*self.limit.read()
}
fn author(&self) -> Address {
*self.author.read()
}
fn minimal_gas_price(&self) -> U256 {
*self.min_gas_price.read()
}
fn extra_data(&self) -> Bytes {
self.extra_data.read().clone()
}
fn gas_floor_target(&self) -> U256 {
self.gas_range_target.read().0
}
fn gas_ceil_target(&self) -> U256 {
self.gas_range_target.read().1
fn set_gas_range_target(&self, target: (U256, U256)) {
self.authoring_params.write().gas_range_target = target;
}
/// Imports transactions to transaction queue.
fn import_external_transactions<C>(&self, _chain: &C, transactions: Vec<UnverifiedTransaction>) ->
Vec<Result<TransactionImportResult, Error>> {
fn import_external_transactions<C: Nonce + Sync>(&self, chain: &C, transactions: Vec<UnverifiedTransaction>)
-> Vec<Result<(), transaction::Error>>
{
// lets assume that all txs are valid
let transactions: Vec<_> = transactions.into_iter().map(|tx| SignedTransaction::new(tx).unwrap()).collect();
self.imported_transactions.lock().extend_from_slice(&transactions);
for sender in transactions.iter().map(|tx| tx.sender()) {
let nonce = self.last_nonce(&sender).expect("last_nonce must be populated in tests");
self.last_nonces.write().insert(sender, nonce + U256::from(1));
let nonce = self.next_nonce(chain, &sender);
self.next_nonces.write().insert(sender, nonce);
}
transactions
.iter()
.map(|_| Ok(TransactionImportResult::Current))
.map(|_| Ok(()))
.collect()
}
/// Imports transactions to transaction queue.
fn import_own_transaction<C: Nonce>(&self, chain: &C, pending: PendingTransaction) ->
Result<TransactionImportResult, Error> {
fn import_own_transaction<C: Nonce + Sync>(&self, chain: &C, pending: PendingTransaction)
-> Result<(), transaction::Error> {
// keep the pending nonces up to date
let sender = pending.transaction.sender();
let nonce = self.last_nonce(&sender).unwrap_or(chain.latest_nonce(&sender));
self.last_nonces.write().insert(sender, nonce + U256::from(1));
let nonce = self.next_nonce(chain, &sender);
self.next_nonces.write().insert(sender, nonce);
// lets assume that all txs are valid
self.imported_transactions.lock().push(pending.transaction);
Ok(TransactionImportResult::Current)
}
/// Returns hashes of transactions currently in pending
fn pending_transactions_hashes(&self, _best_block: BlockNumber) -> Vec<H256> {
vec![]
}
/// Removes all transactions from the queue and restart mining operation.
fn clear_and_reset<C>(&self, _chain: &C) {
unimplemented!();
Ok(())
}
/// Called when blocks are imported to chain, updates transactions queue.
fn chain_new_blocks<C>(&self, _chain: &C, _imported: &[H256], _invalid: &[H256], _enacted: &[H256], _retracted: &[H256]) {
fn chain_new_blocks<C>(&self, _chain: &C, _imported: &[H256], _invalid: &[H256], _enacted: &[H256], _retracted: &[H256], _is_internal: bool) {
unimplemented!();
}
/// PoW chain - can produce work package
fn can_produce_work_package(&self) -> bool {
true
}
/// New chain head event. Restart mining operation.
fn update_sealing<C>(&self, _chain: &C) {
unimplemented!();
}
fn map_sealing_work<C: PrepareOpenBlock, F, T>(&self, chain: &C, f: F) -> Option<T> where F: FnOnce(&ClosedBlock) -> T {
let open_block = chain.prepare_open_block(self.author(), *self.gas_range_target.write(), self.extra_data());
Some(f(&open_block.close()))
fn work_package<C: PrepareOpenBlock>(&self, chain: &C) -> Option<(H256, BlockNumber, u64, U256)> {
let params = self.authoring_params();
let open_block = chain.prepare_open_block(params.author, params.gas_range_target, params.extra_data);
let closed = open_block.close();
let header = closed.header();
Some((header.hash(), header.number(), header.timestamp(), *header.difficulty()))
}
fn transaction(&self, _best_block: BlockNumber, hash: &H256) -> Option<PendingTransaction> {
self.pending_transactions.lock().get(hash).cloned().map(Into::into)
fn transaction(&self, hash: &H256) -> Option<Arc<VerifiedTransaction>> {
self.pending_transactions.lock().get(hash).cloned().map(|tx| {
Arc::new(VerifiedTransaction::from_pending_block_transaction(tx))
})
}
fn remove_pending_transaction<C>(&self, _chain: &C, hash: &H256) -> Option<PendingTransaction> {
self.pending_transactions.lock().remove(hash).map(Into::into)
fn remove_transaction(&self, hash: &H256) -> Option<Arc<VerifiedTransaction>> {
self.pending_transactions.lock().remove(hash).map(|tx| {
Arc::new(VerifiedTransaction::from_pending_block_transaction(tx))
})
}
fn pending_transactions(&self) -> Vec<PendingTransaction> {
self.pending_transactions.lock().values().cloned().map(Into::into).collect()
fn pending_transactions(&self, _best_block: BlockNumber) -> Option<Vec<SignedTransaction>> {
Some(self.pending_transactions.lock().values().cloned().collect())
}
fn local_transactions(&self) -> BTreeMap<H256, LocalTransactionStatus> {
self.local_transactions.lock().iter().map(|(hash, stats)| (*hash, stats.clone())).collect()
}
fn ready_transactions(&self, _best_block: BlockNumber, _best_timestamp: u64) -> Vec<PendingTransaction> {
self.pending_transactions.lock().values().cloned().map(Into::into).collect()
fn ready_transactions<C>(&self, _chain: &C) -> Vec<Arc<VerifiedTransaction>> {
self.queued_transactions()
}
fn future_transactions(&self) -> Vec<PendingTransaction> {
vec![]
fn queued_transactions(&self) -> Vec<Arc<VerifiedTransaction>> {
self.pending_transactions.lock().values().cloned().map(|tx| {
Arc::new(VerifiedTransaction::from_pending_block_transaction(tx))
}).collect()
}
fn pending_receipt(&self, _best_block: BlockNumber, hash: &H256) -> Option<RichReceipt> {
// Not much point implementing this since the logic is complex and the only thing it relies on is pending_receipts, which is already tested.
self.pending_receipts(0).get(hash).map(|r|
self.pending_receipts(0).unwrap().get(hash).map(|r|
RichReceipt {
transaction_hash: Default::default(),
transaction_index: Default::default(),
@@ -300,25 +234,49 @@ impl MinerService for TestMinerService {
)
}
fn pending_receipts(&self, _best_block: BlockNumber) -> BTreeMap<H256, Receipt> {
self.pending_receipts.lock().clone()
fn pending_receipts(&self, _best_block: BlockNumber) -> Option<BTreeMap<H256, Receipt>> {
Some(self.pending_receipts.lock().clone())
}
fn last_nonce(&self, address: &Address) -> Option<U256> {
self.last_nonces.read().get(address).cloned()
fn next_nonce<C: Nonce + Sync>(&self, _chain: &C, address: &Address) -> U256 {
self.next_nonces.read().get(address).cloned().unwrap_or_default()
}
fn is_currently_sealing(&self) -> bool {
false
}
fn queue_status(&self) -> QueueStatus {
QueueStatus {
options: verifier::Options {
minimal_gas_price: 0x1312d00.into(),
block_gas_limit: 5_000_000.into(),
tx_gas_limit: 5_000_000.into(),
},
status: txpool::LightStatus {
mem_usage: 1_000,
transaction_count: 52,
senders: 1,
},
limits: txpool::Options {
max_count: 1_024,
max_per_sender: 16,
max_mem_usage: 5_000,
},
}
}
/// Submit `seal` as a valid solution for the header of `pow_hash`.
/// Will check the seal, but not actually insert the block into the chain.
fn submit_seal<C>(&self, _chain: &C, _pow_hash: H256, _seal: Vec<Bytes>) -> Result<(), Error> {
fn submit_seal(&self, _pow_hash: H256, _seal: Vec<Bytes>) -> Result<SealedBlock, Error> {
unimplemented!();
}
fn sensible_gas_price(&self) -> U256 {
20000000000u64.into()
20_000_000_000u64.into()
}
fn sensible_gas_limit(&self) -> U256 {
0x5208.into()
}
}

View File

@@ -368,7 +368,7 @@ fn rpc_eth_author() {
for i in 0..20 {
let addr = tester.accounts_provider.new_account(&format!("{}", i)).unwrap();
tester.miner.set_author(addr.clone());
tester.miner.set_author(addr.clone(), None).unwrap();
assert_eq!(tester.io.handle_request_sync(req), Some(make_res(addr)));
}
@@ -377,7 +377,7 @@ fn rpc_eth_author() {
#[test]
fn rpc_eth_mining() {
let tester = EthTester::default();
tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap());
tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(), None).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "eth_mining", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":false,"id":1}"#;
@@ -498,7 +498,7 @@ fn rpc_eth_transaction_count_next_nonce() {
let tester = EthTester::new_with_options(EthClientOptions::with(|options| {
options.pending_nonce_from_queue = true;
}));
tester.miner.increment_last_nonce(1.into());
tester.miner.increment_nonce(&1.into());
let request1 = r#"{
"jsonrpc": "2.0",
@@ -553,7 +553,7 @@ fn rpc_eth_transaction_count_by_number_pending() {
"params": ["pending"],
"id": 1
}"#;
let response = r#"{"jsonrpc":"2.0","result":"0x1","id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":"0x0","id":1}"#;
assert_eq!(EthTester::default().io.handle_request_sync(request), Some(response.to_owned()));
}
@@ -835,7 +835,7 @@ fn rpc_eth_send_transaction() {
assert_eq!(tester.io.handle_request_sync(&request), Some(response));
tester.miner.last_nonces.write().insert(address.clone(), U256::zero());
tester.miner.increment_nonce(&address);
let t = Transaction {
nonce: U256::one(),
@@ -905,7 +905,7 @@ fn rpc_eth_sign_transaction() {
r#""value":"0x9184e72a""# +
r#"}},"id":1}"#;
tester.miner.last_nonces.write().insert(address.clone(), U256::zero());
tester.miner.increment_nonce(&address);
assert_eq!(tester.io.handle_request_sync(&request), Some(response));
}
@@ -1118,7 +1118,7 @@ fn rpc_get_work_returns_no_work_if_cant_mine() {
#[test]
fn rpc_get_work_returns_correct_work_package() {
let eth_tester = EthTester::default();
eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap());
eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(), None).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":["0x76c7bd86693aee93d1a80a408a09a0585b1a1292afcb56192f171d925ea18e2d","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000800000000000000000000000000000000000000000000000000000000000","0x1"],"id":1}"#;
@@ -1131,7 +1131,7 @@ fn rpc_get_work_should_not_return_block_number() {
let eth_tester = EthTester::new_with_options(EthClientOptions::with(|options| {
options.send_block_number_in_get_work = false;
}));
eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap());
eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(), None).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":["0x76c7bd86693aee93d1a80a408a09a0585b1a1292afcb56192f171d925ea18e2d","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000800000000000000000000000000000000000000000000000000000000000"],"id":1}"#;
@@ -1142,10 +1142,10 @@ fn rpc_get_work_should_not_return_block_number() {
#[test]
fn rpc_get_work_should_timeout() {
let eth_tester = EthTester::default();
eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap());
eth_tester.miner.set_author(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(), None).unwrap();
let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() - 1000; // Set latest block to 1000 seconds ago
eth_tester.client.set_latest_block_timestamp(timestamp);
let hash = eth_tester.miner.map_sealing_work(&*eth_tester.client, |b| b.hash()).unwrap();
let hash = eth_tester.miner.work_package(&*eth_tester.client).unwrap().0;
// Request without providing timeout. This should work since we're disabling timeout.
let request = r#"{"jsonrpc": "2.0", "method": "eth_getWork", "params": [], "id": 1}"#;

View File

@@ -17,13 +17,13 @@
use std::sync::Arc;
use ethcore::account_provider::AccountProvider;
use ethcore::client::{TestBlockChainClient, Executed};
use ethcore::miner::LocalTransactionStatus;
use ethcore_logger::RotatingLogger;
use ethereum_types::{Address, U256, H256};
use ethstore::ethkey::{Generator, Random};
use sync::ManageNetwork;
use miner::pool::local_transactions::Status as LocalTransactionStatus;
use node_health::{self, NodeHealth};
use parity_reactor;
use ethereum_types::{Address, U256, H256};
use sync::ManageNetwork;
use jsonrpc_core::IoHandler;
use v1::{Parity, ParityClient};
@@ -455,7 +455,9 @@ fn rpc_parity_next_nonce() {
let address = Address::default();
let io1 = deps.default_client();
let deps = Dependencies::new();
deps.miner.last_nonces.write().insert(address.clone(), 2.into());
deps.miner.increment_nonce(&address);
deps.miner.increment_nonce(&address);
deps.miner.increment_nonce(&address);
let io2 = deps.default_client();
let request = r#"{
@@ -486,11 +488,20 @@ fn rpc_parity_transactions_stats() {
fn rpc_parity_local_transactions() {
let deps = Dependencies::new();
let io = deps.default_client();
deps.miner.local_transactions.lock().insert(10.into(), LocalTransactionStatus::Pending);
deps.miner.local_transactions.lock().insert(15.into(), LocalTransactionStatus::Future);
let tx = ::transaction::Transaction {
value: 5.into(),
gas: 3.into(),
gas_price: 2.into(),
action: ::transaction::Action::Create,
data: vec![1, 2, 3],
nonce: 0.into(),
}.fake_sign(3.into());
let tx = Arc::new(::miner::pool::VerifiedTransaction::from_pending_block_transaction(tx));
deps.miner.local_transactions.lock().insert(10.into(), LocalTransactionStatus::Pending(tx.clone()));
deps.miner.local_transactions.lock().insert(15.into(), LocalTransactionStatus::Pending(tx.clone()));
let request = r#"{"jsonrpc": "2.0", "method": "parity_localTransactions", "params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":{"0x000000000000000000000000000000000000000000000000000000000000000a":{"status":"pending"},"0x000000000000000000000000000000000000000000000000000000000000000f":{"status":"future"}},"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":{"0x000000000000000000000000000000000000000000000000000000000000000a":{"status":"pending"},"0x000000000000000000000000000000000000000000000000000000000000000f":{"status":"pending"}},"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
}

View File

@@ -109,10 +109,9 @@ fn rpc_parity_set_min_gas_price() {
io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate());
let request = r#"{"jsonrpc": "2.0", "method": "parity_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":false,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
assert_eq!(miner.minimal_gas_price(), U256::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap());
}
#[test]
@@ -129,7 +128,7 @@ fn rpc_parity_set_gas_floor_target() {
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
assert_eq!(miner.gas_floor_target(), U256::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap());
assert_eq!(miner.authoring_params().gas_range_target.0, U256::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap());
}
#[test]
@@ -146,7 +145,7 @@ fn rpc_parity_set_extra_data() {
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
assert_eq!(miner.extra_data(), "cd1722f3947def4cf144679da39c4c32bdc35681".from_hex().unwrap());
assert_eq!(miner.authoring_params().extra_data, "cd1722f3947def4cf144679da39c4c32bdc35681".from_hex().unwrap());
}
#[test]
@@ -162,7 +161,7 @@ fn rpc_parity_set_author() {
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
assert_eq!(miner.author(), Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap());
assert_eq!(miner.authoring_params().author, Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap());
}
#[test]
@@ -178,7 +177,7 @@ fn rpc_parity_set_engine_signer() {
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
assert_eq!(miner.author(), Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap());
assert_eq!(miner.authoring_params().author, Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap());
assert_eq!(*miner.password.read(), "password".to_string());
}
@@ -193,10 +192,9 @@ fn rpc_parity_set_transactions_limit() {
io.extend_with(parity_set_client(&client, &miner, &updater, &network).to_delegate());
let request = r#"{"jsonrpc": "2.0", "method": "parity_setTransactionsLimit", "params":[10240240], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
let response = r#"{"jsonrpc":"2.0","result":false,"id":1}"#;
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
assert_eq!(miner.transactions_limit(), 10_240_240);
}
#[test]

View File

@@ -220,7 +220,7 @@ fn sign_and_send_test(method: &str) {
assert_eq!(tester.io.handle_request_sync(request.as_ref()), Some(response));
tester.miner.last_nonces.write().insert(address.clone(), U256::zero());
tester.miner.increment_nonce(&address);
let t = Transaction {
nonce: U256::one(),

View File

@@ -327,7 +327,7 @@ fn should_add_sign_transaction_to_the_queue() {
r#"}},"id":1}"#;
// then
tester.miner.last_nonces.write().insert(address.clone(), U256::zero());
tester.miner.increment_nonce(&address);
let promise = tester.io.handle_request(&request);
// the future must be polled at least once before request is queued.