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:
committed by
Marek Kotewicz
parent
03b96a7c0a
commit
1cd93e4ceb
@@ -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> {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}"#;
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user