diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 6ec2584ec..8da7c14b2 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -26,7 +26,7 @@ use util::error::{Mismatch, OutOfBounds}; use basic_types::{LogBloom, Seal}; use env_info::{EnvInfo, LastHashes}; -use engines::{Engine, ValidationProof}; +use engines::Engine; use error::{Error, BlockError, TransactionError}; use factory::Factories; use header::Header; @@ -488,11 +488,10 @@ impl LockedBlock { self, engine: &Engine, seal: Vec, - proof: Option, ) -> Result { let mut s = self; s.block.header.set_seal(seal); - match engine.verify_block_seal(&s.block.header, proof) { + match engine.verify_block_seal(&s.block.header) { Err(e) => Err((e, s)), _ => Ok(SealedBlock { block: s.block, uncle_bytes: s.uncle_bytes }), } diff --git a/ethcore/src/engines/authority_round.rs b/ethcore/src/engines/authority_round.rs index acc276d21..e6cbdb531 100644 --- a/ethcore/src/engines/authority_round.rs +++ b/ethcore/src/engines/authority_round.rs @@ -464,14 +464,14 @@ mod tests { engine.set_signer(tap.clone(), addr1, "1".into()); if let Seal::Regular(seal) = engine.generate_seal(b1.block()) { - assert!(b1.clone().try_seal(engine, seal, None).is_ok()); + assert!(b1.clone().try_seal(engine, seal).is_ok()); // Second proposal is forbidden. assert!(engine.generate_seal(b1.block()) == Seal::None); } engine.set_signer(tap, addr2, "2".into()); if let Seal::Regular(seal) = engine.generate_seal(b2.block()) { - assert!(b2.clone().try_seal(engine, seal, None).is_ok()); + assert!(b2.clone().try_seal(engine, seal).is_ok()); // Second proposal is forbidden. assert!(engine.generate_seal(b2.block()) == Seal::None); } diff --git a/ethcore/src/engines/basic_authority.rs b/ethcore/src/engines/basic_authority.rs index fe27994e4..e5a53d4e9 100644 --- a/ethcore/src/engines/basic_authority.rs +++ b/ethcore/src/engines/basic_authority.rs @@ -258,7 +258,7 @@ mod tests { let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = b.close_and_lock(); if let Seal::Regular(seal) = engine.generate_seal(b.block()) { - assert!(b.try_seal(engine, seal, None).is_ok()); + assert!(b.try_seal(engine, seal).is_ok()); } } diff --git a/ethcore/src/engines/instant_seal.rs b/ethcore/src/engines/instant_seal.rs index 5d05dd83f..45bede9f4 100644 --- a/ethcore/src/engines/instant_seal.rs +++ b/ethcore/src/engines/instant_seal.rs @@ -89,7 +89,7 @@ mod tests { let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = b.close_and_lock(); if let Seal::Regular(seal) = engine.generate_seal(b.block()) { - assert!(b.try_seal(engine, seal, None).is_ok()); + assert!(b.try_seal(engine, seal).is_ok()); } } diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 0ae353a56..e4bc514b7 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -44,6 +44,7 @@ use evm::Schedule; use header::Header; use spec::CommonParams; use transaction::{UnverifiedTransaction, SignedTransaction}; +use receipt::Receipt; use ethkey::Signature; use util::*; @@ -61,8 +62,6 @@ pub enum EngineError { UnexpectedMessage, /// Seal field has an unexpected size. BadSealFieldSize(OutOfBounds), - /// Needs a validation proof for the given block hash before verification can continue. - NeedsValidationProof(H256), } impl fmt::Display for EngineError { @@ -74,7 +73,6 @@ impl fmt::Display for EngineError { NotAuthorized(ref address) => format!("Signer {} is not authorized.", address), UnexpectedMessage => "This Engine should not be fed messages.".into(), BadSealFieldSize(ref oob) => format!("Seal field has an unexpected length: {}", oob), - NeedsValidationProof(ref hash) => format!("Needs validation proof of block {} to verify seal.", hash), }; f.write_fmt(format_args!("Engine error ({})", msg)) @@ -92,12 +90,29 @@ pub enum Seal { None, } -/// A validation proof, required for validation of a block header. -pub type ValidationProof = Vec; - /// Type alias for a function we can make calls through synchronously. pub type Call = Fn(Address, Bytes) -> Result; +/// Results of a query of whether a validation proof is necessary at a block. +pub enum RequiresProof { + /// Cannot determine until more data is passed. + Unsure(Unsure), + /// Validation proof not required. + No, + /// Validation proof required. + Yes, +} + +/// More data required to determine if a validation proof is required. +pub enum Unsure { + /// Needs the body. + NeedsBody, + /// Needs the receipts. + NeedsReceipts, + /// Needs both body and receipts. + NeedsBoth, +} + /// A consensus mechanism for the chain. Generally either proof-of-work or proof-of-stake-based. /// Provides hooks into each of the major parts of block import. pub trait Engine : Sync + Send { @@ -191,23 +206,22 @@ pub trait Engine : Sync + Send { /// Verify the seal of a block. This is an auxilliary method that actually just calls other `verify_` methods /// to get the job done. By default it must pass `verify_basic` and `verify_block_unordered`. If more or fewer /// methods are needed for an Engine, this may be overridden. - fn verify_block_seal(&self, header: &Header, _proof: Option) -> Result<(), Error> { + fn verify_block_seal(&self, header: &Header) -> Result<(), Error> { self.verify_block_basic(header, None).and_then(|_| self.verify_block_unordered(header, None)) } - /// Generate a validation proof for the given block header. + /// Re-do all verification for a header with the given contract-calling interface /// - /// All values queried during execution of given will go into the proof. - /// This may only be called for blocks indicated in "needs validation proof" - /// errors. - /// - /// Engines which don't draw consensus information from the state (e.g. PoW) - /// don't need to change anything here. - /// - /// Engines which do draw consensus information from the state may only do so - /// here. - fn generate_validation_proof(&self, header: &Header, _call: &Call) -> ValidationProof { - ValidationProof::default() + /// This will be used to generate proofs of validation as well as verify them. + fn verify_with_state(&self, _header: &Header, _call: &Call) -> Result<(), Error> { + Ok(()) + } + + /// Whether a proof is required for the given header. + fn proof_required(&self, _header: Header, _block: Option<&[u8]>, _receipts: Option<&[Receipt]>) + -> RequiresProof + { + RequiresProof::No } /// Populate a header's fields based on its parent's header. diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index e88803ce2..8c8094117 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -864,7 +864,7 @@ mod tests { let proposer = insert_and_register(&tap, spec.engine.as_ref(), "1"); let (b, seal) = propose_default(&spec, proposer); - assert!(b.lock().try_seal(spec.engine.as_ref(), seal, None).is_ok()); + assert!(b.lock().try_seal(spec.engine.as_ref(), seal).is_ok()); } #[test] diff --git a/ethcore/src/engines/validator_set/mod.rs b/ethcore/src/engines/validator_set/mod.rs index a2f6d1075..2c00c43b0 100644 --- a/ethcore/src/engines/validator_set/mod.rs +++ b/ethcore/src/engines/validator_set/mod.rs @@ -25,15 +25,12 @@ use std::sync::Weak; use util::{Address, H256}; use ethjson::spec::ValidatorSet as ValidatorSpec; use client::Client; -use receipt::Receipt; use self::simple_list::SimpleList; use self::contract::ValidatorContract; use self::safe_contract::ValidatorSafeContract; use self::multi::Multi; -pub type Call = Fn(Address, Vec) -> Result, String>; - /// Creates a validator set from spec. pub fn new_validator_set(spec: ValidatorSpec) -> Box { match spec { @@ -48,10 +45,6 @@ pub fn new_validator_set(spec: ValidatorSpec) -> Box { /// A validator set. pub trait ValidatorSet: Send + Sync { - /// Get this validator set as a flexible validator set. - /// Returning `None` indicates this is only usable for - /// full nodes. - fn as_memoized(&self) -> Option<&Memoized> { None } /// Checks if a given address is a validator. fn contains(&self, parent_block_hash: &H256, address: &Address) -> bool; /// Draws an validator nonce modulo number of validators. @@ -65,35 +58,3 @@ pub trait ValidatorSet: Send + Sync { /// Allows blockchain state access. fn register_contract(&self, _client: Weak) {} } - -/// A flexible validator set can track its changes. -pub trait FlexibleValidatorSet: Send + Sync { - /// Whether a validator set may have changed at this header. - fn has_possibly_changed(&self, header: &Header) -> bool; - - /// Whether a validator set has changed at this header, given the block receipts. - /// Called after `has_possibly_changed`. - /// `Some` indicates the validator set has changed at this header and the new - /// expected validator set. - /// `None` indicates no change. - fn has_changed(&self, header: &Header, receipts: &[Receipt]) -> Option; - - /// Fetch validators at a block synchronously. - fn fetch_validators(&self, header: &Header, call: &Call) -> Result; -} - -/// A memoized flexible validator set -pub struct Memoized { - inner: Box, - memo: Mutex<(SimpleList, (H256, u64))>, -} - -impl Memoized { - /// Denote that the - pub fn use_memo_at(&self, list: SimpleList) -} - -impl ValidatorSet for Memoized { - fn as_memoized(&self) -> Option<&Memoized> { Some(self) } -} - diff --git a/ethcore/src/engines/validator_set/multi.rs b/ethcore/src/engines/validator_set/multi.rs index 8527a8aa9..3ae93b0f5 100644 --- a/ethcore/src/engines/validator_set/multi.rs +++ b/ethcore/src/engines/validator_set/multi.rs @@ -55,7 +55,7 @@ impl Multi { ) { Ok((block, set)) => { trace!(target: "engine", "Multi ValidatorSet retrieved for block {}.", block); - Some(&*set) + Some(&**set) }, Err(e) => { debug!(target: "engine", "ValidatorSet could not be recovered: {}", e); @@ -66,21 +66,6 @@ impl Multi { } impl ValidatorSet for Multi { - fn has_possibly_changed(&self, header: &Header) -> bool { - // if the sets are the same for each header, compare those. - // otherwise, the sets have almost certainly changed. - match (self.correct_set(&header.hash()), self.correct_set(header.parent_hash())) { - (Some(a), Some(b)) if a as *const _ == b as *const _ => { a.has_possibly_changed(header) }, - _ => true, - } - } - - fn has_changed(&self, header: &Header, receipts: &[Receipt]) -> Option> { - - } - - fn fetch(&self) -> - fn contains(&self, bh: &H256, address: &Address) -> bool { self.correct_set(bh).map_or(false, |set| set.contains(bh, address)) } diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 8337ef2d8..ac1695b52 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -1133,7 +1133,7 @@ impl MinerService for Miner { |b| &b.hash() == &block_hash ) { trace!(target: "miner", "Submitted block {}={}={} with seal {:?}", block_hash, b.hash(), b.header().bare_hash(), seal); - b.lock().try_seal(&*self.engine, seal, None).or_else(|(e, _)| { + b.lock().try_seal(&*self.engine, seal).or_else(|(e, _)| { warn!(target: "miner", "Mined solution rejected: {}", e); Err(Error::PowInvalid) }) diff --git a/ethcore/src/snapshot/mod.rs b/ethcore/src/snapshot/mod.rs index 0ef263476..1c3b4366b 100644 --- a/ethcore/src/snapshot/mod.rs +++ b/ethcore/src/snapshot/mod.rs @@ -567,7 +567,7 @@ pub fn verify_old_block(rng: &mut OsRng, header: &Header, engine: &Engine, chain if always || rng.gen::() <= POW_VERIFY_RATE { match chain.block_header(header.parent_hash()) { Some(parent) => engine.verify_block_family(header, &parent, body), - None => engine.verify_block_seal(header, None), // TODO: fetch validation proof as necessary. + None => engine.verify_block_seal(header), // TODO: fetch validation proof as necessary. } } else { engine.verify_block_basic(header, body)