Merge pull request #305 from sigp/fork-choice-correction

Correct all fork choice rules for children with no votes.
This commit is contained in:
Paul Hauner 2019-03-14 18:29:03 +13:00 committed by GitHub
commit e44f2fca8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 12 deletions

View File

@ -409,11 +409,23 @@ impl<T: ClientDB + Sized> ForkChoice for BitwiseLMDGhost<T> {
*child_votes.entry(child).or_insert_with(|| 0) += vote; *child_votes.entry(child).or_insert_with(|| 0) += vote;
} }
} }
// given the votes on the children, find the best child // check if we have votes of children, if not select the smallest hash child
current_head = self if child_votes.is_empty() {
.choose_best_child(&child_votes) current_head = *children
.ok_or(ForkChoiceError::CannotFindBestChild)?; .iter()
trace!("Best child found: {}", current_head); .min_by(|child1, child2| child1.cmp(child2))
.expect("Must be children here");
trace!(
"Children have no votes - smallest hash chosen: {}",
current_head
);
} else {
// given the votes on the children, find the best child
current_head = self
.choose_best_child(&child_votes)
.ok_or(ForkChoiceError::CannotFindBestChild)?;
trace!("Best child found: {}", current_head);
}
} }
// didn't find head yet, proceed to next iteration // didn't find head yet, proceed to next iteration

View File

@ -380,11 +380,23 @@ impl<T: ClientDB + Sized> ForkChoice for OptimizedLMDGhost<T> {
*child_votes.entry(child).or_insert_with(|| 0) += vote; *child_votes.entry(child).or_insert_with(|| 0) += vote;
} }
} }
// given the votes on the children, find the best child // check if we have votes of children, if not select the smallest hash child
current_head = self if child_votes.is_empty() {
.choose_best_child(&child_votes) current_head = *children
.ok_or(ForkChoiceError::CannotFindBestChild)?; .iter()
trace!("Best child found: {}", current_head); .min_by(|child1, child2| child1.cmp(child2))
.expect("Must be children here");
trace!(
"Children have no votes - smallest hash chosen: {}",
current_head
);
} else {
// given the votes on the children, find the best child
current_head = self
.choose_best_child(&child_votes)
.ok_or(ForkChoiceError::CannotFindBestChild)?;
trace!("Best child found: {}", current_head);
}
} }
// didn't find head yet, proceed to next iteration // didn't find head yet, proceed to next iteration

View File

@ -210,6 +210,7 @@ impl<T: ClientDB + Sized> ForkChoice for SlowLMDGhost<T> {
trace!("Children found: {:?}", children); trace!("Children found: {:?}", children);
let mut head_vote_count = 0; let mut head_vote_count = 0;
head_hash = children[0];
for child_hash in children { for child_hash in children {
let vote_count = self.get_vote_count(&latest_votes, &child_hash)?; let vote_count = self.get_vote_count(&latest_votes, &child_hash)?;
trace!("Vote count for child: {} is: {}", child_hash, vote_count); trace!("Vote count for child: {} is: {}", child_hash, vote_count);
@ -218,6 +219,12 @@ impl<T: ClientDB + Sized> ForkChoice for SlowLMDGhost<T> {
head_hash = *child_hash; head_hash = *child_hash;
head_vote_count = vote_count; head_vote_count = vote_count;
} }
// resolve ties - choose smaller hash
else if vote_count == head_vote_count {
if *child_hash < head_hash {
head_hash = *child_hash;
}
}
} }
} }
Ok(head_hash) Ok(head_hash)

View File

@ -128,4 +128,17 @@ test_cases:
- b8: 4 - b8: 4
- b9: 2 - b9: 2
heads: heads:
- id: 'b7' - id: 'b7'
- blocks:
- id: 'b0'
parent: 'b0'
- id: 'b1'
parent: 'b0'
- id: 'b2'
parent: 'b0'
weights:
- b1: 0
- b2: 0
heads:
- id: 'b1'

View File

@ -51,3 +51,15 @@ test_cases:
- b3: 6 - b3: 6
heads: heads:
- id: 'b2' - id: 'b2'
- blocks:
- id: 'b0'
parent: 'b0'
- id: 'b1'
parent: 'b0'
- id: 'b2'
parent: 'b0'
weights:
- b1: 0
- b2: 0
heads:
- id: 'b1'