Generalize engine trait (#6591)
* move common forks and parameters to common params * port specs over to new format * fix RPC tests * parity-machine skeleton * remove block type * extract out ethereum-specific methods into EthereumMachine * beginning to integrate Machine into engines. dealing with stale transitions in Ethash * initial porting to machine * move block reward back into engine * abstract block reward logic * move last hash and DAO HF logic into machine * begin making engine function parameters generic * abstract epoch verifier and ethash block reward logic * instantiate special ethereummachine for ethash in spec * optional full verification in verify_block_family * re-instate tx_filter in a way that works for all engines * fix warnings * fix most tests, further generalize engine trait * uncomment nullengine, get ethcore tests compiling * fix warnings * update a bunch of specs * re-enable engine signer, validator set, and transition handler * migrate basic_authority engine * move last hashes into executedblock * port tendermint * make all ethcore tests pass * json-tests compilation * fix RPC tests: change in gas limit for new block changed PoW hash * fix minor grumbles * validate chainspecs * fix broken import * fix transaction verification for pre-homestead
This commit is contained in:
committed by
Gav Wood
parent
d8af9f4e7b
commit
bc167a211b
@@ -20,7 +20,8 @@ use std::sync::{Weak, Arc};
|
||||
|
||||
use ethcore::block_status::BlockStatus;
|
||||
use ethcore::client::{ClientReport, EnvInfo};
|
||||
use ethcore::engines::{epoch, Engine, EpochChange, EpochTransition, Proof, Unsure};
|
||||
use ethcore::engines::{epoch, EthEngine, EpochChange, EpochTransition, Proof};
|
||||
use ethcore::machine::EthereumMachine;
|
||||
use ethcore::error::BlockImportError;
|
||||
use ethcore::ids::BlockId;
|
||||
use ethcore::header::{BlockNumber, Header};
|
||||
@@ -117,7 +118,7 @@ pub trait LightChainClient: Send + Sync {
|
||||
fn env_info(&self, id: BlockId) -> Option<EnvInfo>;
|
||||
|
||||
/// Get a handle to the consensus engine.
|
||||
fn engine(&self) -> &Arc<Engine>;
|
||||
fn engine(&self) -> &Arc<EthEngine>;
|
||||
|
||||
/// Query whether a block is known.
|
||||
fn is_known(&self, hash: &H256) -> bool;
|
||||
@@ -165,7 +166,7 @@ impl<T: LightChainClient> AsLightClient for T {
|
||||
/// Light client implementation.
|
||||
pub struct Client<T> {
|
||||
queue: HeaderQueue,
|
||||
engine: Arc<Engine>,
|
||||
engine: Arc<EthEngine>,
|
||||
chain: HeaderChain,
|
||||
report: RwLock<ClientReport>,
|
||||
import_lock: Mutex<()>,
|
||||
@@ -381,7 +382,7 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
}
|
||||
|
||||
/// Get a handle to the verification engine.
|
||||
pub fn engine(&self) -> &Arc<Engine> {
|
||||
pub fn engine(&self) -> &Arc<EthEngine> {
|
||||
&self.engine
|
||||
}
|
||||
|
||||
@@ -444,7 +445,7 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
};
|
||||
|
||||
// Verify Block Family
|
||||
let verify_family_result = self.engine.verify_block_family(&verified_header, &parent_header.decode(), None);
|
||||
let verify_family_result = self.engine.verify_block_family(&verified_header, &parent_header.decode());
|
||||
if let Err(e) = verify_family_result {
|
||||
warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}",
|
||||
verified_header.number(), verified_header.hash(), e);
|
||||
@@ -453,7 +454,7 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
};
|
||||
|
||||
// "external" verification.
|
||||
let verify_external_result = self.engine.verify_block_external(&verified_header, None);
|
||||
let verify_external_result = self.engine.verify_block_external(&verified_header);
|
||||
if let Err(e) = verify_external_result {
|
||||
warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}",
|
||||
verified_header.number(), verified_header.hash(), e);
|
||||
@@ -465,50 +466,54 @@ impl<T: ChainDataFetcher> Client<T> {
|
||||
true
|
||||
}
|
||||
|
||||
fn check_epoch_signal(&self, verified_header: &Header) -> Result<Option<Proof>, T::Error> {
|
||||
let (mut block, mut receipts) = (None, None);
|
||||
fn check_epoch_signal(&self, verified_header: &Header) -> Result<Option<Proof<EthereumMachine>>, T::Error> {
|
||||
use ethcore::machine::{AuxiliaryRequest, AuxiliaryData};
|
||||
|
||||
// First, check without providing auxiliary data.
|
||||
match self.engine.signals_epoch_end(verified_header, None, None) {
|
||||
EpochChange::No => return Ok(None),
|
||||
EpochChange::Yes(proof) => return Ok(Some(proof)),
|
||||
EpochChange::Unsure(unsure) => {
|
||||
let (b, r) = match unsure {
|
||||
Unsure::NeedsBody =>
|
||||
(Some(self.fetcher.block_body(verified_header)), None),
|
||||
Unsure::NeedsReceipts =>
|
||||
(None, Some(self.fetcher.block_receipts(verified_header))),
|
||||
Unsure::NeedsBoth => (
|
||||
Some(self.fetcher.block_body(verified_header)),
|
||||
Some(self.fetcher.block_receipts(verified_header)),
|
||||
),
|
||||
let mut block: Option<Vec<u8>> = None;
|
||||
let mut receipts: Option<Vec<_>> = None;
|
||||
|
||||
loop {
|
||||
|
||||
|
||||
let is_signal = {
|
||||
let auxiliary = AuxiliaryData {
|
||||
bytes: block.as_ref().map(|x| &x[..]),
|
||||
receipts: receipts.as_ref().map(|x| &x[..]),
|
||||
};
|
||||
|
||||
if let Some(b) = b {
|
||||
block = Some(b.into_future().wait()?.into_inner());
|
||||
}
|
||||
self.engine.signals_epoch_end(verified_header, auxiliary)
|
||||
};
|
||||
|
||||
if let Some(r) = r {
|
||||
receipts = Some(r.into_future().wait()?);
|
||||
// check with any auxiliary data fetched so far
|
||||
match is_signal {
|
||||
EpochChange::No => return Ok(None),
|
||||
EpochChange::Yes(proof) => return Ok(Some(proof)),
|
||||
EpochChange::Unsure(unsure) => {
|
||||
let (b, r) = match unsure {
|
||||
AuxiliaryRequest::Body =>
|
||||
(Some(self.fetcher.block_body(verified_header)), None),
|
||||
AuxiliaryRequest::Receipts =>
|
||||
(None, Some(self.fetcher.block_receipts(verified_header))),
|
||||
AuxiliaryRequest::Both => (
|
||||
Some(self.fetcher.block_body(verified_header)),
|
||||
Some(self.fetcher.block_receipts(verified_header)),
|
||||
),
|
||||
};
|
||||
|
||||
if let Some(b) = b {
|
||||
block = Some(b.into_future().wait()?.into_inner());
|
||||
}
|
||||
|
||||
if let Some(r) = r {
|
||||
receipts = Some(r.into_future().wait()?);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let block = block.as_ref().map(|x| &x[..]);
|
||||
let receipts = receipts.as_ref().map(|x| &x[..]);
|
||||
|
||||
// Check again now that required data has been fetched.
|
||||
match self.engine.signals_epoch_end(verified_header, block, receipts) {
|
||||
EpochChange::No => return Ok(None),
|
||||
EpochChange::Yes(proof) => return Ok(Some(proof)),
|
||||
EpochChange::Unsure(_) =>
|
||||
panic!("Detected faulty engine implementation: requests additional \
|
||||
data to check epoch end signal when everything necessary provided"),
|
||||
}
|
||||
}
|
||||
|
||||
// attempts to fetch the epoch proof from the network until successful.
|
||||
fn write_pending_proof(&self, header: &Header, proof: Proof) -> Result<(), T::Error> {
|
||||
fn write_pending_proof(&self, header: &Header, proof: Proof<EthereumMachine>) -> Result<(), T::Error> {
|
||||
let proof = match proof {
|
||||
Proof::Known(known) => known,
|
||||
Proof::WithState(state_dependent) => {
|
||||
@@ -568,7 +573,7 @@ impl<T: ChainDataFetcher> LightChainClient for Client<T> {
|
||||
Client::env_info(self, id)
|
||||
}
|
||||
|
||||
fn engine(&self) -> &Arc<Engine> {
|
||||
fn engine(&self) -> &Arc<EthEngine> {
|
||||
Client::engine(self)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user