Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Print warnings when using dangerous settings for ValidatorSet #10733

Merged
merged 19 commits into from
Jun 24, 2019
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions ethcore/blockchain/src/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,7 @@ impl BlockChain {
/// Iterate over all epoch transitions.
/// This will only return transitions within the canonical chain.
pub fn epoch_transitions(&self) -> EpochTransitionIter {
trace!(target: "blockchain", "Iterating over all epoch transitions");
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
let iter = self.db.key_value().iter_from_prefix(db::COL_EXTRA, &EPOCH_KEY_PREFIX[..]);
EpochTransitionIter {
chain: self,
Expand All @@ -988,7 +989,9 @@ impl BlockChain {
pub fn epoch_transition_for(&self, parent_hash: H256) -> Option<EpochTransition> {
// slow path: loop back block by block
for hash in self.ancestry_iter(parent_hash)? {
trace!(target: "blockchain", "Got parent hash {} from ancestry_iter", hash);
let details = self.block_details(&hash)?;
trace!(target: "blockchain", "Block #{}: Got block details", details.number);
dvdplm marked this conversation as resolved.
Show resolved Hide resolved

// look for transition in database.
if let Some(transition) = self.epoch_transition(details.number, hash) {
Expand All @@ -1000,11 +1003,22 @@ impl BlockChain {
//
// if `block_hash` is canonical it will only return transitions up to
// the parent.
if self.block_hash(details.number)? == hash {
return self.epoch_transitions()
.map(|(_, t)| t)
.take_while(|t| t.block_number <= details.number)
.last()
match self.block_hash(details.number) {
Some(h) if h == hash => {
return self.epoch_transitions()
.map(|(_, t)| t)
.take_while(|t| t.block_number <= details.number)
.last()
},
Some(h) => {
warn!(target: "blockchain", "Block #{}: Found non-canonical block hash {} (expected {})", details.number, h, hash);

trace!(target: "blockchain", "Block #{} Mismatched hashes. Ancestor {} != Own {} – Own block #{}", details.number, hash, h, self.block_number(&h).unwrap_or_default() );
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
trace!(target: "blockchain", " Ancestor {}: #{:#?}", hash, self.block_details(&hash));
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
trace!(target: "blockchain", " Own {}: #{:#?}", h, self.block_details(&h));

},
None => trace!(target: "blockchain", "Block #{}: hash {} not found in cache or DB", details.number, hash),
}
}

Expand Down
12 changes: 10 additions & 2 deletions ethcore/src/engines/authority_round/finality.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub struct RollingFinality {
impl RollingFinality {
/// Create a blank finality checker under the given validator set.
pub fn blank(signers: Vec<Address>) -> Self {
trace!(target: "finality", "Instantiating blank RollingFinality with {} signers: {:?}", signers.len(), signers);
RollingFinality {
headers: VecDeque::new(),
signers: SimpleList::new(signers),
Expand Down Expand Up @@ -110,7 +111,14 @@ impl RollingFinality {
/// Returns a list of all newly finalized headers.
// TODO: optimize with smallvec.
pub fn push_hash(&mut self, head: H256, signers: Vec<Address>) -> Result<Vec<H256>, UnknownValidator> {
if signers.iter().any(|s| !self.signers.contains(s)) { return Err(UnknownValidator) }
// TODO: seems bad to iterate over signers twice like this.
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
// Can do the work in a single loop and call `clear()` if an unknown validator was found?
for their_signer in signers.iter() {
if !self.signers.contains(their_signer) {
warn!(target: "finality", "Unknown validator: {}", their_signer);
return Err(UnknownValidator)
}
}

for signer in signers.iter() {
*self.sign_count.entry(*signer).or_insert(0) += 1;
Expand Down Expand Up @@ -141,7 +149,7 @@ impl RollingFinality {
}
}

trace!(target: "finality", "Blocks finalized by {:?}: {:?}", head, newly_finalized);
trace!(target: "finality", "{} Blocks finalized by {:?}: {:?}", newly_finalized.len(), head, newly_finalized);

self.last_pushed = Some(head);
Ok(newly_finalized)
Expand Down
8 changes: 4 additions & 4 deletions ethcore/src/engines/authority_round/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ impl EpochManager {
None => {
// this really should never happen unless the block passed
// hasn't got a parent in the database.
debug!(target: "engine", "No genesis transition found.");
warn!(target: "engine", "No genesis transition found.");
return false;
}
};
Expand Down Expand Up @@ -280,8 +280,8 @@ impl EpochManager {
true
}

// note new epoch hash. this will force the next block to re-load
// the epoch set
// Note new epoch hash. This will force the next block to re-load
// the epoch set.
// TODO: optimize and don't require re-loading after epoch change.
fn note_new_epoch(&mut self) {
self.force = true;
Expand Down Expand Up @@ -614,7 +614,7 @@ fn verify_external(header: &Header, validators: &ValidatorSet, empty_steps_trans
};

if is_invalid_proposer {
trace!(target: "engine", "verify_block_external: bad proposer for step: {}", header_step);
warn!(target: "engine", "verify_block_external: bad proposer for step: {}", header_step);
Err(EngineError::NotProposer(Mismatch { expected: correct_proposer, found: *header.author() }))?
} else {
Ok(())
Expand Down
14 changes: 9 additions & 5 deletions ethcore/src/engines/validator_set/safe_contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,11 @@ impl ValidatorSafeContract {

match value {
Ok(new) => {
debug!(target: "engine", "Set of validators obtained: {:?}", new);
debug!(target: "engine", "Got validator set from contract: {:?}", new);
Some(SimpleList::new(new))
},
Err(s) => {
debug!(target: "engine", "Set of validators could not be updated: {}", s);
debug!(target: "engine", "Could not get validator set from contract: {}", s);
None
},
}
Expand Down Expand Up @@ -335,7 +335,7 @@ impl ValidatorSet for ValidatorSafeContract {
Some(receipts) => match self.extract_from_event(bloom, header, receipts) {
None => ::engines::EpochChange::No,
Some(list) => {
info!(target: "engine", "Signal for transition within contract. New list: {:?}",
info!(target: "engine", "Signal for transition within contract. New validator list: {:?}",
&*list);

let proof = encode_proof(&header, receipts);
Expand All @@ -359,7 +359,7 @@ impl ValidatorSet for ValidatorSafeContract {
let addresses = check_first_proof(machine, self.contract_address, old_header, &state_items)
.map_err(::engines::EngineError::InsufficientProof)?;

trace!(target: "engine", "extracted epoch set at #{}: {} addresses",
trace!(target: "engine", "Extracted epoch validator set at block #{}: {} addresses",
number, addresses.len());

Ok((SimpleList::new(addresses), Some(old_hash)))
Expand All @@ -380,7 +380,11 @@ impl ValidatorSet for ValidatorSafeContract {
let bloom = self.expected_bloom(&old_header);

match self.extract_from_event(bloom, &old_header, &receipts) {
Some(list) => Ok((list, Some(old_header.hash()))),
Some(list) => {
trace!(target: "engine", "Extracted epoch validator set at block #{}: {} addresses", old_header.number(), list.len());

Ok((list, Some(old_header.hash())))
},
None => Err(::engines::EngineError::InsufficientProof("No log event in proof.".into()).into()),
}
}
Expand Down
13 changes: 8 additions & 5 deletions ethcore/src/engines/validator_set/simple_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,14 @@ pub struct SimpleList {
impl SimpleList {
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
/// Create a new `SimpleList`.
pub fn new(validators: Vec<Address>) -> Self {
SimpleList {
validators: validators,
let validator_count = validators.len();
if validator_count == 1 {
warn!(target: "engine", "Running AuRa with a single validator is not supported.");
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
}
if validator_count % 2 == 0 {
warn!(target: "engine", "Running AuRa with an even number of validators is not supported.");
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
}
SimpleList { validators }
}

/// Convert into inner representation.
Expand All @@ -52,9 +57,7 @@ impl ::std::ops::Deref for SimpleList {

impl From<Vec<Address>> for SimpleList {
fn from(validators: Vec<Address>) -> Self {
SimpleList {
validators: validators,
}
SimpleList::new(validators)
}
}

Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/verification/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ pub trait Verifier<C>: Send + Sync

/// Do a final verification check for an enacted header vs its expected counterpart.
fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error>;
/// Verify a block, inspecing external state.
/// Verify a block, inspecting external state.
fn verify_block_external(&self, header: &Header, engine: &EthEngine) -> Result<(), Error>;
}