split interfaces
This commit is contained in:
@@ -37,7 +37,7 @@ use filter::Filter;
|
||||
use log_entry::LocalizedLogEntry;
|
||||
use block_queue::{BlockQueue, BlockQueueInfo};
|
||||
use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute};
|
||||
use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient, TraceFilter};
|
||||
use client::{BlockID, TransactionID, UncleID, TraceId, ClientConfig, BlockChainClient, ExtendedBlockChainClient, TraceFilter};
|
||||
use client::Error as ClientError;
|
||||
use env_info::EnvInfo;
|
||||
use executive::{Executive, Executed, TransactOptions, contract_address};
|
||||
@@ -448,81 +448,10 @@ impl<V> BlockChainClient for Client<V> where V: Verifier {
|
||||
Executive::new(&mut state, &env_info, self.engine.deref().deref(), &self.vm_factory).transact(t, options)
|
||||
}
|
||||
|
||||
// TODO [todr] Should be moved to miner crate eventually.
|
||||
fn try_seal(&self, block: LockedBlock, seal: Vec<Bytes>) -> Result<SealedBlock, LockedBlock> {
|
||||
block.try_seal(self.engine.deref().deref(), seal)
|
||||
}
|
||||
|
||||
fn vm_factory(&self) -> &EvmFactory {
|
||||
&self.vm_factory
|
||||
}
|
||||
|
||||
// TODO [todr] Should be moved to miner crate eventually.
|
||||
fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec<SignedTransaction>)
|
||||
-> (Option<ClosedBlock>, HashSet<H256>) {
|
||||
let engine = self.engine.deref().deref();
|
||||
let h = self.chain.best_block_hash();
|
||||
let mut invalid_transactions = HashSet::new();
|
||||
|
||||
let mut b = OpenBlock::new(
|
||||
engine,
|
||||
&self.vm_factory,
|
||||
false, // TODO: this will need to be parameterised once we want to do immediate mining insertion.
|
||||
self.state_db.lock().unwrap().boxed_clone(),
|
||||
match self.chain.block_header(&h) { Some(ref x) => x, None => { return (None, invalid_transactions) } },
|
||||
self.build_last_hashes(h.clone()),
|
||||
author,
|
||||
gas_floor_target,
|
||||
extra_data,
|
||||
);
|
||||
|
||||
// Add uncles
|
||||
self.chain
|
||||
.find_uncle_headers(&h, engine.maximum_uncle_age())
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.take(engine.maximum_uncle_count())
|
||||
.foreach(|h| {
|
||||
b.push_uncle(h).unwrap();
|
||||
});
|
||||
|
||||
// Add transactions
|
||||
let block_number = b.block().header().number();
|
||||
let min_tx_gas = U256::from(self.engine.schedule(&b.env_info()).tx_gas);
|
||||
|
||||
for tx in transactions {
|
||||
// Push transaction to block
|
||||
let hash = tx.hash();
|
||||
let import = b.push_transaction(tx, None);
|
||||
|
||||
match import {
|
||||
Err(Error::Execution(ExecutionError::BlockGasLimitReached { gas_limit, gas_used, .. })) => {
|
||||
trace!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?}", hash);
|
||||
// Exit early if gas left is smaller then min_tx_gas
|
||||
if gas_limit - gas_used < min_tx_gas {
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
invalid_transactions.insert(hash);
|
||||
trace!(target: "miner",
|
||||
"Error adding transaction to block: number={}. transaction_hash={:?}, Error: {:?}",
|
||||
block_number, hash, e);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// And close
|
||||
let b = b.close();
|
||||
trace!(target: "miner", "Sealing: number={}, hash={}, diff={}",
|
||||
b.block().header().number(),
|
||||
b.hash(),
|
||||
b.block().header().difficulty()
|
||||
);
|
||||
(Some(b), invalid_transactions)
|
||||
}
|
||||
|
||||
fn block_header(&self, id: BlockID) -> Option<Bytes> {
|
||||
Self::block_hash(&self.chain, id).and_then(|hash| self.chain.block(&hash).map(|bytes| BlockView::new(&bytes).rlp().at(0).as_raw().to_vec()))
|
||||
}
|
||||
@@ -776,6 +705,79 @@ impl<V> BlockChainClient for Client<V> where V: Verifier {
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> ExtendedBlockChainClient for Client<V> where V: Verifier {
|
||||
// TODO [todr] Should be moved to miner crate eventually.
|
||||
fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec<SignedTransaction>)
|
||||
-> (Option<ClosedBlock>, HashSet<H256>) {
|
||||
let engine = self.engine.deref().deref();
|
||||
let h = self.chain.best_block_hash();
|
||||
let mut invalid_transactions = HashSet::new();
|
||||
|
||||
let mut b = OpenBlock::new(
|
||||
engine,
|
||||
&self.vm_factory,
|
||||
false, // TODO: this will need to be parameterised once we want to do immediate mining insertion.
|
||||
self.state_db.lock().unwrap().boxed_clone(),
|
||||
match self.chain.block_header(&h) { Some(ref x) => x, None => { return (None, invalid_transactions) } },
|
||||
self.build_last_hashes(h.clone()),
|
||||
author,
|
||||
gas_floor_target,
|
||||
extra_data,
|
||||
);
|
||||
|
||||
// Add uncles
|
||||
self.chain
|
||||
.find_uncle_headers(&h, engine.maximum_uncle_age())
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.take(engine.maximum_uncle_count())
|
||||
.foreach(|h| {
|
||||
b.push_uncle(h).unwrap();
|
||||
});
|
||||
|
||||
// Add transactions
|
||||
let block_number = b.block().header().number();
|
||||
let min_tx_gas = U256::from(self.engine.schedule(&b.env_info()).tx_gas);
|
||||
|
||||
for tx in transactions {
|
||||
// Push transaction to block
|
||||
let hash = tx.hash();
|
||||
let import = b.push_transaction(tx, None);
|
||||
|
||||
match import {
|
||||
Err(Error::Execution(ExecutionError::BlockGasLimitReached { gas_limit, gas_used, .. })) => {
|
||||
trace!(target: "miner", "Skipping adding transaction to block because of gas limit: {:?}", hash);
|
||||
// Exit early if gas left is smaller then min_tx_gas
|
||||
if gas_limit - gas_used < min_tx_gas {
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
invalid_transactions.insert(hash);
|
||||
trace!(target: "miner",
|
||||
"Error adding transaction to block: number={}. transaction_hash={:?}, Error: {:?}",
|
||||
block_number, hash, e);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// And close
|
||||
let b = b.close();
|
||||
trace!(target: "miner", "Sealing: number={}, hash={}, diff={}",
|
||||
b.block().header().number(),
|
||||
b.hash(),
|
||||
b.block().header().difficulty()
|
||||
);
|
||||
(Some(b), invalid_transactions)
|
||||
}
|
||||
|
||||
// TODO [todr] Should be moved to miner crate eventually.
|
||||
fn try_seal(&self, block: LockedBlock, seal: Vec<Bytes>) -> Result<SealedBlock, LockedBlock> {
|
||||
block.try_seal(self.engine.deref().deref(), seal)
|
||||
}
|
||||
}
|
||||
|
||||
impl MayPanic for Client {
|
||||
fn on_panic<F>(&self, closure: F) where F: OnPanicListener {
|
||||
self.panic_handler.on_panic(closure);
|
||||
|
||||
@@ -154,15 +154,6 @@ pub trait BlockChainClient : Sync + Send {
|
||||
/// Returns logs matching given filter.
|
||||
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry>;
|
||||
|
||||
// TODO [todr] Should be moved to miner crate eventually.
|
||||
/// Returns ClosedBlock prepared for sealing.
|
||||
fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec<SignedTransaction>)
|
||||
-> (Option<ClosedBlock>, HashSet<H256>);
|
||||
|
||||
// TODO [todr] Should be moved to miner crate eventually.
|
||||
/// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error.
|
||||
fn try_seal(&self, block: LockedBlock, seal: Vec<Bytes>) -> Result<SealedBlock, LockedBlock>;
|
||||
|
||||
/// Makes a non-persistent transaction call.
|
||||
fn call(&self, t: &SignedTransaction) -> Result<Executed, ExecutionError>;
|
||||
|
||||
@@ -185,3 +176,14 @@ pub trait BlockChainClient : Sync + Send {
|
||||
fn last_hashes(&self) -> LastHashes;
|
||||
}
|
||||
|
||||
/// Extended client interface used for mining
|
||||
pub trait ExtendedBlockChainClient : BlockChainClient {
|
||||
// TODO [todr] Should be moved to miner crate eventually.
|
||||
/// Attempts to seal given block. Returns `SealedBlock` on success and the same block in case of error.
|
||||
fn try_seal(&self, block: LockedBlock, seal: Vec<Bytes>) -> Result<SealedBlock, LockedBlock>;
|
||||
|
||||
// TODO [todr] Should be moved to miner crate eventually.
|
||||
/// Returns ClosedBlock prepared for sealing.
|
||||
fn prepare_sealing(&self, author: Address, gas_floor_target: U256, extra_data: Bytes, transactions: Vec<SignedTransaction>)
|
||||
-> (Option<ClosedBlock>, HashSet<H256>);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrder};
|
||||
use util::*;
|
||||
use transaction::{Transaction, LocalizedTransaction, SignedTransaction, Action};
|
||||
use blockchain::TreeRoute;
|
||||
use client::{BlockChainClient, BlockChainInfo, BlockStatus, BlockID, TransactionID, UncleID, TraceId, TraceFilter, LastHashes};
|
||||
use client::{BlockChainClient, ExtendedBlockChainClient, BlockChainInfo, BlockStatus, BlockID, TransactionID, UncleID, TraceId, TraceFilter, LastHashes};
|
||||
use header::{Header as BlockHeader, BlockNumber};
|
||||
use filter::Filter;
|
||||
use log_entry::LocalizedLogEntry;
|
||||
@@ -232,6 +232,17 @@ impl TestBlockChainClient {
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtendedBlockChainClient for TestBlockChainClient {
|
||||
fn try_seal(&self, block: LockedBlock, _seal: Vec<Bytes>) -> Result<SealedBlock, LockedBlock> {
|
||||
Err(block)
|
||||
}
|
||||
|
||||
|
||||
fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec<SignedTransaction>) -> (Option<ClosedBlock>, HashSet<H256>) {
|
||||
(None, HashSet::new())
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockChainClient for TestBlockChainClient {
|
||||
fn call(&self, _t: &SignedTransaction) -> Result<Executed, ExecutionError> {
|
||||
Ok(self.execution_result.read().unwrap().clone().unwrap())
|
||||
@@ -296,14 +307,6 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn prepare_sealing(&self, _author: Address, _gas_floor_target: U256, _extra_data: Bytes, _transactions: Vec<SignedTransaction>) -> (Option<ClosedBlock>, HashSet<H256>) {
|
||||
(None, HashSet::new())
|
||||
}
|
||||
|
||||
fn try_seal(&self, block: LockedBlock, _seal: Vec<Bytes>) -> Result<SealedBlock, LockedBlock> {
|
||||
Err(block)
|
||||
}
|
||||
|
||||
fn block_header(&self, id: BlockID) -> Option<Bytes> {
|
||||
self.block_hash(id).and_then(|hash| self.blocks.read().unwrap().get(&hash).map(|r| Rlp::new(r).at(0).as_raw().to_vec()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user