engine changes
This commit is contained in:
		
							parent
							
								
									7723d6281b
								
							
						
					
					
						commit
						2d8a8bd3e5
					
				| @ -26,7 +26,7 @@ use util::error::{Mismatch, OutOfBounds}; | |||||||
| 
 | 
 | ||||||
| use basic_types::{LogBloom, Seal}; | use basic_types::{LogBloom, Seal}; | ||||||
| use env_info::{EnvInfo, LastHashes}; | use env_info::{EnvInfo, LastHashes}; | ||||||
| use engines::{Engine, ValidationProof}; | use engines::Engine; | ||||||
| use error::{Error, BlockError, TransactionError}; | use error::{Error, BlockError, TransactionError}; | ||||||
| use factory::Factories; | use factory::Factories; | ||||||
| use header::Header; | use header::Header; | ||||||
| @ -488,11 +488,10 @@ impl LockedBlock { | |||||||
| 		self, | 		self, | ||||||
| 		engine: &Engine, | 		engine: &Engine, | ||||||
| 		seal: Vec<Bytes>, | 		seal: Vec<Bytes>, | ||||||
| 		proof: Option<ValidationProof>, |  | ||||||
| 	) -> Result<SealedBlock, (Error, LockedBlock)> { | 	) -> Result<SealedBlock, (Error, LockedBlock)> { | ||||||
| 		let mut s = self; | 		let mut s = self; | ||||||
| 		s.block.header.set_seal(seal); | 		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)), | 			Err(e) => Err((e, s)), | ||||||
| 			_ => Ok(SealedBlock { block: s.block, uncle_bytes: s.uncle_bytes }), | 			_ => Ok(SealedBlock { block: s.block, uncle_bytes: s.uncle_bytes }), | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -464,14 +464,14 @@ mod tests { | |||||||
| 
 | 
 | ||||||
| 		engine.set_signer(tap.clone(), addr1, "1".into()); | 		engine.set_signer(tap.clone(), addr1, "1".into()); | ||||||
| 		if let Seal::Regular(seal) = engine.generate_seal(b1.block()) { | 		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.
 | 			// Second proposal is forbidden.
 | ||||||
| 			assert!(engine.generate_seal(b1.block()) == Seal::None); | 			assert!(engine.generate_seal(b1.block()) == Seal::None); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		engine.set_signer(tap, addr2, "2".into()); | 		engine.set_signer(tap, addr2, "2".into()); | ||||||
| 		if let Seal::Regular(seal) = engine.generate_seal(b2.block()) { | 		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.
 | 			// Second proposal is forbidden.
 | ||||||
| 			assert!(engine.generate_seal(b2.block()) == Seal::None); | 			assert!(engine.generate_seal(b2.block()) == Seal::None); | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -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 = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap(); | ||||||
| 		let b = b.close_and_lock(); | 		let b = b.close_and_lock(); | ||||||
| 		if let Seal::Regular(seal) = engine.generate_seal(b.block()) { | 		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()); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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 = 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(); | 		let b = b.close_and_lock(); | ||||||
| 		if let Seal::Regular(seal) = engine.generate_seal(b.block()) { | 		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()); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -44,6 +44,7 @@ use evm::Schedule; | |||||||
| use header::Header; | use header::Header; | ||||||
| use spec::CommonParams; | use spec::CommonParams; | ||||||
| use transaction::{UnverifiedTransaction, SignedTransaction}; | use transaction::{UnverifiedTransaction, SignedTransaction}; | ||||||
|  | use receipt::Receipt; | ||||||
| 
 | 
 | ||||||
| use ethkey::Signature; | use ethkey::Signature; | ||||||
| use util::*; | use util::*; | ||||||
| @ -61,8 +62,6 @@ pub enum EngineError { | |||||||
| 	UnexpectedMessage, | 	UnexpectedMessage, | ||||||
| 	/// Seal field has an unexpected size.
 | 	/// Seal field has an unexpected size.
 | ||||||
| 	BadSealFieldSize(OutOfBounds<usize>), | 	BadSealFieldSize(OutOfBounds<usize>), | ||||||
| 	/// Needs a validation proof for the given block hash before verification can continue.
 |  | ||||||
| 	NeedsValidationProof(H256), |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl fmt::Display for EngineError { | impl fmt::Display for EngineError { | ||||||
| @ -74,7 +73,6 @@ impl fmt::Display for EngineError { | |||||||
| 			NotAuthorized(ref address) => format!("Signer {} is not authorized.", address), | 			NotAuthorized(ref address) => format!("Signer {} is not authorized.", address), | ||||||
| 			UnexpectedMessage => "This Engine should not be fed messages.".into(), | 			UnexpectedMessage => "This Engine should not be fed messages.".into(), | ||||||
| 			BadSealFieldSize(ref oob) => format!("Seal field has an unexpected length: {}", oob), | 			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)) | 		f.write_fmt(format_args!("Engine error ({})", msg)) | ||||||
| @ -92,12 +90,29 @@ pub enum Seal { | |||||||
| 	None, | 	None, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// A validation proof, required for validation of a block header.
 |  | ||||||
| pub type ValidationProof = Vec<DBValue>; |  | ||||||
| 
 |  | ||||||
| /// Type alias for a function we can make calls through synchronously.
 | /// Type alias for a function we can make calls through synchronously.
 | ||||||
| pub type Call = Fn(Address, Bytes) -> Result<Bytes, String>; | pub type Call = Fn(Address, Bytes) -> Result<Bytes, String>; | ||||||
| 
 | 
 | ||||||
|  | /// 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.
 | /// 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.
 | /// Provides hooks into each of the major parts of block import.
 | ||||||
| pub trait Engine : Sync + Send { | 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
 | 	/// 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
 | 	/// 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.
 | 	/// methods are needed for an Engine, this may be overridden.
 | ||||||
| 	fn verify_block_seal(&self, header: &Header, _proof: Option<ValidationProof>) -> 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)) | 		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 will be used to generate proofs of validation as well as verify them.
 | ||||||
| 	/// This may only be called for blocks indicated in "needs validation proof"
 | 	fn verify_with_state(&self, _header: &Header, _call: &Call) -> Result<(), Error> { | ||||||
| 	/// errors.
 | 		Ok(()) | ||||||
| 	///
 | 	} | ||||||
| 	/// Engines which don't draw consensus information from the state (e.g. PoW)
 | 
 | ||||||
| 	/// don't need to change anything here.
 | 	/// Whether a proof is required for the given header.
 | ||||||
| 	///
 | 	fn proof_required(&self, _header: Header, _block: Option<&[u8]>, _receipts: Option<&[Receipt]>) | ||||||
| 	/// Engines which do draw consensus information from the state may only do so
 | 		-> RequiresProof | ||||||
| 	/// here.
 | 	{ | ||||||
| 	fn generate_validation_proof(&self, header: &Header, _call: &Call) -> ValidationProof { | 		RequiresProof::No | ||||||
| 		ValidationProof::default() |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/// Populate a header's fields based on its parent's header.
 | 	/// Populate a header's fields based on its parent's header.
 | ||||||
|  | |||||||
| @ -864,7 +864,7 @@ mod tests { | |||||||
| 		let proposer = insert_and_register(&tap, spec.engine.as_ref(), "1"); | 		let proposer = insert_and_register(&tap, spec.engine.as_ref(), "1"); | ||||||
| 
 | 
 | ||||||
| 		let (b, seal) = propose_default(&spec, proposer); | 		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] | 	#[test] | ||||||
|  | |||||||
| @ -25,15 +25,12 @@ use std::sync::Weak; | |||||||
| use util::{Address, H256}; | use util::{Address, H256}; | ||||||
| use ethjson::spec::ValidatorSet as ValidatorSpec; | use ethjson::spec::ValidatorSet as ValidatorSpec; | ||||||
| use client::Client; | use client::Client; | ||||||
| use receipt::Receipt; |  | ||||||
| 
 | 
 | ||||||
| use self::simple_list::SimpleList; | use self::simple_list::SimpleList; | ||||||
| use self::contract::ValidatorContract; | use self::contract::ValidatorContract; | ||||||
| use self::safe_contract::ValidatorSafeContract; | use self::safe_contract::ValidatorSafeContract; | ||||||
| use self::multi::Multi; | use self::multi::Multi; | ||||||
| 
 | 
 | ||||||
| pub type Call = Fn(Address, Vec<u8>) -> Result<Vec<u8>, String>; |  | ||||||
| 
 |  | ||||||
| /// Creates a validator set from spec.
 | /// Creates a validator set from spec.
 | ||||||
| pub fn new_validator_set(spec: ValidatorSpec) -> Box<ValidatorSet> { | pub fn new_validator_set(spec: ValidatorSpec) -> Box<ValidatorSet> { | ||||||
| 	match spec { | 	match spec { | ||||||
| @ -48,10 +45,6 @@ pub fn new_validator_set(spec: ValidatorSpec) -> Box<ValidatorSet> { | |||||||
| 
 | 
 | ||||||
| /// A validator set.
 | /// A validator set.
 | ||||||
| pub trait ValidatorSet: Send + Sync { | 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.
 | 	/// Checks if a given address is a validator.
 | ||||||
| 	fn contains(&self, parent_block_hash: &H256, address: &Address) -> bool; | 	fn contains(&self, parent_block_hash: &H256, address: &Address) -> bool; | ||||||
| 	/// Draws an validator nonce modulo number of validators.
 | 	/// Draws an validator nonce modulo number of validators.
 | ||||||
| @ -65,35 +58,3 @@ pub trait ValidatorSet: Send + Sync { | |||||||
| 	/// Allows blockchain state access.
 | 	/// Allows blockchain state access.
 | ||||||
| 	fn register_contract(&self, _client: Weak<Client>) {} | 	fn register_contract(&self, _client: Weak<Client>) {} | ||||||
| } | } | ||||||
| 
 |  | ||||||
| /// 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<SimpleList>; |  | ||||||
| 
 |  | ||||||
| 	/// Fetch validators at a block synchronously.
 |  | ||||||
| 	fn fetch_validators(&self, header: &Header, call: &Call) -> Result<SimpleList, String>; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// A memoized flexible validator set
 |  | ||||||
| pub struct Memoized { |  | ||||||
| 	inner: Box<FlexibleValidatorSet>, |  | ||||||
| 	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) } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
|  | |||||||
| @ -55,7 +55,7 @@ impl Multi { | |||||||
| 				) { | 				) { | ||||||
| 			Ok((block, set)) => { | 			Ok((block, set)) => { | ||||||
| 				trace!(target: "engine", "Multi ValidatorSet retrieved for block {}.", block); | 				trace!(target: "engine", "Multi ValidatorSet retrieved for block {}.", block); | ||||||
| 				Some(&*set) | 				Some(&**set) | ||||||
| 			}, | 			}, | ||||||
| 			Err(e) => { | 			Err(e) => { | ||||||
| 				debug!(target: "engine", "ValidatorSet could not be recovered: {}", e); | 				debug!(target: "engine", "ValidatorSet could not be recovered: {}", e); | ||||||
| @ -66,21 +66,6 @@ impl Multi { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl ValidatorSet for 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<Vec<Address>> { |  | ||||||
| 
 |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	fn fetch(&self) -> |  | ||||||
| 
 |  | ||||||
| 	fn contains(&self, bh: &H256, address: &Address) -> bool { | 	fn contains(&self, bh: &H256, address: &Address) -> bool { | ||||||
| 		self.correct_set(bh).map_or(false, |set| set.contains(bh, address)) | 		self.correct_set(bh).map_or(false, |set| set.contains(bh, address)) | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -1133,7 +1133,7 @@ impl MinerService for Miner { | |||||||
| 				|b| &b.hash() == &block_hash | 				|b| &b.hash() == &block_hash | ||||||
| 			) { | 			) { | ||||||
| 				trace!(target: "miner", "Submitted block {}={}={} with seal {:?}", block_hash, b.hash(), b.header().bare_hash(), seal); | 				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); | 					warn!(target: "miner", "Mined solution rejected: {}", e); | ||||||
| 					Err(Error::PowInvalid) | 					Err(Error::PowInvalid) | ||||||
| 				}) | 				}) | ||||||
|  | |||||||
| @ -567,7 +567,7 @@ pub fn verify_old_block(rng: &mut OsRng, header: &Header, engine: &Engine, chain | |||||||
| 	if always || rng.gen::<f32>() <= POW_VERIFY_RATE { | 	if always || rng.gen::<f32>() <= POW_VERIFY_RATE { | ||||||
| 		match chain.block_header(header.parent_hash()) { | 		match chain.block_header(header.parent_hash()) { | ||||||
| 			Some(parent) => engine.verify_block_family(header, &parent, body), | 			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 { | 	} else { | ||||||
| 		engine.verify_block_basic(header, body) | 		engine.verify_block_basic(header, body) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user