Client refactoring (#7038)
* Improves `BestBlock` comment * Improves `TraceDB` comment * Improves `journaldb::Algorithm` comment. Probably the whole enum should be renamed to `Strategy` or something alike. * Comments some of the `Client`'s fields * Deglobs client imports * Fixes comments * Extracts `import_lock` to `Importer` struct * Extracts `verifier` to `Importer` struct * Extracts `block_queue` to `Importer` struct * Extracts `miner` to `Importer` struct * Extracts `ancient_verifier` to `Importer` struct * Extracts `rng` to `Importer` struct * Extracts `import_old_block` to `Importer` struct * Adds `Nonce` trait * Adds `Balance` trait * Adds `ChainInfo` trait * Fixes imports for tests using `chain_info` method * Adds `BlockInfo` trait * Adds more `ChainInfo` imports * Adds `BlockInfo` imports * Adds `ReopenBlock` trait * Adds `PrepareOpenBlock` trait * Fixes import in tests * Adds `CallContract` trait * Fixes imports in tests using `call_contract` method * Adds `TransactionInfo` trait * Adds `RegistryInfo` trait * Fixes imports in tests using `registry_address` method * Adds `ScheduleInfo` trait * Adds `ImportSealedBlock` trait * Fixes imports in test using `import_sealed_block` method * Adds `BroadcastProposalBlock` trait * Migrates `Miner` to static dispatch * Fixes tests * Moves `calculate_enacted_retracted` to `Importer` * Moves import-related methods to `Importer` * Removes redundant `import_old_block` wrapper * Extracts `import_block*` into separate trait * Fixes tests * Handles `Pending` in `LightFetch` * Handles `Pending` in filters * Handles `Pending` in `ParityClient` * Handles `Pending` in `EthClient` * Removes `BlockId::Pending`, partly refactors dependent code * Adds `StateInfo` trait * Exports `StateOrBlock` and `BlockChain` types from `client` module * Refactors `balance` RPC using generic API * Refactors `storage_at` RPC using generic API * Makes `MinerService::pending_state`'s return type dynamic * Adds `StateOrBlock` and `BlockChain` types * Adds impl of `client::BlockChain` for `Client` * Exports `StateInfo` trait from `client` module * Missing `self` use To be fixed up to "Adds impl of `client::BlockChain` for `Client`" * Adds `number_to_id` and refactors dependent RPC methods * Refactors `code_at` using generic API * Adds `StateClient` trait * Refactors RPC to use `StateClient` trait * Reverts `client::BlockChain` trait stuff, refactors methods to accept `StateOrBlock` * Refactors TestClient * Adds helper function `block_number_to_id` * Uses `block_number_to_id` instead of local function * Handles `Pending` in `list_accounts` and `list_storage_keys` * Attempt to use associated types for state instead of trait objects * Simplifies `state_at_beginning` * Extracts `call` and `call_many` into separate trait * Refactors `build_last_hashes` to accept reference * Exports `Call` type from the module * Refactors `call` and `call_many` to accept state and header * Exports `state_at` in `StateClient` * Exports `pending_block_header` from `MinerService` * Refactors RPC `call` method using new API * Adds missing parentheses * Refactors `parity::call` to use new call API * Update .gitlab-ci.yml fix gitlab lint * Fixes error handling * Refactors `traces::call` and `call_many` to use new call API * Refactors `call_contract` * Refactors `block_header` * Refactors internal RPC method `block` * Moves `estimate_gas` to `Call` trait, refactors parameters * Refactors `estimate_gas` in RPC * Refactors `uncle` * Refactors RPC `transaction` * Covers missing branches * Makes it all compile, fixes compiler grumbles * Adds casts in `blockchain` module * Fixes `PendingBlock` tests, work on `MinerService` * Adds test stubs for StateClient and EngineInfo * Makes `state_db` public * Adds missing impls for `TestBlockChainClient` * Adds trait documentation * Adds missing docs to the `state_db` module * Fixes trivial compilation errors * Moves `code_hash` method to a `BlockInfo` trait * Refactors `Verifier` to be generic over client * Refactors `TransactionFilter` to be generic over client * Refactors `Miner` and `Client` to reflect changes in verifier and txfilter API * Moves `ServiceTransactionChecker` back to `ethcore` * Fixes trait bounds in `Miner` API * Fixes `Client` * Fixes lifetime bound in `FullFamilyParams` * Adds comments to `FullFamilyParams` * Fixes imports in `ethcore` * Fixes BlockNumber handling in `code_at` and `replay_block_transactions` * fix compile issues * First step to redundant trait merge * Fixes compilation error in RPC tests * Adds mock `State` as a stub for `TestClient` * Handles `StateOrBlock::State` in `TestBlockChainClient::balance` * Fixes `transaction_count` RPC * Fixes `transaction_count` * Moves `service_transaction.json` to the `contracts` subfolder * Fixes compilation errors in tests * Refactors client to use `AccountData` * Refactors client to use `BlockChain` * Refactors miner to use aggregate traits * Adds `SealedBlockImporter` trait * Refactors miner to use `SealedBlockImporter` trait * Removes unused imports * Simplifies `RegistryInfo::registry_address` * Fixes indentation * Removes commented out trait bound
This commit is contained in:
committed by
Marek Kotewicz
parent
81b52c7336
commit
9d7d6f7108
File diff suppressed because it is too large
Load Diff
@@ -30,9 +30,12 @@ pub use self::error::Error;
|
||||
pub use self::evm_test_client::{EvmTestClient, EvmTestError, TransactResult};
|
||||
pub use self::test_client::{TestBlockChainClient, EachBlockWith};
|
||||
pub use self::chain_notify::ChainNotify;
|
||||
pub use self::traits::{BlockChainClient, MiningBlockChainClient, EngineClient};
|
||||
|
||||
pub use self::traits::ProvingBlockChainClient;
|
||||
pub use self::traits::{
|
||||
Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, PrepareOpenBlock, CallContract, TransactionInfo, RegistryInfo, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock,
|
||||
StateOrBlock, StateClient, Call, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter
|
||||
};
|
||||
pub use state::StateInfo;
|
||||
pub use self::traits::{BlockChainClient, MiningBlockChainClient, EngineClient, ProvingBlockChainClient};
|
||||
|
||||
pub use types::ids::*;
|
||||
pub use types::trace_filter::Filter as TraceFilter;
|
||||
|
||||
@@ -34,9 +34,11 @@ use ethkey::{Generator, Random};
|
||||
use transaction::{self, Transaction, LocalizedTransaction, PendingTransaction, SignedTransaction, Action};
|
||||
use blockchain::{TreeRoute, BlockReceipts};
|
||||
use client::{
|
||||
BlockChainClient, MiningBlockChainClient, BlockChainInfo, BlockStatus, BlockId,
|
||||
Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, CallContract, TransactionInfo, RegistryInfo,
|
||||
PrepareOpenBlock, BlockChainClient, MiningBlockChainClient, BlockChainInfo, BlockStatus, BlockId,
|
||||
TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics, BlockImportError,
|
||||
ProvingBlockChainClient,
|
||||
ProvingBlockChainClient, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock,
|
||||
Call, StateClient, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter
|
||||
};
|
||||
use db::{NUM_COLUMNS, COL_STATE};
|
||||
use header::{Header as BlockHeader, BlockNumber};
|
||||
@@ -59,7 +61,11 @@ use executive::Executed;
|
||||
use error::CallError;
|
||||
use trace::LocalizedTrace;
|
||||
use state_db::StateDB;
|
||||
use header::Header;
|
||||
use encoded;
|
||||
use engines::EthEngine;
|
||||
use trie;
|
||||
use state::StateInfo;
|
||||
|
||||
/// Test client.
|
||||
pub struct TestBlockChainClient {
|
||||
@@ -316,7 +322,7 @@ impl TestBlockChainClient {
|
||||
BlockId::Hash(hash) => Some(hash),
|
||||
BlockId::Number(n) => self.numbers.read().get(&(n as usize)).cloned(),
|
||||
BlockId::Earliest => self.numbers.read().get(&0).cloned(),
|
||||
BlockId::Latest | BlockId::Pending => self.numbers.read().get(&(self.numbers.read().len() - 1)).cloned()
|
||||
BlockId::Latest => self.numbers.read().get(&(self.numbers.read().len() - 1)).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,13 +363,13 @@ pub fn get_temp_state_db() -> StateDB {
|
||||
StateDB::new(journal_db, 1024 * 1024)
|
||||
}
|
||||
|
||||
impl MiningBlockChainClient for TestBlockChainClient {
|
||||
fn as_block_chain_client(&self) -> &BlockChainClient { self }
|
||||
|
||||
fn latest_schedule(&self) -> Schedule {
|
||||
Schedule::new_post_eip150(24576, true, true, true)
|
||||
impl ReopenBlock for TestBlockChainClient {
|
||||
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock {
|
||||
block.reopen(&*self.spec.engine)
|
||||
}
|
||||
}
|
||||
|
||||
impl PrepareOpenBlock for TestBlockChainClient {
|
||||
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
|
||||
let engine = &*self.spec.engine;
|
||||
let genesis_header = self.spec.genesis_header();
|
||||
@@ -386,39 +392,221 @@ impl MiningBlockChainClient for TestBlockChainClient {
|
||||
open_block.set_timestamp(*self.latest_block_timestamp.read());
|
||||
open_block
|
||||
}
|
||||
}
|
||||
|
||||
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock {
|
||||
block.reopen(&*self.spec.engine)
|
||||
}
|
||||
|
||||
fn vm_factory(&self) -> &VmFactory {
|
||||
&self.vm_factory
|
||||
impl ScheduleInfo for TestBlockChainClient {
|
||||
fn latest_schedule(&self) -> Schedule {
|
||||
Schedule::new_post_eip150(24576, true, true, true)
|
||||
}
|
||||
}
|
||||
|
||||
impl ImportSealedBlock for TestBlockChainClient {
|
||||
fn import_sealed_block(&self, _block: SealedBlock) -> ImportResult {
|
||||
Ok(H256::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockProducer for TestBlockChainClient {}
|
||||
|
||||
impl BroadcastProposalBlock for TestBlockChainClient {
|
||||
fn broadcast_proposal_block(&self, _block: SealedBlock) {}
|
||||
}
|
||||
|
||||
impl BlockChainClient for TestBlockChainClient {
|
||||
fn call(&self, _t: &SignedTransaction, _analytics: CallAnalytics, _block: BlockId) -> Result<Executed, CallError> {
|
||||
impl SealedBlockImporter for TestBlockChainClient {}
|
||||
|
||||
impl MiningBlockChainClient for TestBlockChainClient {
|
||||
fn vm_factory(&self) -> &VmFactory {
|
||||
&self.vm_factory
|
||||
}
|
||||
}
|
||||
|
||||
impl Nonce for TestBlockChainClient {
|
||||
fn nonce(&self, address: &Address, id: BlockId) -> Option<U256> {
|
||||
match id {
|
||||
BlockId::Latest => Some(self.nonces.read().get(address).cloned().unwrap_or(self.spec.params().account_start_nonce)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn latest_nonce(&self, address: &Address) -> U256 {
|
||||
self.nonce(address, BlockId::Latest).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Balance for TestBlockChainClient {
|
||||
fn balance(&self, address: &Address, state: StateOrBlock) -> Option<U256> {
|
||||
match state {
|
||||
StateOrBlock::Block(BlockId::Latest) | StateOrBlock::State(_) => Some(self.balances.read().get(address).cloned().unwrap_or_else(U256::zero)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn latest_balance(&self, address: &Address) -> U256 {
|
||||
self.balance(address, BlockId::Latest.into()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl AccountData for TestBlockChainClient {}
|
||||
|
||||
impl ChainInfo for TestBlockChainClient {
|
||||
fn chain_info(&self) -> BlockChainInfo {
|
||||
let number = self.blocks.read().len() as BlockNumber - 1;
|
||||
BlockChainInfo {
|
||||
total_difficulty: *self.difficulty.read(),
|
||||
pending_total_difficulty: *self.difficulty.read(),
|
||||
genesis_hash: self.genesis_hash.clone(),
|
||||
best_block_hash: self.last_hash.read().clone(),
|
||||
best_block_number: number,
|
||||
best_block_timestamp: number,
|
||||
first_block_hash: self.first_block.read().as_ref().map(|x| x.0),
|
||||
first_block_number: self.first_block.read().as_ref().map(|x| x.1),
|
||||
ancient_block_hash: self.ancient_block.read().as_ref().map(|x| x.0),
|
||||
ancient_block_number: self.ancient_block.read().as_ref().map(|x| x.1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockInfo for TestBlockChainClient {
|
||||
fn block_header(&self, id: BlockId) -> Option<encoded::Header> {
|
||||
self.block_hash(id)
|
||||
.and_then(|hash| self.blocks.read().get(&hash).map(|r| Rlp::new(r).at(0).as_raw().to_vec()))
|
||||
.map(encoded::Header::new)
|
||||
}
|
||||
|
||||
fn best_block_header(&self) -> encoded::Header {
|
||||
self.block_header(BlockId::Hash(self.chain_info().best_block_hash))
|
||||
.expect("Best block always has header.")
|
||||
}
|
||||
|
||||
fn block(&self, id: BlockId) -> Option<encoded::Block> {
|
||||
self.block_hash(id)
|
||||
.and_then(|hash| self.blocks.read().get(&hash).cloned())
|
||||
.map(encoded::Block::new)
|
||||
}
|
||||
|
||||
fn code_hash(&self, address: &Address, id: BlockId) -> Option<H256> {
|
||||
match id {
|
||||
BlockId::Latest => self.code.read().get(address).map(|c| keccak(&c)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CallContract for TestBlockChainClient {
|
||||
fn call_contract(&self, _id: BlockId, _address: Address, _data: Bytes) -> Result<Bytes, String> { Ok(vec![]) }
|
||||
}
|
||||
|
||||
impl TransactionInfo for TestBlockChainClient {
|
||||
fn transaction_block(&self, _id: TransactionId) -> Option<H256> {
|
||||
None // Simple default.
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockChain for TestBlockChainClient {}
|
||||
|
||||
impl RegistryInfo for TestBlockChainClient {
|
||||
fn registry_address(&self, _name: String, _block: BlockId) -> Option<Address> { None }
|
||||
}
|
||||
|
||||
impl ImportBlock for TestBlockChainClient {
|
||||
fn import_block(&self, b: Bytes) -> Result<H256, BlockImportError> {
|
||||
let header = Rlp::new(&b).val_at::<BlockHeader>(0);
|
||||
let h = header.hash();
|
||||
let number: usize = header.number() as usize;
|
||||
if number > self.blocks.read().len() {
|
||||
panic!("Unexpected block number. Expected {}, got {}", self.blocks.read().len(), number);
|
||||
}
|
||||
if number > 0 {
|
||||
match self.blocks.read().get(header.parent_hash()) {
|
||||
Some(parent) => {
|
||||
let parent = Rlp::new(parent).val_at::<BlockHeader>(0);
|
||||
if parent.number() != (header.number() - 1) {
|
||||
panic!("Unexpected block parent");
|
||||
}
|
||||
},
|
||||
None => {
|
||||
panic!("Unknown block parent {:?} for block {}", header.parent_hash(), number);
|
||||
}
|
||||
}
|
||||
}
|
||||
let len = self.numbers.read().len();
|
||||
if number == len {
|
||||
{
|
||||
let mut difficulty = self.difficulty.write();
|
||||
*difficulty = *difficulty + header.difficulty().clone();
|
||||
}
|
||||
mem::replace(&mut *self.last_hash.write(), h.clone());
|
||||
self.blocks.write().insert(h.clone(), b);
|
||||
self.numbers.write().insert(number, h.clone());
|
||||
let mut parent_hash = header.parent_hash().clone();
|
||||
if number > 0 {
|
||||
let mut n = number - 1;
|
||||
while n > 0 && self.numbers.read()[&n] != parent_hash {
|
||||
*self.numbers.write().get_mut(&n).unwrap() = parent_hash.clone();
|
||||
n -= 1;
|
||||
parent_hash = Rlp::new(&self.blocks.read()[&parent_hash]).val_at::<BlockHeader>(0).parent_hash().clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
self.blocks.write().insert(h.clone(), b.to_vec());
|
||||
}
|
||||
Ok(h)
|
||||
}
|
||||
|
||||
fn import_block_with_receipts(&self, b: Bytes, _r: Bytes) -> Result<H256, BlockImportError> {
|
||||
self.import_block(b)
|
||||
}
|
||||
}
|
||||
|
||||
impl Call for TestBlockChainClient {
|
||||
// State will not be used by test client anyway, since all methods that accept state are mocked
|
||||
type State = ();
|
||||
|
||||
fn call(&self, _t: &SignedTransaction, _analytics: CallAnalytics, _state: &mut Self::State, _header: &Header) -> Result<Executed, CallError> {
|
||||
self.execution_result.read().clone().unwrap()
|
||||
}
|
||||
|
||||
fn call_many(&self, txs: &[(SignedTransaction, CallAnalytics)], block: BlockId) -> Result<Vec<Executed>, CallError> {
|
||||
fn call_many(&self, txs: &[(SignedTransaction, CallAnalytics)], state: &mut Self::State, header: &Header) -> Result<Vec<Executed>, CallError> {
|
||||
let mut res = Vec::with_capacity(txs.len());
|
||||
for &(ref tx, analytics) in txs {
|
||||
res.push(self.call(tx, analytics, block)?);
|
||||
res.push(self.call(tx, analytics, state, header)?);
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn estimate_gas(&self, _t: &SignedTransaction, _block: BlockId) -> Result<U256, CallError> {
|
||||
fn estimate_gas(&self, _t: &SignedTransaction, _state: &Self::State, _header: &Header) -> Result<U256, CallError> {
|
||||
Ok(21000.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl StateInfo for () {
|
||||
fn nonce(&self, _address: &Address) -> trie::Result<U256> { unimplemented!() }
|
||||
fn balance(&self, _address: &Address) -> trie::Result<U256> { unimplemented!() }
|
||||
fn storage_at(&self, _address: &Address, _key: &H256) -> trie::Result<H256> { unimplemented!() }
|
||||
fn code(&self, _address: &Address) -> trie::Result<Option<Arc<Bytes>>> { unimplemented!() }
|
||||
}
|
||||
|
||||
impl StateClient for TestBlockChainClient {
|
||||
// State will not be used by test client anyway, since all methods that accept state are mocked
|
||||
type State = ();
|
||||
|
||||
fn latest_state(&self) -> Self::State {
|
||||
()
|
||||
}
|
||||
|
||||
fn state_at(&self, _id: BlockId) -> Option<Self::State> {
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
impl EngineInfo for TestBlockChainClient {
|
||||
fn engine(&self) -> &EthEngine {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockChainClient for TestBlockChainClient {
|
||||
fn replay(&self, _id: TransactionId, _analytics: CallAnalytics) -> Result<Executed, CallError> {
|
||||
self.execution_result.read().clone().unwrap()
|
||||
}
|
||||
@@ -435,49 +623,20 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
Self::block_hash(self, id)
|
||||
}
|
||||
|
||||
fn nonce(&self, address: &Address, id: BlockId) -> Option<U256> {
|
||||
match id {
|
||||
BlockId::Latest | BlockId::Pending => Some(self.nonces.read().get(address).cloned().unwrap_or(self.spec.params().account_start_nonce)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn storage_root(&self, _address: &Address, _id: BlockId) -> Option<H256> {
|
||||
None
|
||||
}
|
||||
|
||||
fn latest_nonce(&self, address: &Address) -> U256 {
|
||||
self.nonce(address, BlockId::Latest).unwrap()
|
||||
}
|
||||
|
||||
fn code(&self, address: &Address, id: BlockId) -> Option<Option<Bytes>> {
|
||||
match id {
|
||||
BlockId::Latest | BlockId::Pending => Some(self.code.read().get(address).cloned()),
|
||||
fn code(&self, address: &Address, state: StateOrBlock) -> Option<Option<Bytes>> {
|
||||
match state {
|
||||
StateOrBlock::Block(BlockId::Latest) => Some(self.code.read().get(address).cloned()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn code_hash(&self, address: &Address, id: BlockId) -> Option<H256> {
|
||||
match id {
|
||||
BlockId::Latest | BlockId::Pending => self.code.read().get(address).map(|c| keccak(&c)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn balance(&self, address: &Address, id: BlockId) -> Option<U256> {
|
||||
match id {
|
||||
BlockId::Latest | BlockId::Pending => Some(self.balances.read().get(address).cloned().unwrap_or_else(U256::zero)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn latest_balance(&self, address: &Address) -> U256 {
|
||||
self.balance(address, BlockId::Latest).unwrap()
|
||||
}
|
||||
|
||||
fn storage_at(&self, address: &Address, position: &H256, id: BlockId) -> Option<H256> {
|
||||
match id {
|
||||
BlockId::Latest | BlockId::Pending => Some(self.storage.read().get(&(address.clone(), position.clone())).cloned().unwrap_or_else(H256::new)),
|
||||
fn storage_at(&self, address: &Address, position: &H256, state: StateOrBlock) -> Option<H256> {
|
||||
match state {
|
||||
StateOrBlock::Block(BlockId::Latest) => Some(self.storage.read().get(&(address.clone(), position.clone())).cloned().unwrap_or_else(H256::new)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -493,10 +652,6 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
None // Simple default.
|
||||
}
|
||||
|
||||
fn transaction_block(&self, _id: TransactionId) -> Option<H256> {
|
||||
None // Simple default.
|
||||
}
|
||||
|
||||
fn uncle(&self, _id: UncleId) -> Option<encoded::Header> {
|
||||
None // Simple default.
|
||||
}
|
||||
@@ -522,17 +677,6 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn best_block_header(&self) -> encoded::Header {
|
||||
self.block_header(BlockId::Hash(self.chain_info().best_block_hash))
|
||||
.expect("Best block always has header.")
|
||||
}
|
||||
|
||||
fn block_header(&self, id: BlockId) -> Option<encoded::Header> {
|
||||
self.block_hash(id)
|
||||
.and_then(|hash| self.blocks.read().get(&hash).map(|r| Rlp::new(r).at(0).as_raw().to_vec()))
|
||||
.map(encoded::Header::new)
|
||||
}
|
||||
|
||||
fn block_number(&self, _id: BlockId) -> Option<BlockNumber> {
|
||||
unimplemented!()
|
||||
}
|
||||
@@ -546,12 +690,6 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
}))
|
||||
}
|
||||
|
||||
fn block(&self, id: BlockId) -> Option<encoded::Block> {
|
||||
self.block_hash(id)
|
||||
.and_then(|hash| self.blocks.read().get(&hash).cloned())
|
||||
.map(encoded::Block::new)
|
||||
}
|
||||
|
||||
fn block_extra_info(&self, id: BlockId) -> Option<BTreeMap<String, String>> {
|
||||
self.block(id)
|
||||
.map(|block| block.view().header())
|
||||
@@ -564,7 +702,6 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
BlockId::Number(number) if (number as usize) < self.blocks.read().len() => BlockStatus::InChain,
|
||||
BlockId::Hash(ref hash) if self.blocks.read().get(hash).is_some() => BlockStatus::InChain,
|
||||
BlockId::Latest | BlockId::Earliest => BlockStatus::InChain,
|
||||
BlockId::Pending => BlockStatus::Pending,
|
||||
_ => BlockStatus::Unknown,
|
||||
}
|
||||
}
|
||||
@@ -628,55 +765,6 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
None
|
||||
}
|
||||
|
||||
fn import_block(&self, b: Bytes) -> Result<H256, BlockImportError> {
|
||||
let header = Rlp::new(&b).val_at::<BlockHeader>(0);
|
||||
let h = header.hash();
|
||||
let number: usize = header.number() as usize;
|
||||
if number > self.blocks.read().len() {
|
||||
panic!("Unexpected block number. Expected {}, got {}", self.blocks.read().len(), number);
|
||||
}
|
||||
if number > 0 {
|
||||
match self.blocks.read().get(header.parent_hash()) {
|
||||
Some(parent) => {
|
||||
let parent = Rlp::new(parent).val_at::<BlockHeader>(0);
|
||||
if parent.number() != (header.number() - 1) {
|
||||
panic!("Unexpected block parent");
|
||||
}
|
||||
},
|
||||
None => {
|
||||
panic!("Unknown block parent {:?} for block {}", header.parent_hash(), number);
|
||||
}
|
||||
}
|
||||
}
|
||||
let len = self.numbers.read().len();
|
||||
if number == len {
|
||||
{
|
||||
let mut difficulty = self.difficulty.write();
|
||||
*difficulty = *difficulty + header.difficulty().clone();
|
||||
}
|
||||
mem::replace(&mut *self.last_hash.write(), h.clone());
|
||||
self.blocks.write().insert(h.clone(), b);
|
||||
self.numbers.write().insert(number, h.clone());
|
||||
let mut parent_hash = header.parent_hash().clone();
|
||||
if number > 0 {
|
||||
let mut n = number - 1;
|
||||
while n > 0 && self.numbers.read()[&n] != parent_hash {
|
||||
*self.numbers.write().get_mut(&n).unwrap() = parent_hash.clone();
|
||||
n -= 1;
|
||||
parent_hash = Rlp::new(&self.blocks.read()[&parent_hash]).val_at::<BlockHeader>(0).parent_hash().clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
self.blocks.write().insert(h.clone(), b.to_vec());
|
||||
}
|
||||
Ok(h)
|
||||
}
|
||||
|
||||
fn import_block_with_receipts(&self, b: Bytes, _r: Bytes) -> Result<H256, BlockImportError> {
|
||||
self.import_block(b)
|
||||
}
|
||||
|
||||
fn queue_info(&self) -> QueueInfo {
|
||||
QueueInfo {
|
||||
verified_queue_size: self.queue_size.load(AtomicOrder::Relaxed),
|
||||
@@ -695,22 +783,6 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn chain_info(&self) -> BlockChainInfo {
|
||||
let number = self.blocks.read().len() as BlockNumber - 1;
|
||||
BlockChainInfo {
|
||||
total_difficulty: *self.difficulty.read(),
|
||||
pending_total_difficulty: *self.difficulty.read(),
|
||||
genesis_hash: self.genesis_hash.clone(),
|
||||
best_block_hash: self.last_hash.read().clone(),
|
||||
best_block_number: number,
|
||||
best_block_timestamp: number,
|
||||
first_block_hash: self.first_block.read().as_ref().map(|x| x.0),
|
||||
first_block_number: self.first_block.read().as_ref().map(|x| x.1),
|
||||
ancient_block_hash: self.ancient_block.read().as_ref().map(|x| x.0),
|
||||
ancient_block_number: self.ancient_block.read().as_ref().map(|x| x.1)
|
||||
}
|
||||
}
|
||||
|
||||
fn filter_traces(&self, _filter: TraceFilter) -> Option<Vec<LocalizedTrace>> {
|
||||
self.traces.read().clone()
|
||||
}
|
||||
@@ -762,8 +834,6 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
}
|
||||
}
|
||||
|
||||
fn call_contract(&self, _id: BlockId, _address: Address, _data: Bytes) -> Result<Bytes, String> { Ok(vec![]) }
|
||||
|
||||
fn transact_contract(&self, address: Address, data: Bytes) -> Result<transaction::ImportResult, EthcoreError> {
|
||||
let transaction = Transaction {
|
||||
nonce: self.latest_nonce(&self.miner.author()),
|
||||
@@ -781,8 +851,6 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
|
||||
fn registrar_address(&self) -> Option<Address> { None }
|
||||
|
||||
fn registry_address(&self, _name: String, _block: BlockId) -> Option<Address> { None }
|
||||
|
||||
fn eip86_transition(&self) -> u64 { u64::max_value() }
|
||||
}
|
||||
|
||||
@@ -821,10 +889,6 @@ impl super::traits::EngineClient for TestBlockChainClient {
|
||||
None
|
||||
}
|
||||
|
||||
fn chain_info(&self) -> BlockChainInfo {
|
||||
BlockChainClient::chain_info(self)
|
||||
}
|
||||
|
||||
fn as_full_client(&self) -> Option<&BlockChainClient> { Some(self) }
|
||||
|
||||
fn block_number(&self, id: BlockId) -> Option<BlockNumber> {
|
||||
|
||||
@@ -32,6 +32,9 @@ use receipt::LocalizedReceipt;
|
||||
use trace::LocalizedTrace;
|
||||
use transaction::{LocalizedTransaction, PendingTransaction, SignedTransaction, ImportResult as TransactionImportResult};
|
||||
use verification::queue::QueueInfo as BlockQueueInfo;
|
||||
use state::StateInfo;
|
||||
use header::Header;
|
||||
use engines::EthEngine;
|
||||
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use bytes::Bytes;
|
||||
@@ -46,80 +49,198 @@ use types::block_status::BlockStatus;
|
||||
use types::mode::Mode;
|
||||
use types::pruning_info::PruningInfo;
|
||||
|
||||
/// Blockchain database client. Owns and manages a blockchain and a block queue.
|
||||
pub trait BlockChainClient : Sync + Send {
|
||||
/// State information to be used during client query
|
||||
pub enum StateOrBlock {
|
||||
/// State to be used, may be pending
|
||||
State(Box<StateInfo>),
|
||||
|
||||
/// Get raw block header data by block id.
|
||||
fn block_header(&self, id: BlockId) -> Option<encoded::Header>;
|
||||
/// Id of an existing block from a chain to get state from
|
||||
Block(BlockId)
|
||||
}
|
||||
|
||||
/// Look up the block number for the given block ID.
|
||||
fn block_number(&self, id: BlockId) -> Option<BlockNumber>;
|
||||
impl<S: StateInfo + 'static> From<S> for StateOrBlock {
|
||||
fn from(info: S) -> StateOrBlock {
|
||||
StateOrBlock::State(Box::new(info) as Box<_>)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get raw block body data by block id.
|
||||
/// Block body is an RLP list of two items: uncles and transactions.
|
||||
fn block_body(&self, id: BlockId) -> Option<encoded::Body>;
|
||||
impl From<Box<StateInfo>> for StateOrBlock {
|
||||
fn from(info: Box<StateInfo>) -> StateOrBlock {
|
||||
StateOrBlock::State(info)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get raw block data by block header hash.
|
||||
fn block(&self, id: BlockId) -> Option<encoded::Block>;
|
||||
|
||||
/// Get block status by block header hash.
|
||||
fn block_status(&self, id: BlockId) -> BlockStatus;
|
||||
|
||||
/// Get block total difficulty.
|
||||
fn block_total_difficulty(&self, id: BlockId) -> Option<U256>;
|
||||
impl From<BlockId> for StateOrBlock {
|
||||
fn from(id: BlockId) -> StateOrBlock {
|
||||
StateOrBlock::Block(id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides `nonce` and `latest_nonce` methods
|
||||
pub trait Nonce {
|
||||
/// Attempt to get address nonce at given block.
|
||||
/// May not fail on BlockId::Latest.
|
||||
fn nonce(&self, address: &Address, id: BlockId) -> Option<U256>;
|
||||
|
||||
/// Attempt to get address storage root at given block.
|
||||
/// May not fail on BlockId::Latest.
|
||||
fn storage_root(&self, address: &Address, id: BlockId) -> Option<H256>;
|
||||
|
||||
/// Get address nonce at the latest block's state.
|
||||
fn latest_nonce(&self, address: &Address) -> U256 {
|
||||
self.nonce(address, BlockId::Latest)
|
||||
.expect("nonce will return Some when given BlockId::Latest. nonce was given BlockId::Latest. \
|
||||
Therefore nonce has returned Some; qed")
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides `balance` and `latest_balance` methods
|
||||
pub trait Balance {
|
||||
/// Get address balance at the given block's state.
|
||||
///
|
||||
/// May not return None if given BlockId::Latest.
|
||||
/// Returns None if and only if the block's root hash has been pruned from the DB.
|
||||
fn balance(&self, address: &Address, state: StateOrBlock) -> Option<U256>;
|
||||
|
||||
/// Get address balance at the latest block's state.
|
||||
fn latest_balance(&self, address: &Address) -> U256 {
|
||||
self.balance(address, BlockId::Latest.into())
|
||||
.expect("balance will return Some if given BlockId::Latest. balance was given BlockId::Latest \
|
||||
Therefore balance has returned Some; qed")
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides methods to access account info
|
||||
pub trait AccountData: Nonce + Balance {}
|
||||
|
||||
/// Provides `chain_info` method
|
||||
pub trait ChainInfo {
|
||||
/// Get blockchain information.
|
||||
fn chain_info(&self) -> BlockChainInfo;
|
||||
}
|
||||
|
||||
/// Provides various information on a block by it's ID
|
||||
pub trait BlockInfo {
|
||||
/// Get raw block header data by block id.
|
||||
fn block_header(&self, id: BlockId) -> Option<encoded::Header>;
|
||||
|
||||
/// Get the best block header.
|
||||
fn best_block_header(&self) -> encoded::Header;
|
||||
|
||||
/// Get raw block data by block header hash.
|
||||
fn block(&self, id: BlockId) -> Option<encoded::Block>;
|
||||
|
||||
/// Get address code hash at given block's state.
|
||||
fn code_hash(&self, address: &Address, id: BlockId) -> Option<H256>;
|
||||
}
|
||||
|
||||
/// Provides various information on a transaction by it's ID
|
||||
pub trait TransactionInfo {
|
||||
/// Get the hash of block that contains the transaction, if any.
|
||||
fn transaction_block(&self, id: TransactionId) -> Option<H256>;
|
||||
}
|
||||
|
||||
/// Provides methods to access chain state
|
||||
pub trait StateClient {
|
||||
/// Type representing chain state
|
||||
type State: StateInfo;
|
||||
|
||||
/// Get a copy of the best block's state.
|
||||
fn latest_state(&self) -> Self::State;
|
||||
|
||||
/// Attempt to get a copy of a specific block's final state.
|
||||
///
|
||||
/// This will not fail if given BlockId::Latest.
|
||||
/// Otherwise, this can fail (but may not) if the DB prunes state or the block
|
||||
/// is unknown.
|
||||
fn state_at(&self, id: BlockId) -> Option<Self::State>;
|
||||
}
|
||||
|
||||
/// Provides various blockchain information, like block header, chain state etc.
|
||||
pub trait BlockChain: ChainInfo + BlockInfo + TransactionInfo {}
|
||||
|
||||
/// Provides information on a blockchain service and it's registry
|
||||
pub trait RegistryInfo {
|
||||
/// Get the address of a particular blockchain service, if available.
|
||||
fn registry_address(&self, name: String, block: BlockId) -> Option<Address>;
|
||||
}
|
||||
|
||||
// FIXME Why these methods belong to BlockChainClient and not MiningBlockChainClient?
|
||||
/// Provides methods to import block into blockchain
|
||||
pub trait ImportBlock {
|
||||
/// Import a block into the blockchain.
|
||||
fn import_block(&self, bytes: Bytes) -> Result<H256, BlockImportError>;
|
||||
|
||||
/// Import a block with transaction receipts. Does no sealing and transaction validation.
|
||||
fn import_block_with_receipts(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result<H256, BlockImportError>;
|
||||
}
|
||||
|
||||
/// Provides `call_contract` method
|
||||
pub trait CallContract {
|
||||
/// Like `call`, but with various defaults. Designed to be used for calling contracts.
|
||||
fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String>;
|
||||
}
|
||||
|
||||
/// Provides `call` and `call_many` methods
|
||||
pub trait Call {
|
||||
/// Type representing chain state
|
||||
type State: StateInfo;
|
||||
|
||||
/// Makes a non-persistent transaction call.
|
||||
fn call(&self, tx: &SignedTransaction, analytics: CallAnalytics, state: &mut Self::State, header: &Header) -> Result<Executed, CallError>;
|
||||
|
||||
/// Makes multiple non-persistent but dependent transaction calls.
|
||||
/// Returns a vector of successes or a failure if any of the transaction fails.
|
||||
fn call_many(&self, txs: &[(SignedTransaction, CallAnalytics)], state: &mut Self::State, header: &Header) -> Result<Vec<Executed>, CallError>;
|
||||
|
||||
/// Estimates how much gas will be necessary for a call.
|
||||
fn estimate_gas(&self, t: &SignedTransaction, state: &Self::State, header: &Header) -> Result<U256, CallError>;
|
||||
}
|
||||
|
||||
/// Provides `engine` method
|
||||
pub trait EngineInfo {
|
||||
/// Get underlying engine object
|
||||
fn engine(&self) -> &EthEngine;
|
||||
}
|
||||
|
||||
/// Blockchain database client. Owns and manages a blockchain and a block queue.
|
||||
pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContract + RegistryInfo + ImportBlock {
|
||||
/// Look up the block number for the given block ID.
|
||||
fn block_number(&self, id: BlockId) -> Option<BlockNumber>;
|
||||
|
||||
/// Get raw block body data by block id.
|
||||
/// Block body is an RLP list of two items: uncles and transactions.
|
||||
fn block_body(&self, id: BlockId) -> Option<encoded::Body>;
|
||||
|
||||
/// Get block status by block header hash.
|
||||
fn block_status(&self, id: BlockId) -> BlockStatus;
|
||||
|
||||
/// Get block total difficulty.
|
||||
fn block_total_difficulty(&self, id: BlockId) -> Option<U256>;
|
||||
|
||||
/// Attempt to get address storage root at given block.
|
||||
/// May not fail on BlockId::Latest.
|
||||
fn storage_root(&self, address: &Address, id: BlockId) -> Option<H256>;
|
||||
|
||||
/// Get block hash.
|
||||
fn block_hash(&self, id: BlockId) -> Option<H256>;
|
||||
|
||||
/// Get address code at given block's state.
|
||||
fn code(&self, address: &Address, id: BlockId) -> Option<Option<Bytes>>;
|
||||
fn code(&self, address: &Address, state: StateOrBlock) -> Option<Option<Bytes>>;
|
||||
|
||||
/// Get address code at the latest block's state.
|
||||
fn latest_code(&self, address: &Address) -> Option<Bytes> {
|
||||
self.code(address, BlockId::Latest)
|
||||
self.code(address, BlockId::Latest.into())
|
||||
.expect("code will return Some if given BlockId::Latest; qed")
|
||||
}
|
||||
|
||||
/// Get address code hash at given block's state.
|
||||
fn code_hash(&self, address: &Address, id: BlockId) -> Option<H256>;
|
||||
|
||||
/// Get address balance at the given block's state.
|
||||
///
|
||||
/// May not return None if given BlockId::Latest.
|
||||
/// Returns None if and only if the block's root hash has been pruned from the DB.
|
||||
fn balance(&self, address: &Address, id: BlockId) -> Option<U256>;
|
||||
|
||||
/// Get address balance at the latest block's state.
|
||||
fn latest_balance(&self, address: &Address) -> U256 {
|
||||
self.balance(address, BlockId::Latest)
|
||||
.expect("balance will return Some if given BlockId::Latest. balance was given BlockId::Latest \
|
||||
Therefore balance has returned Some; qed")
|
||||
}
|
||||
|
||||
/// Get value of the storage at given position at the given block's state.
|
||||
///
|
||||
/// May not return None if given BlockId::Latest.
|
||||
/// Returns None if and only if the block's root hash has been pruned from the DB.
|
||||
fn storage_at(&self, address: &Address, position: &H256, id: BlockId) -> Option<H256>;
|
||||
fn storage_at(&self, address: &Address, position: &H256, state: StateOrBlock) -> Option<H256>;
|
||||
|
||||
/// Get value of the storage at given position at the latest block's state.
|
||||
fn latest_storage_at(&self, address: &Address, position: &H256) -> H256 {
|
||||
self.storage_at(address, position, BlockId::Latest)
|
||||
self.storage_at(address, position, BlockId::Latest.into())
|
||||
.expect("storage_at will return Some if given BlockId::Latest. storage_at was given BlockId::Latest. \
|
||||
Therefore storage_at has returned Some; qed")
|
||||
}
|
||||
@@ -135,9 +256,6 @@ pub trait BlockChainClient : Sync + Send {
|
||||
/// Get transaction with given hash.
|
||||
fn transaction(&self, id: TransactionId) -> Option<LocalizedTransaction>;
|
||||
|
||||
/// Get the hash of block that contains the transaction, if any.
|
||||
fn transaction_block(&self, id: TransactionId) -> Option<H256>;
|
||||
|
||||
/// Get uncle with given id.
|
||||
fn uncle(&self, id: UncleId) -> Option<encoded::Header>;
|
||||
|
||||
@@ -157,40 +275,18 @@ pub trait BlockChainClient : Sync + Send {
|
||||
/// Get raw block receipts data by block header hash.
|
||||
fn block_receipts(&self, hash: &H256) -> Option<Bytes>;
|
||||
|
||||
/// Import a block into the blockchain.
|
||||
fn import_block(&self, bytes: Bytes) -> Result<H256, BlockImportError>;
|
||||
|
||||
/// Import a block with transaction receipts. Does no sealing and transaction validation.
|
||||
fn import_block_with_receipts(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result<H256, BlockImportError>;
|
||||
|
||||
/// Get block queue information.
|
||||
fn queue_info(&self) -> BlockQueueInfo;
|
||||
|
||||
/// Clear block queue and abort all import activity.
|
||||
fn clear_queue(&self);
|
||||
|
||||
/// Get blockchain information.
|
||||
fn chain_info(&self) -> BlockChainInfo;
|
||||
|
||||
/// Get the registrar address, if it exists.
|
||||
fn additional_params(&self) -> BTreeMap<String, String>;
|
||||
|
||||
/// Get the best block header.
|
||||
fn best_block_header(&self) -> encoded::Header;
|
||||
|
||||
/// Returns logs matching given filter.
|
||||
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry>;
|
||||
|
||||
/// Makes a non-persistent transaction call.
|
||||
fn call(&self, tx: &SignedTransaction, analytics: CallAnalytics, block: BlockId) -> Result<Executed, CallError>;
|
||||
|
||||
/// Makes multiple non-persistent but dependent transaction calls.
|
||||
/// Returns a vector of successes or a failure if any of the transaction fails.
|
||||
fn call_many(&self, txs: &[(SignedTransaction, CallAnalytics)], block: BlockId) -> Result<Vec<Executed>, CallError>;
|
||||
|
||||
/// Estimates how much gas will be necessary for a call.
|
||||
fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result<U256, CallError>;
|
||||
|
||||
/// Replays a given transaction for inspection.
|
||||
fn replay(&self, t: TransactionId, analytics: CallAnalytics) -> Result<Executed, CallError>;
|
||||
|
||||
@@ -270,52 +366,64 @@ pub trait BlockChainClient : Sync + Send {
|
||||
/// Returns information about pruning/data availability.
|
||||
fn pruning_info(&self) -> PruningInfo;
|
||||
|
||||
/// Like `call`, but with various defaults. Designed to be used for calling contracts.
|
||||
fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result<Bytes, String>;
|
||||
|
||||
/// Import a transaction: used for misbehaviour reporting.
|
||||
fn transact_contract(&self, address: Address, data: Bytes) -> Result<TransactionImportResult, EthcoreError>;
|
||||
|
||||
/// Get the address of the registry itself.
|
||||
fn registrar_address(&self) -> Option<Address>;
|
||||
|
||||
/// Get the address of a particular blockchain service, if available.
|
||||
fn registry_address(&self, name: String, block: BlockId) -> Option<Address>;
|
||||
|
||||
/// Get the EIP-86 transition block number.
|
||||
fn eip86_transition(&self) -> u64;
|
||||
}
|
||||
|
||||
/// Extended client interface used for mining
|
||||
pub trait MiningBlockChainClient: BlockChainClient {
|
||||
/// Provides `reopen_block` method
|
||||
pub trait ReopenBlock {
|
||||
/// Reopens an OpenBlock and updates uncles.
|
||||
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock;
|
||||
}
|
||||
|
||||
/// Provides `prepare_open_block` method
|
||||
pub trait PrepareOpenBlock {
|
||||
/// Returns OpenBlock prepared for closing.
|
||||
fn prepare_open_block(&self,
|
||||
author: Address,
|
||||
gas_range_target: (U256, U256),
|
||||
extra_data: Bytes
|
||||
) -> OpenBlock;
|
||||
}
|
||||
|
||||
/// Reopens an OpenBlock and updates uncles.
|
||||
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock;
|
||||
|
||||
/// Returns EvmFactory.
|
||||
fn vm_factory(&self) -> &VmFactory;
|
||||
|
||||
/// Broadcast a block proposal.
|
||||
fn broadcast_proposal_block(&self, block: SealedBlock);
|
||||
|
||||
/// Import sealed block. Skips all verifications.
|
||||
fn import_sealed_block(&self, block: SealedBlock) -> ImportResult;
|
||||
/// Provides methods used for sealing new state
|
||||
pub trait BlockProducer: PrepareOpenBlock + ReopenBlock {}
|
||||
|
||||
/// Provides `latest_schedule` method
|
||||
pub trait ScheduleInfo {
|
||||
/// Returns latest schedule.
|
||||
fn latest_schedule(&self) -> Schedule;
|
||||
}
|
||||
|
||||
/// Returns base of this trait
|
||||
fn as_block_chain_client(&self) -> &BlockChainClient;
|
||||
///Provides `import_sealed_block` method
|
||||
pub trait ImportSealedBlock {
|
||||
/// Import sealed block. Skips all verifications.
|
||||
fn import_sealed_block(&self, block: SealedBlock) -> ImportResult;
|
||||
}
|
||||
|
||||
/// Provides `broadcast_proposal_block` method
|
||||
pub trait BroadcastProposalBlock {
|
||||
/// Broadcast a block proposal.
|
||||
fn broadcast_proposal_block(&self, block: SealedBlock);
|
||||
}
|
||||
|
||||
/// Provides methods to import sealed block and broadcast a block proposal
|
||||
pub trait SealedBlockImporter: ImportSealedBlock + BroadcastProposalBlock {}
|
||||
|
||||
/// Extended client interface used for mining
|
||||
pub trait MiningBlockChainClient: BlockChainClient + BlockProducer + ScheduleInfo + SealedBlockImporter {
|
||||
/// Returns EvmFactory.
|
||||
fn vm_factory(&self) -> &VmFactory;
|
||||
}
|
||||
|
||||
/// Client facilities used by internally sealing Engines.
|
||||
pub trait EngineClient: Sync + Send {
|
||||
pub trait EngineClient: Sync + Send + ChainInfo {
|
||||
/// Make a new block and seal it.
|
||||
fn update_sealing(&self);
|
||||
|
||||
@@ -332,9 +440,6 @@ pub trait EngineClient: Sync + Send {
|
||||
/// The block corresponding the the parent hash must be stored already.
|
||||
fn epoch_transition_for(&self, parent_hash: H256) -> Option<::engines::EpochTransition>;
|
||||
|
||||
/// Get block chain info.
|
||||
fn chain_info(&self) -> BlockChainInfo;
|
||||
|
||||
/// Attempt to cast the engine client to a full client.
|
||||
fn as_full_client(&self) -> Option<&BlockChainClient>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user