Strict validation transitions (#4988)
* ability to make validation stricter * fix consensus * remove logger
This commit is contained in:
		
							parent
							
								
									7039eaf995
								
							
						
					
					
						commit
						a61b1567d0
					
				@ -23,7 +23,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            "0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
 | 
					            "0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
 | 
				
			||||||
          ]
 | 
					          ]
 | 
				
			||||||
        }
 | 
					        },
 | 
				
			||||||
 | 
					        "validateScoreTransition": 1000000
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
@ -31,7 +32,7 @@
 | 
				
			|||||||
    "maximumExtraDataSize": "0x20",
 | 
					    "maximumExtraDataSize": "0x20",
 | 
				
			||||||
    "minGasLimit": "0x1388",
 | 
					    "minGasLimit": "0x1388",
 | 
				
			||||||
    "networkID" : "0x2A",
 | 
					    "networkID" : "0x2A",
 | 
				
			||||||
    "validateReceipts" : false
 | 
					    "validateReceiptsTransition" : 1000000
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "genesis": {
 | 
					  "genesis": {
 | 
				
			||||||
    "seal": {
 | 
					    "seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -393,7 +393,7 @@ impl Client {
 | 
				
			|||||||
			})?;
 | 
								})?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Final Verification
 | 
								// Final Verification
 | 
				
			||||||
			if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header(), self.engine().params().validate_receipts) {
 | 
								if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header(), self.engine().params().validate_receipts_transition) {
 | 
				
			||||||
				warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
 | 
									warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
 | 
				
			||||||
				return Err(());
 | 
									return Err(());
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
				
			|||||||
@ -53,6 +53,8 @@ pub struct AuthorityRoundParams {
 | 
				
			|||||||
	pub start_step: Option<u64>,
 | 
						pub start_step: Option<u64>,
 | 
				
			||||||
	/// Valid validators.
 | 
						/// Valid validators.
 | 
				
			||||||
	pub validators: ethjson::spec::ValidatorSet,
 | 
						pub validators: ethjson::spec::ValidatorSet,
 | 
				
			||||||
 | 
						/// Chain score validation transition block.
 | 
				
			||||||
 | 
						pub validate_score_transition: u64,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
 | 
					impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
 | 
				
			||||||
@ -64,6 +66,7 @@ impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
 | 
				
			|||||||
			block_reward: p.block_reward.map_or_else(U256::zero, Into::into),
 | 
								block_reward: p.block_reward.map_or_else(U256::zero, Into::into),
 | 
				
			||||||
			registrar: p.registrar.map_or_else(Address::new, Into::into),
 | 
								registrar: p.registrar.map_or_else(Address::new, Into::into),
 | 
				
			||||||
			start_step: p.start_step.map(Into::into),
 | 
								start_step: p.start_step.map(Into::into),
 | 
				
			||||||
 | 
								validate_score_transition: p.validate_score_transition.map_or(0, Into::into),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -85,6 +88,7 @@ pub struct AuthorityRound {
 | 
				
			|||||||
	validators: Box<ValidatorSet>,
 | 
						validators: Box<ValidatorSet>,
 | 
				
			||||||
	/// Is this Engine just for testing (prevents step calibration).
 | 
						/// Is this Engine just for testing (prevents step calibration).
 | 
				
			||||||
	calibrate_step: bool,
 | 
						calibrate_step: bool,
 | 
				
			||||||
 | 
						validate_score_transition: u64,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn header_step(header: &Header) -> Result<usize, ::rlp::DecoderError> {
 | 
					fn header_step(header: &Header) -> Result<usize, ::rlp::DecoderError> {
 | 
				
			||||||
@ -125,6 +129,7 @@ impl AuthorityRound {
 | 
				
			|||||||
				signer: Default::default(),
 | 
									signer: Default::default(),
 | 
				
			||||||
				validators: new_validator_set(our_params.validators),
 | 
									validators: new_validator_set(our_params.validators),
 | 
				
			||||||
				calibrate_step: our_params.start_step.is_none(),
 | 
									calibrate_step: our_params.start_step.is_none(),
 | 
				
			||||||
 | 
									validate_score_transition: our_params.validate_score_transition,
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		// Do not initialize timeouts for tests.
 | 
							// Do not initialize timeouts for tests.
 | 
				
			||||||
		if should_timeout {
 | 
							if should_timeout {
 | 
				
			||||||
@ -295,6 +300,10 @@ impl Engine for AuthorityRound {
 | 
				
			|||||||
			Err(From::from(BlockError::InvalidSealArity(
 | 
								Err(From::from(BlockError::InvalidSealArity(
 | 
				
			||||||
				Mismatch { expected: self.seal_fields(), found: header.seal().len() }
 | 
									Mismatch { expected: self.seal_fields(), found: header.seal().len() }
 | 
				
			||||||
			)))
 | 
								)))
 | 
				
			||||||
 | 
							} else if header.number() >= self.validate_score_transition && *header.difficulty() >= U256::from(U128::max_value()) {
 | 
				
			||||||
 | 
								Err(From::from(BlockError::DifficultyOutOfBounds(
 | 
				
			||||||
 | 
									OutOfBounds { min: None, max: Some(U256::from(U128::max_value())), found: *header.difficulty() }
 | 
				
			||||||
 | 
								)))
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			Ok(())
 | 
								Ok(())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -327,7 +336,8 @@ impl Engine for AuthorityRound {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Check if parent is from a previous step.
 | 
							// Check if parent is from a previous step.
 | 
				
			||||||
		if step == header_step(parent)? {
 | 
							let parent_step = header_step(parent)?;
 | 
				
			||||||
 | 
							if step == parent_step {
 | 
				
			||||||
			trace!(target: "engine", "Multiple blocks proposed for step {}.", step);
 | 
								trace!(target: "engine", "Multiple blocks proposed for step {}.", step);
 | 
				
			||||||
			self.validators.report_malicious(header.author());
 | 
								self.validators.report_malicious(header.author());
 | 
				
			||||||
			Err(EngineError::DoubleVote(header.author().clone()))?;
 | 
								Err(EngineError::DoubleVote(header.author().clone()))?;
 | 
				
			||||||
 | 
				
			|||||||
@ -56,7 +56,7 @@ pub struct CommonParams {
 | 
				
			|||||||
	/// Number of first block where EIP-98 rules begin.
 | 
						/// Number of first block where EIP-98 rules begin.
 | 
				
			||||||
	pub eip98_transition: BlockNumber,
 | 
						pub eip98_transition: BlockNumber,
 | 
				
			||||||
	/// Validate block receipts root.
 | 
						/// Validate block receipts root.
 | 
				
			||||||
	pub validate_receipts: bool,
 | 
						pub validate_receipts_transition: u64,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<ethjson::spec::Params> for CommonParams {
 | 
					impl From<ethjson::spec::Params> for CommonParams {
 | 
				
			||||||
@ -70,7 +70,7 @@ impl From<ethjson::spec::Params> for CommonParams {
 | 
				
			|||||||
			min_gas_limit: p.min_gas_limit.into(),
 | 
								min_gas_limit: p.min_gas_limit.into(),
 | 
				
			||||||
			fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None },
 | 
								fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None },
 | 
				
			||||||
			eip98_transition: p.eip98_transition.map_or(0, Into::into),
 | 
								eip98_transition: p.eip98_transition.map_or(0, Into::into),
 | 
				
			||||||
			validate_receipts: p.validate_receipts.unwrap_or(true),
 | 
								validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ impl Verifier for CanonVerifier {
 | 
				
			|||||||
		verification::verify_block_family(header, bytes, engine, bc)
 | 
							verification::verify_block_family(header, bytes, engine, bc)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn verify_block_final(&self, expected: &Header, got: &Header, receipts: bool) -> Result<(), Error> {
 | 
						fn verify_block_final(&self, expected: &Header, got: &Header, receipts: u64) -> Result<(), Error> {
 | 
				
			||||||
		verification::verify_block_final(expected, got, receipts)
 | 
							verification::verify_block_final(expected, got, receipts)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ impl Verifier for NoopVerifier {
 | 
				
			|||||||
		Ok(())
 | 
							Ok(())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn verify_block_final(&self, _expected: &Header, _got: &Header, _receipts: bool) -> Result<(), Error> {
 | 
						fn verify_block_final(&self, _expected: &Header, _got: &Header, _receipts: u64) -> Result<(), Error> {
 | 
				
			||||||
		Ok(())
 | 
							Ok(())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -178,7 +178,7 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Phase 4 verification. Check block information against transaction enactment results,
 | 
					/// Phase 4 verification. Check block information against transaction enactment results,
 | 
				
			||||||
pub fn verify_block_final(expected: &Header, got: &Header, check_receipts: bool) -> Result<(), Error> {
 | 
					pub fn verify_block_final(expected: &Header, got: &Header, check_receipts: u64) -> Result<(), Error> {
 | 
				
			||||||
	if expected.gas_used() != got.gas_used() {
 | 
						if expected.gas_used() != got.gas_used() {
 | 
				
			||||||
		return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: expected.gas_used().clone(), found: got.gas_used().clone() })))
 | 
							return Err(From::from(BlockError::InvalidGasUsed(Mismatch { expected: expected.gas_used().clone(), found: got.gas_used().clone() })))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -188,7 +188,7 @@ pub fn verify_block_final(expected: &Header, got: &Header, check_receipts: bool)
 | 
				
			|||||||
	if expected.state_root() != got.state_root() {
 | 
						if expected.state_root() != got.state_root() {
 | 
				
			||||||
		return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root().clone(), found: got.state_root().clone() })))
 | 
							return Err(From::from(BlockError::InvalidStateRoot(Mismatch { expected: expected.state_root().clone(), found: got.state_root().clone() })))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if check_receipts && expected.receipts_root() != got.receipts_root() {
 | 
						if got.number() >= check_receipts && expected.receipts_root() != got.receipts_root() {
 | 
				
			||||||
		return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: expected.receipts_root().clone(), found: got.receipts_root().clone() })))
 | 
							return Err(From::from(BlockError::InvalidReceiptsRoot(Mismatch { expected: expected.receipts_root().clone(), found: got.receipts_root().clone() })))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	Ok(())
 | 
						Ok(())
 | 
				
			||||||
 | 
				
			|||||||
@ -26,5 +26,5 @@ pub trait Verifier: Send + Sync {
 | 
				
			|||||||
	/// Verify a block relative to its parent and uncles.
 | 
						/// Verify a block relative to its parent and uncles.
 | 
				
			||||||
	fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>;
 | 
						fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>;
 | 
				
			||||||
	/// Do a final verification check for an enacted header vs its expected counterpart.
 | 
						/// Do a final verification check for an enacted header vs its expected counterpart.
 | 
				
			||||||
	fn verify_block_final(&self, expected: &Header, got: &Header, receipts: bool) -> Result<(), Error>;
 | 
						fn verify_block_final(&self, expected: &Header, got: &Header, receipts: u64) -> Result<(), Error>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -40,6 +40,9 @@ pub struct AuthorityRoundParams {
 | 
				
			|||||||
	/// To be used for testing only.
 | 
						/// To be used for testing only.
 | 
				
			||||||
	#[serde(rename="startStep")]
 | 
						#[serde(rename="startStep")]
 | 
				
			||||||
	pub start_step: Option<Uint>,
 | 
						pub start_step: Option<Uint>,
 | 
				
			||||||
 | 
						/// Block at which score validation should start.
 | 
				
			||||||
 | 
						#[serde(rename="validateScoreTransition")]
 | 
				
			||||||
 | 
						pub validate_score_transition: Option<Uint>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Authority engine deserialization.
 | 
					/// Authority engine deserialization.
 | 
				
			||||||
 | 
				
			|||||||
@ -54,8 +54,8 @@ pub struct Params {
 | 
				
			|||||||
	#[serde(rename="eip98Transition")]
 | 
						#[serde(rename="eip98Transition")]
 | 
				
			||||||
	pub eip98_transition: Option<Uint>,
 | 
						pub eip98_transition: Option<Uint>,
 | 
				
			||||||
	/// See `CommonParams` docs.
 | 
						/// See `CommonParams` docs.
 | 
				
			||||||
	#[serde(rename="validateReceipts")]
 | 
						#[serde(rename="validateReceiptsTransition")]
 | 
				
			||||||
	pub validate_receipts: Option<bool>,
 | 
						pub validate_receipts_transition: Option<Uint>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user