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
@@ -79,6 +79,8 @@ extern crate serde_derive;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate ethjson;
|
||||
#[cfg(test)]
|
||||
extern crate transaction_pool as txpool;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
|
||||
@@ -34,8 +34,8 @@ use stats::Corpus;
|
||||
use ethkey::Signature;
|
||||
use sync::LightSync;
|
||||
use ethcore::ids::BlockId;
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::client::MiningBlockChainClient;
|
||||
use ethcore::client::BlockChainClient;
|
||||
use ethcore::miner::{self, MinerService};
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use crypto::DEFAULT_MAC;
|
||||
use transaction::{Action, SignedTransaction, PendingTransaction, Transaction};
|
||||
@@ -117,10 +117,9 @@ impl<C, M> Clone for FullDispatcher<C, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: MiningBlockChainClient, M: MinerService> FullDispatcher<C, M> {
|
||||
impl<C: miner::BlockChainClient, M: MinerService> FullDispatcher<C, M> {
|
||||
fn state_nonce(&self, from: &Address) -> U256 {
|
||||
self.miner.last_nonce(from).map(|nonce| nonce + U256::one())
|
||||
.unwrap_or_else(|| self.client.latest_nonce(from))
|
||||
self.miner.next_nonce(&*self.client, from)
|
||||
}
|
||||
|
||||
/// Imports transaction to the miner's queue.
|
||||
@@ -133,7 +132,7 @@ impl<C: MiningBlockChainClient, M: MinerService> FullDispatcher<C, M> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: MiningBlockChainClient, M: MinerService> Dispatcher for FullDispatcher<C, M> {
|
||||
impl<C: miner::BlockChainClient + BlockChainClient, M: MinerService> Dispatcher for FullDispatcher<C, M> {
|
||||
fn fill_optional_fields(&self, request: TransactionRequest, default_sender: Address, force_nonce: bool)
|
||||
-> BoxFuture<FilledTransactionRequest>
|
||||
{
|
||||
@@ -747,7 +746,7 @@ fn decrypt(accounts: &AccountProvider, address: Address, msg: Bytes, password: S
|
||||
|
||||
/// Extract the default gas price from a client and miner.
|
||||
pub fn default_gas_price<C, M>(client: &C, miner: &M, percentile: usize) -> U256 where
|
||||
C: MiningBlockChainClient,
|
||||
C: BlockChainClient,
|
||||
M: MinerService,
|
||||
{
|
||||
client.gas_price_corpus(100).percentile(percentile).cloned().unwrap_or_else(|| miner.sensible_gas_price())
|
||||
|
||||
@@ -391,11 +391,11 @@ pub fn no_light_peers() -> Error {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deprecated<T: Into<Option<String>>>(message: T) -> Error {
|
||||
pub fn deprecated<S: Into<String>, T: Into<Option<S>>>(message: T) -> Error {
|
||||
Error {
|
||||
code: ErrorCode::ServerError(codes::DEPRECATED),
|
||||
message: "Method deprecated".into(),
|
||||
data: message.into().map(Value::String),
|
||||
data: message.into().map(Into::into).map(Value::String),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,13 +26,12 @@ use parking_lot::Mutex;
|
||||
|
||||
use ethash::SeedHashCompute;
|
||||
use ethcore::account_provider::{AccountProvider, DappId};
|
||||
use ethcore::block::IsBlock;
|
||||
use ethcore::client::{MiningBlockChainClient, BlockId, TransactionId, UncleId, StateOrBlock, StateClient, StateInfo, Call, EngineInfo};
|
||||
use ethcore::client::{BlockChainClient, BlockId, TransactionId, UncleId, StateOrBlock, StateClient, StateInfo, Call, EngineInfo};
|
||||
use ethcore::ethereum::Ethash;
|
||||
use ethcore::filter::Filter as EthcoreFilter;
|
||||
use ethcore::header::{BlockNumber as EthBlockNumber};
|
||||
use ethcore::log_entry::LogEntry;
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::miner::{self, MinerService};
|
||||
use ethcore::snapshot::SnapshotService;
|
||||
use ethcore::encoded;
|
||||
use sync::{SyncProvider};
|
||||
@@ -92,7 +91,7 @@ impl Default for EthClientOptions {
|
||||
|
||||
/// Eth rpc implementation.
|
||||
pub struct EthClient<C, SN: ?Sized, S: ?Sized, M, EM> where
|
||||
C: MiningBlockChainClient,
|
||||
C: miner::BlockChainClient + BlockChainClient,
|
||||
SN: SnapshotService,
|
||||
S: SyncProvider,
|
||||
M: MinerService,
|
||||
@@ -142,7 +141,7 @@ enum PendingTransactionId {
|
||||
}
|
||||
|
||||
impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> EthClient<C, SN, S, M, EM> where
|
||||
C: MiningBlockChainClient + StateClient<State=T> + Call<State=T> + EngineInfo,
|
||||
C: miner::BlockChainClient + BlockChainClient + StateClient<State=T> + Call<State=T> + EngineInfo,
|
||||
SN: SnapshotService,
|
||||
S: SyncProvider,
|
||||
M: MinerService<State=T>,
|
||||
@@ -420,7 +419,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> EthClient<C, SN, S
|
||||
}
|
||||
|
||||
pub fn pending_logs<M>(miner: &M, best_block: EthBlockNumber, filter: &EthcoreFilter) -> Vec<Log> where M: MinerService {
|
||||
let receipts = miner.pending_receipts(best_block);
|
||||
let receipts = miner.pending_receipts(best_block).unwrap_or_default();
|
||||
|
||||
let pending_logs = receipts.into_iter()
|
||||
.flat_map(|(hash, r)| r.logs.into_iter().map(|l| (hash.clone(), l)).collect::<Vec<(H256, LogEntry)>>())
|
||||
@@ -438,7 +437,7 @@ pub fn pending_logs<M>(miner: &M, best_block: EthBlockNumber, filter: &EthcoreFi
|
||||
result
|
||||
}
|
||||
|
||||
fn check_known<C>(client: &C, number: BlockNumber) -> Result<()> where C: MiningBlockChainClient {
|
||||
fn check_known<C>(client: &C, number: BlockNumber) -> Result<()> where C: BlockChainClient {
|
||||
use ethcore::block_status::BlockStatus;
|
||||
|
||||
let id = match number {
|
||||
@@ -458,7 +457,7 @@ fn check_known<C>(client: &C, number: BlockNumber) -> Result<()> where C: Mining
|
||||
const MAX_QUEUE_SIZE_TO_MINE_ON: usize = 4; // because uncles go back 6.
|
||||
|
||||
impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<C, SN, S, M, EM> where
|
||||
C: MiningBlockChainClient + StateClient<State=T> + Call<State=T> + EngineInfo + 'static,
|
||||
C: miner::BlockChainClient + BlockChainClient + StateClient<State=T> + Call<State=T> + EngineInfo + 'static,
|
||||
SN: SnapshotService + 'static,
|
||||
S: SyncProvider + 'static,
|
||||
M: MinerService<State=T> + 'static,
|
||||
@@ -506,7 +505,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
|
||||
fn author(&self, meta: Metadata) -> Result<RpcH160> {
|
||||
let dapp = meta.dapp_id();
|
||||
|
||||
let mut miner = self.miner.author();
|
||||
let mut miner = self.miner.authoring_params().author;
|
||||
if miner == 0.into() {
|
||||
miner = self.dapp_accounts(dapp.into())?.get(0).cloned().unwrap_or_default();
|
||||
}
|
||||
@@ -571,16 +570,8 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
|
||||
|
||||
let res = match num.unwrap_or_default() {
|
||||
BlockNumber::Pending if self.options.pending_nonce_from_queue => {
|
||||
let nonce = self.miner.last_nonce(&address)
|
||||
.map(|n| n + 1.into())
|
||||
.or_else(|| self.client.nonce(&address, BlockId::Latest));
|
||||
|
||||
match nonce {
|
||||
Some(nonce) => Ok(nonce.into()),
|
||||
None => Err(errors::database("latest nonce missing"))
|
||||
}
|
||||
},
|
||||
|
||||
Ok(self.miner.next_nonce(&*self.client, &address).into())
|
||||
}
|
||||
BlockNumber::Pending => {
|
||||
let info = self.client.chain_info();
|
||||
let nonce = self.miner
|
||||
@@ -596,7 +587,6 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
|
||||
None => Err(errors::database("latest nonce missing"))
|
||||
}
|
||||
},
|
||||
|
||||
number => {
|
||||
try_bf!(check_known(&*self.client, number.clone()));
|
||||
match self.client.nonce(&address, block_number_to_id(number)) {
|
||||
@@ -615,13 +605,13 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
|
||||
}
|
||||
|
||||
fn block_transaction_count_by_number(&self, num: BlockNumber) -> BoxFuture<Option<RpcU256>> {
|
||||
let block_number = self.client.chain_info().best_block_number;
|
||||
|
||||
Box::new(future::ok(match num {
|
||||
BlockNumber::Pending => Some(
|
||||
self.miner.status().transactions_in_pending_block.into()
|
||||
),
|
||||
BlockNumber::Pending =>
|
||||
self.miner.pending_transactions(block_number).map(|x| x.len().into()),
|
||||
_ =>
|
||||
self.client.block(block_number_to_id(num))
|
||||
.map(|block| block.transactions_count().into())
|
||||
self.client.block(block_number_to_id(num)).map(|block| block.transactions_count().into())
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -665,8 +655,8 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
|
||||
let hash: H256 = hash.into();
|
||||
let block_number = self.client.chain_info().best_block_number;
|
||||
let tx = try_bf!(self.transaction(PendingTransactionId::Hash(hash))).or_else(|| {
|
||||
self.miner.transaction(block_number, &hash)
|
||||
.map(|t| Transaction::from_pending(t, block_number, self.eip86_transition))
|
||||
self.miner.transaction(&hash)
|
||||
.map(|t| Transaction::from_pending(t.pending().clone(), block_number + 1, self.eip86_transition))
|
||||
});
|
||||
|
||||
Box::new(future::ok(tx))
|
||||
@@ -745,11 +735,6 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
|
||||
}
|
||||
|
||||
fn work(&self, no_new_work_timeout: Trailing<u64>) -> Result<Work> {
|
||||
if !self.miner.can_produce_work_package() {
|
||||
warn!(target: "miner", "Cannot give work package - engine seals internally.");
|
||||
return Err(errors::no_work_required())
|
||||
}
|
||||
|
||||
let no_new_work_timeout = no_new_work_timeout.unwrap_or_default();
|
||||
|
||||
// check if we're still syncing and return empty strings in that case
|
||||
@@ -768,50 +753,58 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
|
||||
}
|
||||
}
|
||||
|
||||
if self.miner.author().is_zero() {
|
||||
if self.miner.authoring_params().author.is_zero() {
|
||||
warn!(target: "miner", "Cannot give work package - no author is configured. Use --author to configure!");
|
||||
return Err(errors::no_author())
|
||||
}
|
||||
self.miner.map_sealing_work(&*self.client, |b| {
|
||||
let pow_hash = b.hash();
|
||||
let target = Ethash::difficulty_to_boundary(b.block().header().difficulty());
|
||||
let seed_hash = self.seed_compute.lock().hash_block_number(b.block().header().number());
|
||||
|
||||
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs();
|
||||
if no_new_work_timeout > 0 && b.block().header().timestamp() + no_new_work_timeout < now {
|
||||
Err(errors::no_new_work())
|
||||
} else if self.options.send_block_number_in_get_work {
|
||||
let block_number = b.block().header().number();
|
||||
Ok(Work {
|
||||
pow_hash: pow_hash.into(),
|
||||
seed_hash: seed_hash.into(),
|
||||
target: target.into(),
|
||||
number: Some(block_number),
|
||||
})
|
||||
} else {
|
||||
Ok(Work {
|
||||
pow_hash: pow_hash.into(),
|
||||
seed_hash: seed_hash.into(),
|
||||
target: target.into(),
|
||||
number: None
|
||||
})
|
||||
}
|
||||
}).unwrap_or(Err(errors::internal("No work found.", "")))
|
||||
let work = self.miner.work_package(&*self.client).ok_or_else(|| {
|
||||
warn!(target: "miner", "Cannot give work package - engine seals internally.");
|
||||
errors::no_work_required()
|
||||
})?;
|
||||
|
||||
let (pow_hash, number, timestamp, difficulty) = work;
|
||||
let target = Ethash::difficulty_to_boundary(&difficulty);
|
||||
let seed_hash = self.seed_compute.lock().hash_block_number(number);
|
||||
|
||||
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs();
|
||||
if no_new_work_timeout > 0 && timestamp + no_new_work_timeout < now {
|
||||
Err(errors::no_new_work())
|
||||
} else if self.options.send_block_number_in_get_work {
|
||||
Ok(Work {
|
||||
pow_hash: pow_hash.into(),
|
||||
seed_hash: seed_hash.into(),
|
||||
target: target.into(),
|
||||
number: Some(number),
|
||||
})
|
||||
} else {
|
||||
Ok(Work {
|
||||
pow_hash: pow_hash.into(),
|
||||
seed_hash: seed_hash.into(),
|
||||
target: target.into(),
|
||||
number: None
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn submit_work(&self, nonce: RpcH64, pow_hash: RpcH256, mix_hash: RpcH256) -> Result<bool> {
|
||||
if !self.miner.can_produce_work_package() {
|
||||
warn!(target: "miner", "Cannot submit work - engine seals internally.");
|
||||
return Err(errors::no_work_required())
|
||||
}
|
||||
|
||||
// TODO [ToDr] Should disallow submissions in case of PoA?
|
||||
let nonce: H64 = nonce.into();
|
||||
let pow_hash: H256 = pow_hash.into();
|
||||
let mix_hash: H256 = mix_hash.into();
|
||||
trace!(target: "miner", "submit_work: Decoded: nonce={}, pow_hash={}, mix_hash={}", nonce, pow_hash, mix_hash);
|
||||
|
||||
let seal = vec![rlp::encode(&mix_hash).into_vec(), rlp::encode(&nonce).into_vec()];
|
||||
Ok(self.miner.submit_seal(&*self.client, pow_hash, seal).is_ok())
|
||||
let import = self.miner.submit_seal(pow_hash, seal)
|
||||
.and_then(|block| self.client.import_sealed_block(block));
|
||||
|
||||
match import {
|
||||
Ok(_) => Ok(true),
|
||||
Err(err) => {
|
||||
warn!(target: "miner", "Cannot submit work - {:?}.", err);
|
||||
Ok(false)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn submit_hashrate(&self, rate: RpcU256, id: RpcH256) -> Result<bool> {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
use std::sync::Arc;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::miner::{self, MinerService};
|
||||
use ethcore::filter::Filter as EthcoreFilter;
|
||||
use ethcore::client::{BlockChainClient, BlockId};
|
||||
use ethereum_types::H256;
|
||||
@@ -42,7 +42,7 @@ pub trait Filterable {
|
||||
fn block_hash(&self, id: BlockId) -> Option<RpcH256>;
|
||||
|
||||
/// pending transaction hashes at the given block.
|
||||
fn pending_transactions_hashes(&self, block_number: u64) -> Vec<H256>;
|
||||
fn pending_transactions_hashes(&self) -> Vec<H256>;
|
||||
|
||||
/// Get logs that match the given filter.
|
||||
fn logs(&self, filter: EthcoreFilter) -> BoxFuture<Vec<Log>>;
|
||||
@@ -55,16 +55,13 @@ pub trait Filterable {
|
||||
}
|
||||
|
||||
/// Eth filter rpc implementation for a full node.
|
||||
pub struct EthFilterClient<C, M> where
|
||||
C: BlockChainClient,
|
||||
M: MinerService {
|
||||
|
||||
pub struct EthFilterClient<C, M> {
|
||||
client: Arc<C>,
|
||||
miner: Arc<M>,
|
||||
polls: Mutex<PollManager<PollFilter>>,
|
||||
}
|
||||
|
||||
impl<C, M> EthFilterClient<C, M> where C: BlockChainClient, M: MinerService {
|
||||
impl<C, M> EthFilterClient<C, M> {
|
||||
/// Creates new Eth filter client.
|
||||
pub fn new(client: Arc<C>, miner: Arc<M>) -> Self {
|
||||
EthFilterClient {
|
||||
@@ -75,7 +72,10 @@ impl<C, M> EthFilterClient<C, M> where C: BlockChainClient, M: MinerService {
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, M> Filterable for EthFilterClient<C, M> where C: BlockChainClient, M: MinerService {
|
||||
impl<C, M> Filterable for EthFilterClient<C, M> where
|
||||
C: miner::BlockChainClient + BlockChainClient,
|
||||
M: MinerService,
|
||||
{
|
||||
fn best_block_number(&self) -> u64 {
|
||||
self.client.chain_info().best_block_number
|
||||
}
|
||||
@@ -84,8 +84,11 @@ impl<C, M> Filterable for EthFilterClient<C, M> where C: BlockChainClient, M: Mi
|
||||
self.client.block_hash(id).map(Into::into)
|
||||
}
|
||||
|
||||
fn pending_transactions_hashes(&self, best: u64) -> Vec<H256> {
|
||||
self.miner.pending_transactions_hashes(best)
|
||||
fn pending_transactions_hashes(&self) -> Vec<H256> {
|
||||
self.miner.ready_transactions(&*self.client)
|
||||
.into_iter()
|
||||
.map(|tx| tx.signed().hash())
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn logs(&self, filter: EthcoreFilter) -> BoxFuture<Vec<Log>> {
|
||||
@@ -118,8 +121,7 @@ impl<T: Filterable + Send + Sync + 'static> EthFilter for T {
|
||||
|
||||
fn new_pending_transaction_filter(&self) -> Result<RpcU256> {
|
||||
let mut polls = self.polls().lock();
|
||||
let best_block = self.best_block_number();
|
||||
let pending_transactions = self.pending_transactions_hashes(best_block);
|
||||
let pending_transactions = self.pending_transactions_hashes();
|
||||
let id = polls.create_poll(PollFilter::PendingTransaction(pending_transactions));
|
||||
Ok(id.into())
|
||||
}
|
||||
@@ -143,8 +145,7 @@ impl<T: Filterable + Send + Sync + 'static> EthFilter for T {
|
||||
},
|
||||
PollFilter::PendingTransaction(ref mut previous_hashes) => {
|
||||
// get hashes of pending transactions
|
||||
let best_block = self.best_block_number();
|
||||
let current_hashes = self.pending_transactions_hashes(best_block);
|
||||
let current_hashes = self.pending_transactions_hashes();
|
||||
|
||||
let new_hashes =
|
||||
{
|
||||
|
||||
@@ -533,7 +533,7 @@ impl<T: LightChainClient + 'static> Filterable for EthClient<T> {
|
||||
self.client.block_hash(id).map(Into::into)
|
||||
}
|
||||
|
||||
fn pending_transactions_hashes(&self, _block_number: u64) -> Vec<::ethereum_types::H256> {
|
||||
fn pending_transactions_hashes(&self) -> Vec<::ethereum_types::H256> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
|
||||
@@ -275,6 +275,21 @@ impl Parity for ParityClient {
|
||||
)
|
||||
}
|
||||
|
||||
fn all_transactions(&self) -> Result<Vec<Transaction>> {
|
||||
let txq = self.light_dispatch.transaction_queue.read();
|
||||
let chain_info = self.light_dispatch.client.chain_info();
|
||||
|
||||
let current = txq.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp);
|
||||
let future = txq.future_transactions(chain_info.best_block_number, chain_info.best_block_timestamp);
|
||||
Ok(
|
||||
current
|
||||
.into_iter()
|
||||
.chain(future.into_iter())
|
||||
.map(|tx| Transaction::from_pending(tx, chain_info.best_block_number, self.eip86_transition))
|
||||
.collect::<Vec<_>>()
|
||||
)
|
||||
}
|
||||
|
||||
fn future_transactions(&self) -> Result<Vec<Transaction>> {
|
||||
let txq = self.light_dispatch.transaction_queue.read();
|
||||
let chain_info = self.light_dispatch.client.chain_info();
|
||||
|
||||
@@ -27,9 +27,9 @@ use ethkey::{Brain, Generator};
|
||||
use ethstore::random_phrase;
|
||||
use sync::{SyncProvider, ManageNetwork};
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::client::{MiningBlockChainClient, StateClient, Call};
|
||||
use ethcore::client::{BlockChainClient, StateClient, Call};
|
||||
use ethcore::ids::BlockId;
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::miner::{self, MinerService};
|
||||
use ethcore::mode::Mode;
|
||||
use ethcore::state::StateInfo;
|
||||
use ethcore_logger::RotatingLogger;
|
||||
@@ -72,7 +72,7 @@ pub struct ParityClient<C, M, U> {
|
||||
}
|
||||
|
||||
impl<C, M, U> ParityClient<C, M, U> where
|
||||
C: MiningBlockChainClient,
|
||||
C: BlockChainClient,
|
||||
{
|
||||
/// Creates new `ParityClient`.
|
||||
pub fn new(
|
||||
@@ -116,7 +116,7 @@ impl<C, M, U> ParityClient<C, M, U> where
|
||||
|
||||
impl<C, M, U, S> Parity for ParityClient<C, M, U> where
|
||||
S: StateInfo + 'static,
|
||||
C: MiningBlockChainClient + StateClient<State=S> + Call<State=S> + 'static,
|
||||
C: miner::BlockChainClient + BlockChainClient + StateClient<State=S> + Call<State=S> + 'static,
|
||||
M: MinerService<State=S> + 'static,
|
||||
U: UpdateService + 'static,
|
||||
{
|
||||
@@ -170,23 +170,23 @@ impl<C, M, U, S> Parity for ParityClient<C, M, U> where
|
||||
}
|
||||
|
||||
fn transactions_limit(&self) -> Result<usize> {
|
||||
Ok(self.miner.transactions_limit())
|
||||
Ok(self.miner.queue_status().limits.max_count)
|
||||
}
|
||||
|
||||
fn min_gas_price(&self) -> Result<U256> {
|
||||
Ok(U256::from(self.miner.minimal_gas_price()))
|
||||
Ok(self.miner.queue_status().options.minimal_gas_price.into())
|
||||
}
|
||||
|
||||
fn extra_data(&self) -> Result<Bytes> {
|
||||
Ok(Bytes::new(self.miner.extra_data()))
|
||||
Ok(Bytes::new(self.miner.authoring_params().extra_data))
|
||||
}
|
||||
|
||||
fn gas_floor_target(&self) -> Result<U256> {
|
||||
Ok(U256::from(self.miner.gas_floor_target()))
|
||||
Ok(U256::from(self.miner.authoring_params().gas_range_target.0))
|
||||
}
|
||||
|
||||
fn gas_ceil_target(&self) -> Result<U256> {
|
||||
Ok(U256::from(self.miner.gas_ceil_target()))
|
||||
Ok(U256::from(self.miner.authoring_params().gas_range_target.1))
|
||||
}
|
||||
|
||||
fn dev_logs(&self) -> Result<Vec<String>> {
|
||||
@@ -315,12 +315,28 @@ impl<C, M, U, S> Parity for ParityClient<C, M, U> where
|
||||
|
||||
fn pending_transactions(&self) -> Result<Vec<Transaction>> {
|
||||
let block_number = self.client.chain_info().best_block_number;
|
||||
Ok(self.miner.pending_transactions().into_iter().map(|t| Transaction::from_pending(t, block_number, self.eip86_transition)).collect::<Vec<_>>())
|
||||
let ready_transactions = self.miner.ready_transactions(&*self.client);
|
||||
|
||||
Ok(ready_transactions
|
||||
.into_iter()
|
||||
.map(|t| Transaction::from_pending(t.pending().clone(), block_number, self.eip86_transition))
|
||||
.collect()
|
||||
)
|
||||
}
|
||||
|
||||
fn all_transactions(&self) -> Result<Vec<Transaction>> {
|
||||
let block_number = self.client.chain_info().best_block_number;
|
||||
let all_transactions = self.miner.queued_transactions();
|
||||
|
||||
Ok(all_transactions
|
||||
.into_iter()
|
||||
.map(|t| Transaction::from_pending(t.pending().clone(), block_number, self.eip86_transition))
|
||||
.collect()
|
||||
)
|
||||
}
|
||||
|
||||
fn future_transactions(&self) -> Result<Vec<Transaction>> {
|
||||
let block_number = self.client.chain_info().best_block_number;
|
||||
Ok(self.miner.future_transactions().into_iter().map(|t| Transaction::from_pending(t, block_number, self.eip86_transition)).collect::<Vec<_>>())
|
||||
Err(errors::deprecated("Use `parity_allTransaction` instead."))
|
||||
}
|
||||
|
||||
fn pending_transactions_stats(&self) -> Result<BTreeMap<H256, TransactionStats>> {
|
||||
@@ -359,11 +375,7 @@ impl<C, M, U, S> Parity for ParityClient<C, M, U> where
|
||||
fn next_nonce(&self, address: H160) -> BoxFuture<U256> {
|
||||
let address: Address = address.into();
|
||||
|
||||
Box::new(future::ok(self.miner.last_nonce(&address)
|
||||
.map(|n| n + 1.into())
|
||||
.unwrap_or_else(|| self.client.latest_nonce(&address))
|
||||
.into()
|
||||
))
|
||||
Box::new(future::ok(self.miner.next_nonce(&*self.client, &address).into()))
|
||||
}
|
||||
|
||||
fn mode(&self) -> Result<String> {
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
use std::io;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ethcore::client::BlockChainClient;
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::client::MiningBlockChainClient;
|
||||
use ethcore::mode::Mode;
|
||||
use sync::ManageNetwork;
|
||||
use fetch::{self, Fetch};
|
||||
@@ -47,7 +47,7 @@ pub struct ParitySetClient<C, M, U, F = fetch::Client> {
|
||||
}
|
||||
|
||||
impl<C, M, U, F> ParitySetClient<C, M, U, F>
|
||||
where C: MiningBlockChainClient + 'static,
|
||||
where C: BlockChainClient + 'static,
|
||||
{
|
||||
/// Creates new `ParitySetClient` with given `Fetch`.
|
||||
pub fn new(
|
||||
@@ -73,24 +73,38 @@ impl<C, M, U, F> ParitySetClient<C, M, U, F>
|
||||
}
|
||||
|
||||
impl<C, M, U, F> ParitySet for ParitySetClient<C, M, U, F> where
|
||||
C: MiningBlockChainClient + 'static,
|
||||
C: BlockChainClient + 'static,
|
||||
M: MinerService + 'static,
|
||||
U: UpdateService + 'static,
|
||||
F: Fetch + 'static,
|
||||
{
|
||||
|
||||
fn set_min_gas_price(&self, gas_price: U256) -> Result<bool> {
|
||||
self.miner.set_minimal_gas_price(gas_price.into());
|
||||
Ok(true)
|
||||
fn set_min_gas_price(&self, _gas_price: U256) -> Result<bool> {
|
||||
warn!("setMinGasPrice is deprecated. Ignoring request.");
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn set_transactions_limit(&self, _limit: usize) -> Result<bool> {
|
||||
warn!("setTransactionsLimit is deprecated. Ignoring request.");
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn set_tx_gas_limit(&self, _limit: U256) -> Result<bool> {
|
||||
warn!("setTxGasLimit is deprecated. Ignoring request.");
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn set_gas_floor_target(&self, target: U256) -> Result<bool> {
|
||||
self.miner.set_gas_floor_target(target.into());
|
||||
let mut range = self.miner.authoring_params().gas_range_target.clone();
|
||||
range.0 = target.into();
|
||||
self.miner.set_gas_range_target(range);
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn set_gas_ceil_target(&self, target: U256) -> Result<bool> {
|
||||
self.miner.set_gas_ceil_target(target.into());
|
||||
let mut range = self.miner.authoring_params().gas_range_target.clone();
|
||||
range.1 = target.into();
|
||||
self.miner.set_gas_range_target(range);
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
@@ -99,23 +113,13 @@ impl<C, M, U, F> ParitySet for ParitySetClient<C, M, U, F> where
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn set_author(&self, author: H160) -> Result<bool> {
|
||||
self.miner.set_author(author.into());
|
||||
fn set_author(&self, address: H160) -> Result<bool> {
|
||||
self.miner.set_author(address.into(), None).map_err(Into::into).map_err(errors::password)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn set_engine_signer(&self, address: H160, password: String) -> Result<bool> {
|
||||
self.miner.set_engine_signer(address.into(), password).map_err(Into::into).map_err(errors::password)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn set_transactions_limit(&self, limit: usize) -> Result<bool> {
|
||||
self.miner.set_transactions_limit(limit);
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn set_tx_gas_limit(&self, limit: U256) -> Result<bool> {
|
||||
self.miner.set_tx_gas_limit(limit.into());
|
||||
self.miner.set_author(address.into(), Some(password)).map_err(Into::into).map_err(errors::password)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
@@ -202,6 +206,8 @@ impl<C, M, U, F> ParitySet for ParitySetClient<C, M, U, F> where
|
||||
let block_number = self.client.chain_info().best_block_number;
|
||||
let hash = hash.into();
|
||||
|
||||
Ok(self.miner.remove_pending_transaction(&*self.client, &hash).map(|t| Transaction::from_pending(t, block_number, self.eip86_transition)))
|
||||
Ok(self.miner.remove_transaction(&hash)
|
||||
.map(|t| Transaction::from_pending(t.pending().clone(), block_number + 1, self.eip86_transition))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use ethcore::client::{MiningBlockChainClient, CallAnalytics, TransactionId, TraceId, StateClient, StateInfo, Call, BlockId};
|
||||
use ethcore::client::{BlockChainClient, CallAnalytics, TransactionId, TraceId, StateClient, StateInfo, Call, BlockId};
|
||||
use rlp::UntrustedRlp;
|
||||
use transaction::SignedTransaction;
|
||||
|
||||
@@ -53,7 +53,7 @@ impl<C> TracesClient<C> {
|
||||
|
||||
impl<C, S> Traces for TracesClient<C> where
|
||||
S: StateInfo + 'static,
|
||||
C: MiningBlockChainClient + StateClient<State=S> + Call<State=S> + 'static
|
||||
C: BlockChainClient + StateClient<State=S> + Call<State=S> + 'static
|
||||
{
|
||||
type Metadata = Metadata;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -143,7 +143,13 @@ build_rpc_trait! {
|
||||
#[rpc(name = "parity_pendingTransactions")]
|
||||
fn pending_transactions(&self) -> Result<Vec<Transaction>>;
|
||||
|
||||
/// Returns all future transactions from transaction queue.
|
||||
/// Returns all transactions from transaction queue.
|
||||
///
|
||||
/// Some of them might not be ready to be included in a block yet.
|
||||
#[rpc(name = "parity_allTransactions")]
|
||||
fn all_transactions(&self) -> Result<Vec<Transaction>>;
|
||||
|
||||
/// Returns all future transactions from transaction queue (deprecated)
|
||||
#[rpc(name = "parity_futureTransactions")]
|
||||
fn future_transactions(&self) -> Result<Vec<Transaction>>;
|
||||
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use serde::{Serialize, Serializer};
|
||||
use serde::ser::SerializeStruct;
|
||||
use ethcore::miner;
|
||||
use ethcore::{contract_address, CreateContractAddress};
|
||||
use miner;
|
||||
use transaction::{LocalizedTransaction, Action, PendingTransaction, SignedTransaction};
|
||||
use v1::helpers::errors;
|
||||
use v1::types::{Bytes, H160, H256, U256, H512, U64, TransactionCondition};
|
||||
|
||||
/// Transaction
|
||||
@@ -248,17 +249,23 @@ impl Transaction {
|
||||
|
||||
impl LocalTransactionStatus {
|
||||
/// Convert `LocalTransactionStatus` into RPC `LocalTransactionStatus`.
|
||||
pub fn from(s: miner::LocalTransactionStatus, block_number: u64, eip86_transition: u64) -> Self {
|
||||
use ethcore::miner::LocalTransactionStatus::*;
|
||||
pub fn from(s: miner::pool::local_transactions::Status, block_number: u64, eip86_transition: u64) -> Self {
|
||||
let convert = |tx: Arc<miner::pool::VerifiedTransaction>| {
|
||||
Transaction::from_signed(tx.signed().clone(), block_number, eip86_transition)
|
||||
};
|
||||
use miner::pool::local_transactions::Status::*;
|
||||
match s {
|
||||
Pending => LocalTransactionStatus::Pending,
|
||||
Future => LocalTransactionStatus::Future,
|
||||
Mined(tx) => LocalTransactionStatus::Mined(Transaction::from_signed(tx, block_number, eip86_transition)),
|
||||
Dropped(tx) => LocalTransactionStatus::Dropped(Transaction::from_signed(tx, block_number, eip86_transition)),
|
||||
Rejected(tx, err) => LocalTransactionStatus::Rejected(Transaction::from_signed(tx, block_number, eip86_transition), errors::transaction_message(err)),
|
||||
Replaced(tx, gas_price, hash) => LocalTransactionStatus::Replaced(Transaction::from_signed(tx, block_number, eip86_transition), gas_price.into(), hash.into()),
|
||||
Invalid(tx) => LocalTransactionStatus::Invalid(Transaction::from_signed(tx, block_number, eip86_transition)),
|
||||
Canceled(tx) => LocalTransactionStatus::Canceled(Transaction::from_pending(tx, block_number, eip86_transition)),
|
||||
Pending(_) => LocalTransactionStatus::Pending,
|
||||
Mined(tx) => LocalTransactionStatus::Mined(convert(tx)),
|
||||
Dropped(tx) => LocalTransactionStatus::Dropped(convert(tx)),
|
||||
Rejected(tx, reason) => LocalTransactionStatus::Rejected(convert(tx), reason),
|
||||
Invalid(tx) => LocalTransactionStatus::Invalid(convert(tx)),
|
||||
Canceled(tx) => LocalTransactionStatus::Canceled(convert(tx)),
|
||||
Replaced { old, new } => LocalTransactionStatus::Replaced(
|
||||
convert(old),
|
||||
new.signed().gas_price.into(),
|
||||
new.signed().hash().into(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user