Validating senders balance before importing transaction to queue
This commit is contained in:
parent
2e88183df4
commit
74ea9cc74c
@ -70,7 +70,14 @@ pub enum TransactionError {
|
|||||||
/// Minimal expected gas price
|
/// Minimal expected gas price
|
||||||
minimal: U256,
|
minimal: U256,
|
||||||
/// Transaction gas price
|
/// Transaction gas price
|
||||||
got: U256
|
got: U256,
|
||||||
|
},
|
||||||
|
/// Sender doesn't have enough funds to pay for this transaction
|
||||||
|
InsufficientBalance {
|
||||||
|
/// Senders balance
|
||||||
|
balance: U256,
|
||||||
|
/// Transaction cost
|
||||||
|
cost: U256,
|
||||||
},
|
},
|
||||||
/// Transaction's gas limit (aka gas) is invalid.
|
/// Transaction's gas limit (aka gas) is invalid.
|
||||||
InvalidGasLimit(OutOfBounds<U256>),
|
InvalidGasLimit(OutOfBounds<U256>),
|
||||||
|
@ -62,11 +62,11 @@ extern crate rayon;
|
|||||||
mod miner;
|
mod miner;
|
||||||
mod transaction_queue;
|
mod transaction_queue;
|
||||||
|
|
||||||
pub use transaction_queue::TransactionQueue;
|
pub use transaction_queue::{TransactionQueue, AccountDetails};
|
||||||
pub use miner::{Miner};
|
pub use miner::{Miner};
|
||||||
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use util::{H256, U256, Address, Bytes};
|
use util::{H256, Address, Bytes};
|
||||||
use ethcore::client::{BlockChainClient};
|
use ethcore::client::{BlockChainClient};
|
||||||
use ethcore::block::{ClosedBlock};
|
use ethcore::block::{ClosedBlock};
|
||||||
use ethcore::error::{Error};
|
use ethcore::error::{Error};
|
||||||
@ -79,8 +79,8 @@ pub trait MinerService : Send + Sync {
|
|||||||
fn status(&self) -> MinerStatus;
|
fn status(&self) -> MinerStatus;
|
||||||
|
|
||||||
/// Imports transactions to transaction queue.
|
/// Imports transactions to transaction queue.
|
||||||
fn import_transactions<T>(&self, transactions: Vec<SignedTransaction>, fetch_nonce: T) -> Result<(), Error>
|
fn import_transactions<T>(&self, transactions: Vec<SignedTransaction>, fetch_account: T) -> Result<(), Error>
|
||||||
where T: Fn(&Address) -> U256;
|
where T: Fn(&Address) -> AccountDetails;
|
||||||
|
|
||||||
/// Returns hashes of transactions currently in pending
|
/// Returns hashes of transactions currently in pending
|
||||||
fn pending_transactions_hashes(&self) -> Vec<H256>;
|
fn pending_transactions_hashes(&self) -> Vec<H256>;
|
||||||
|
@ -26,7 +26,7 @@ use ethcore::client::{BlockChainClient, BlockId};
|
|||||||
use ethcore::block::{ClosedBlock, IsBlock};
|
use ethcore::block::{ClosedBlock, IsBlock};
|
||||||
use ethcore::error::{Error};
|
use ethcore::error::{Error};
|
||||||
use ethcore::transaction::SignedTransaction;
|
use ethcore::transaction::SignedTransaction;
|
||||||
use super::{MinerService, MinerStatus, TransactionQueue};
|
use super::{MinerService, MinerStatus, TransactionQueue, AccountDetails};
|
||||||
|
|
||||||
/// Keeps track of transactions using priority queue and holds currently mined block.
|
/// Keeps track of transactions using priority queue and holds currently mined block.
|
||||||
pub struct Miner {
|
pub struct Miner {
|
||||||
@ -72,7 +72,7 @@ impl Miner {
|
|||||||
|
|
||||||
/// Get the extra_data that we will seal blocks wuth.
|
/// Get the extra_data that we will seal blocks wuth.
|
||||||
fn gas_floor_target(&self) -> U256 {
|
fn gas_floor_target(&self) -> U256 {
|
||||||
self.gas_floor_target.read().unwrap().clone()
|
*self.gas_floor_target.read().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the author that we will seal blocks as.
|
/// Set the author that we will seal blocks as.
|
||||||
@ -113,10 +113,10 @@ impl MinerService for Miner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_transactions<T>(&self, transactions: Vec<SignedTransaction>, fetch_nonce: T) -> Result<(), Error>
|
fn import_transactions<T>(&self, transactions: Vec<SignedTransaction>, fetch_account: T) -> Result<(), Error>
|
||||||
where T: Fn(&Address) -> U256 {
|
where T: Fn(&Address) -> AccountDetails {
|
||||||
let mut transaction_queue = self.transaction_queue.lock().unwrap();
|
let mut transaction_queue = self.transaction_queue.lock().unwrap();
|
||||||
transaction_queue.add_all(transactions, fetch_nonce)
|
transaction_queue.add_all(transactions, fetch_account)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pending_transactions_hashes(&self) -> Vec<H256> {
|
fn pending_transactions_hashes(&self) -> Vec<H256> {
|
||||||
@ -187,7 +187,10 @@ impl MinerService for Miner {
|
|||||||
let _sender = tx.sender();
|
let _sender = tx.sender();
|
||||||
}
|
}
|
||||||
let mut transaction_queue = self.transaction_queue.lock().unwrap();
|
let mut transaction_queue = self.transaction_queue.lock().unwrap();
|
||||||
let _ = transaction_queue.add_all(txs, |a| chain.nonce(a));
|
let _ = transaction_queue.add_all(txs, |a| AccountDetails {
|
||||||
|
nonce: chain.nonce(a),
|
||||||
|
balance: chain.balance(a)
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// First import all transactions and after that remove old ones
|
// First import all transactions and after that remove old ones
|
||||||
@ -209,7 +212,10 @@ impl MinerService for Miner {
|
|||||||
in_chain.for_each(|txs| {
|
in_chain.for_each(|txs| {
|
||||||
let hashes = txs.iter().map(|tx| tx.hash()).collect::<Vec<H256>>();
|
let hashes = txs.iter().map(|tx| tx.hash()).collect::<Vec<H256>>();
|
||||||
let mut transaction_queue = self.transaction_queue.lock().unwrap();
|
let mut transaction_queue = self.transaction_queue.lock().unwrap();
|
||||||
transaction_queue.remove_all(&hashes, |a| chain.nonce(a));
|
transaction_queue.remove_all(&hashes, |a| AccountDetails {
|
||||||
|
nonce: chain.nonce(a),
|
||||||
|
balance: chain.balance(a)
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,8 +232,6 @@ impl TransactionSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Will be used when rpc merged
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// Current status of the queue
|
/// Current status of the queue
|
||||||
pub struct TransactionQueueStatus {
|
pub struct TransactionQueueStatus {
|
||||||
@ -243,6 +241,14 @@ pub struct TransactionQueueStatus {
|
|||||||
pub future: usize,
|
pub future: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Details of account
|
||||||
|
pub struct AccountDetails {
|
||||||
|
/// Most recent account nonce
|
||||||
|
pub nonce: U256,
|
||||||
|
/// Current account balance
|
||||||
|
pub balance: U256,
|
||||||
|
}
|
||||||
|
|
||||||
/// TransactionQueue implementation
|
/// TransactionQueue implementation
|
||||||
pub struct TransactionQueue {
|
pub struct TransactionQueue {
|
||||||
/// Gas Price threshold for transactions that can be imported to this queue (defaults to 0)
|
/// Gas Price threshold for transactions that can be imported to this queue (defaults to 0)
|
||||||
@ -308,49 +314,63 @@ impl TransactionQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds all signed transactions to queue to be verified and imported
|
/// Adds all signed transactions to queue to be verified and imported
|
||||||
pub fn add_all<T>(&mut self, txs: Vec<SignedTransaction>, fetch_nonce: T) -> Result<(), Error>
|
pub fn add_all<T>(&mut self, txs: Vec<SignedTransaction>, fetch_account: T) -> Result<(), Error>
|
||||||
where T: Fn(&Address) -> U256 {
|
where T: Fn(&Address) -> AccountDetails {
|
||||||
for tx in txs.into_iter() {
|
for tx in txs.into_iter() {
|
||||||
try!(self.add(tx, &fetch_nonce));
|
try!(self.add(tx, &fetch_account));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add signed transaction to queue to be verified and imported
|
/// Add signed transaction to queue to be verified and imported
|
||||||
pub fn add<T>(&mut self, tx: SignedTransaction, fetch_nonce: &T) -> Result<(), Error>
|
pub fn add<T>(&mut self, tx: SignedTransaction, fetch_account: &T) -> Result<(), Error>
|
||||||
where T: Fn(&Address) -> U256 {
|
where T: Fn(&Address) -> AccountDetails {
|
||||||
|
|
||||||
|
trace!(target: "miner", "Importing: {:?}", tx.hash());
|
||||||
|
|
||||||
if tx.gas_price < self.minimal_gas_price {
|
if tx.gas_price < self.minimal_gas_price {
|
||||||
trace!(target: "sync",
|
trace!(target: "miner",
|
||||||
"Dropping transaction below minimal gas price threshold: {:?} (gp: {} < {})",
|
"Dropping transaction below minimal gas price threshold: {:?} (gp: {} < {})",
|
||||||
tx.hash(), tx.gas_price, self.minimal_gas_price
|
tx.hash(), tx.gas_price, self.minimal_gas_price
|
||||||
);
|
);
|
||||||
|
|
||||||
return Err(Error::Transaction(TransactionError::InsufficientGasPrice{
|
return Err(Error::Transaction(TransactionError::InsufficientGasPrice{
|
||||||
minimal: self.minimal_gas_price,
|
minimal: self.minimal_gas_price,
|
||||||
got: tx.gas_price
|
got: tx.gas_price,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.import_tx(try!(VerifiedTransaction::new(tx)), fetch_nonce);
|
let vtx = try!(VerifiedTransaction::new(tx));
|
||||||
|
let account = fetch_account(&vtx.sender());
|
||||||
|
|
||||||
|
if account.balance < vtx.transaction.value {
|
||||||
|
trace!(target: "miner", "Dropping transaction without sufficient balance: {:?} ({} < {})",
|
||||||
|
vtx.hash(), account.balance, vtx.transaction.value);
|
||||||
|
return Err(Error::Transaction(TransactionError::InsufficientBalance {
|
||||||
|
cost: vtx.transaction.value,
|
||||||
|
balance: account.balance
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.import_tx(vtx, account.nonce);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes all transactions identified by hashes given in slice
|
/// Removes all transactions identified by hashes given in slice
|
||||||
///
|
///
|
||||||
/// If gap is introduced marks subsequent transactions as future
|
/// If gap is introduced marks subsequent transactions as future
|
||||||
pub fn remove_all<T>(&mut self, transaction_hashes: &[H256], fetch_nonce: T)
|
pub fn remove_all<T>(&mut self, transaction_hashes: &[H256], fetch_account: T)
|
||||||
where T: Fn(&Address) -> U256 {
|
where T: Fn(&Address) -> AccountDetails {
|
||||||
for hash in transaction_hashes {
|
for hash in transaction_hashes {
|
||||||
self.remove(&hash, &fetch_nonce);
|
self.remove(&hash, &fetch_account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes transaction identified by hashes from queue.
|
/// Removes transaction identified by hashes from queue.
|
||||||
///
|
///
|
||||||
/// If gap is introduced marks subsequent transactions as future
|
/// If gap is introduced marks subsequent transactions as future
|
||||||
pub fn remove<T>(&mut self, transaction_hash: &H256, fetch_nonce: &T)
|
pub fn remove<T>(&mut self, transaction_hash: &H256, fetch_account: &T)
|
||||||
where T: Fn(&Address) -> U256 {
|
where T: Fn(&Address) -> AccountDetails {
|
||||||
|
|
||||||
let transaction = self.by_hash.remove(transaction_hash);
|
let transaction = self.by_hash.remove(transaction_hash);
|
||||||
if transaction.is_none() {
|
if transaction.is_none() {
|
||||||
@ -361,7 +381,7 @@ impl TransactionQueue {
|
|||||||
let transaction = transaction.unwrap();
|
let transaction = transaction.unwrap();
|
||||||
let sender = transaction.sender();
|
let sender = transaction.sender();
|
||||||
let nonce = transaction.nonce();
|
let nonce = transaction.nonce();
|
||||||
let current_nonce = fetch_nonce(&sender);
|
let current_nonce = fetch_account(&sender).nonce;
|
||||||
|
|
||||||
|
|
||||||
// Remove from future
|
// Remove from future
|
||||||
@ -403,6 +423,7 @@ impl TransactionQueue {
|
|||||||
if k >= current_nonce {
|
if k >= current_nonce {
|
||||||
self.future.insert(*sender, k, order.update_height(k, current_nonce));
|
self.future.insert(*sender, k, order.update_height(k, current_nonce));
|
||||||
} else {
|
} else {
|
||||||
|
trace!(target: "miner", "Dropping old transaction: {:?} (nonce: {} < {})", order.hash, k, current_nonce);
|
||||||
// Remove the transaction completely
|
// Remove the transaction completely
|
||||||
self.by_hash.remove(&order.hash);
|
self.by_hash.remove(&order.hash);
|
||||||
}
|
}
|
||||||
@ -423,6 +444,7 @@ impl TransactionQueue {
|
|||||||
if k >= current_nonce {
|
if k >= current_nonce {
|
||||||
self.future.insert(*sender, k, order.update_height(k, current_nonce));
|
self.future.insert(*sender, k, order.update_height(k, current_nonce));
|
||||||
} else {
|
} else {
|
||||||
|
trace!(target: "miner", "Dropping old transaction: {:?} (nonce: {} < {})", order.hash, k, current_nonce);
|
||||||
self.by_hash.remove(&order.hash);
|
self.by_hash.remove(&order.hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,13 +510,11 @@ impl TransactionQueue {
|
|||||||
///
|
///
|
||||||
/// It ignores transactions that has already been imported (same `hash`) and replaces the transaction
|
/// It ignores transactions that has already been imported (same `hash`) and replaces the transaction
|
||||||
/// iff `(address, nonce)` is the same but `gas_price` is higher.
|
/// iff `(address, nonce)` is the same but `gas_price` is higher.
|
||||||
fn import_tx<T>(&mut self, tx: VerifiedTransaction, fetch_nonce: &T)
|
fn import_tx(&mut self, tx: VerifiedTransaction, state_nonce: U256) {
|
||||||
where T: Fn(&Address) -> U256 {
|
|
||||||
|
|
||||||
|
|
||||||
if self.by_hash.get(&tx.hash()).is_some() {
|
if self.by_hash.get(&tx.hash()).is_some() {
|
||||||
// Transaction is already imported.
|
// Transaction is already imported.
|
||||||
trace!(target: "sync", "Dropping already imported transaction with hash: {:?}", tx.hash());
|
trace!(target: "miner", "Dropping already imported transaction: {:?}", tx.hash());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,7 +522,6 @@ impl TransactionQueue {
|
|||||||
let address = tx.sender();
|
let address = tx.sender();
|
||||||
let nonce = tx.nonce();
|
let nonce = tx.nonce();
|
||||||
|
|
||||||
let state_nonce = fetch_nonce(&address);
|
|
||||||
let next_nonce = self.last_nonces
|
let next_nonce = self.last_nonces
|
||||||
.get(&address)
|
.get(&address)
|
||||||
.cloned()
|
.cloned()
|
||||||
@ -516,7 +535,7 @@ impl TransactionQueue {
|
|||||||
return;
|
return;
|
||||||
} else if nonce < state_nonce {
|
} else if nonce < state_nonce {
|
||||||
// Droping transaction
|
// Droping transaction
|
||||||
trace!(target: "sync", "Dropping transaction with nonce: {} - expecting: {}", nonce, next_nonce);
|
trace!(target: "miner", "Dropping old transaction: {:?} (nonce: {} < {})", tx.hash(), nonce, next_nonce);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,6 +544,8 @@ impl TransactionQueue {
|
|||||||
// But maybe there are some more items waiting in future?
|
// But maybe there are some more items waiting in future?
|
||||||
self.move_matching_future_to_current(address, nonce + U256::one(), state_nonce);
|
self.move_matching_future_to_current(address, nonce + U256::one(), state_nonce);
|
||||||
self.current.enforce_limit(&mut self.by_hash);
|
self.current.enforce_limit(&mut self.by_hash);
|
||||||
|
|
||||||
|
trace!(target: "miner", "status: {:?}", self.status());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces transaction in given set (could be `future` or `current`).
|
/// Replaces transaction in given set (could be `future` or `current`).
|
||||||
@ -583,8 +604,11 @@ mod test {
|
|||||||
new_unsigned_tx(U256::from(123)).sign(&keypair.secret())
|
new_unsigned_tx(U256::from(123)).sign(&keypair.secret())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_nonce(_address: &Address) -> U256 {
|
fn default_nonce(_address: &Address) -> AccountDetails {
|
||||||
U256::from(123)
|
AccountDetails {
|
||||||
|
nonce: U256::from(123),
|
||||||
|
balance: !U256::zero()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_txs(second_nonce: U256) -> (SignedTransaction, SignedTransaction) {
|
fn new_txs(second_nonce: U256) -> (SignedTransaction, SignedTransaction) {
|
||||||
@ -953,7 +977,8 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_not_move_to_future_if_state_nonce_is_higher() {
|
fn should_not_move_to_future_if_state_nonce_is_higher() {
|
||||||
// given
|
// given
|
||||||
let next_nonce = |a: &Address| default_nonce(a) + U256::one();
|
let next_nonce = |a: &Address| AccountDetails{ nonce: default_nonce(a).nonce + U256::one(), balance:
|
||||||
|
!U256::zero() };
|
||||||
let mut txq = TransactionQueue::new();
|
let mut txq = TransactionQueue::new();
|
||||||
let (tx, tx2) = new_txs(U256::from(1));
|
let (tx, tx2) = new_txs(U256::from(1));
|
||||||
let tx3 = new_tx();
|
let tx3 = new_tx();
|
||||||
@ -1028,8 +1053,10 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn should_recalculate_height_when_removing_from_future() {
|
fn should_recalculate_height_when_removing_from_future() {
|
||||||
// given
|
// given
|
||||||
let previous_nonce = |a: &Address| default_nonce(a) - U256::one();
|
let previous_nonce = |a: &Address| AccountDetails{ nonce: default_nonce(a).nonce - U256::one(), balance:
|
||||||
let next_nonce = |a: &Address| default_nonce(a) + U256::one();
|
!U256::zero() };
|
||||||
|
let next_nonce = |a: &Address| AccountDetails{ nonce: default_nonce(a).nonce + U256::one(), balance:
|
||||||
|
!U256::zero() };
|
||||||
let mut txq = TransactionQueue::new();
|
let mut txq = TransactionQueue::new();
|
||||||
let (tx1, tx2) = new_txs(U256::one());
|
let (tx1, tx2) = new_txs(U256::one());
|
||||||
txq.add(tx1.clone(), &previous_nonce).unwrap();
|
txq.add(tx1.clone(), &previous_nonce).unwrap();
|
||||||
|
@ -19,7 +19,7 @@ use std::collections::HashSet;
|
|||||||
use std::sync::{Arc, Weak, Mutex};
|
use std::sync::{Arc, Weak, Mutex};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use ethsync::{SyncProvider, SyncState};
|
use ethsync::{SyncProvider, SyncState};
|
||||||
use ethminer::{MinerService};
|
use ethminer::{MinerService, AccountDetails};
|
||||||
use jsonrpc_core::*;
|
use jsonrpc_core::*;
|
||||||
use util::numbers::*;
|
use util::numbers::*;
|
||||||
use util::sha3::*;
|
use util::sha3::*;
|
||||||
@ -381,7 +381,10 @@ impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM>
|
|||||||
let signed_transaction = transaction.sign(&secret);
|
let signed_transaction = transaction.sign(&secret);
|
||||||
let hash = signed_transaction.hash();
|
let hash = signed_transaction.hash();
|
||||||
|
|
||||||
let import = miner.import_transactions(vec![signed_transaction], |a: &Address| client.nonce(a));
|
let import = miner.import_transactions(vec![signed_transaction], |a: &Address| AccountDetails {
|
||||||
|
nonce: client.nonce(a),
|
||||||
|
balance: client.balance(a)
|
||||||
|
});
|
||||||
match import {
|
match import {
|
||||||
Ok(_) => to_value(&hash),
|
Ok(_) => to_value(&hash),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -20,7 +20,7 @@ use ethcore::error::Error;
|
|||||||
use ethcore::client::BlockChainClient;
|
use ethcore::client::BlockChainClient;
|
||||||
use ethcore::block::ClosedBlock;
|
use ethcore::block::ClosedBlock;
|
||||||
use ethcore::transaction::SignedTransaction;
|
use ethcore::transaction::SignedTransaction;
|
||||||
use ethminer::{MinerService, MinerStatus};
|
use ethminer::{MinerService, MinerStatus, AccountDetails};
|
||||||
|
|
||||||
pub struct TestMinerService {
|
pub struct TestMinerService {
|
||||||
pub imported_transactions: RwLock<Vec<H256>>,
|
pub imported_transactions: RwLock<Vec<H256>>,
|
||||||
@ -48,7 +48,8 @@ impl MinerService for TestMinerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Imports transactions to transaction queue.
|
/// Imports transactions to transaction queue.
|
||||||
fn import_transactions<T>(&self, _transactions: Vec<SignedTransaction>, _fetch_nonce: T) -> Result<(), Error> where T: Fn(&Address) -> U256 { unimplemented!(); }
|
fn import_transactions<T>(&self, _transactions: Vec<SignedTransaction>, _fetch_account: T) -> Result<(), Error>
|
||||||
|
where T: Fn(&Address) -> AccountDetails { unimplemented!(); }
|
||||||
|
|
||||||
/// Returns hashes of transactions currently in pending
|
/// Returns hashes of transactions currently in pending
|
||||||
fn pending_transactions_hashes(&self) -> Vec<H256> { unimplemented!(); }
|
fn pending_transactions_hashes(&self) -> Vec<H256> { unimplemented!(); }
|
||||||
|
@ -38,7 +38,7 @@ use range_collection::{RangeCollection, ToUsize, FromUsize};
|
|||||||
use ethcore::error::*;
|
use ethcore::error::*;
|
||||||
use ethcore::transaction::SignedTransaction;
|
use ethcore::transaction::SignedTransaction;
|
||||||
use ethcore::block::Block;
|
use ethcore::block::Block;
|
||||||
use ethminer::{Miner, MinerService};
|
use ethminer::{Miner, MinerService, AccountDetails};
|
||||||
use io::SyncIo;
|
use io::SyncIo;
|
||||||
use time;
|
use time;
|
||||||
use super::SyncConfig;
|
use super::SyncConfig;
|
||||||
@ -961,8 +961,11 @@ impl ChainSync {
|
|||||||
transactions.push(tx);
|
transactions.push(tx);
|
||||||
}
|
}
|
||||||
let chain = io.chain();
|
let chain = io.chain();
|
||||||
let fetch_nonce = |a: &Address| chain.nonce(a);
|
let fetch_account = |a: &Address| AccountDetails {
|
||||||
let _ = self.miner.import_transactions(transactions, fetch_nonce);
|
nonce: chain.nonce(a),
|
||||||
|
balance: chain.balance(a)
|
||||||
|
};
|
||||||
|
let _ = self.miner.import_transactions(transactions, fetch_account);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user