Skip to content
This repository has been archived by the owner on Oct 31, 2023. It is now read-only.

Bullshark Fallback #30

Open
wants to merge 7 commits into
base: bullshark
Choose a base branch
from

Conversation

neilgiri
Copy link

Updated code for the fallback path of Bullshark.

Fixed two tests and try steady/fallback commit

Fixed tests

Fixed rust build

Fixed formatting
@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Mar 20, 2022
@asonnino
Copy link
Contributor

Just a quick note: I would recommend against merging this PR (containing the code of the fallback) into the Bullshark branch, it will be better to create a new branch for the fallback.

Copy link
Contributor

@asonnino asonnino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't forget to run cargo fmt and to remove dead code :)
Do the test names match the test content? It seems you made some modifications there. We should keep the original tests (designed for the common case), and add tests for the fallback.

.fb_validator_sets
.entry(fb_wave)
.or_insert(BTreeSet::new());
//println!("commit round {} fbwave {} size {}", certificate.round(), fb_wave, fb_sets.len());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code

.map(|(_, x)| self.committee.stake(&x.origin()))
.sum();

//println!("fb stake {}", stake);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code

.filter(|(_, x)| ss_sets.contains(&x.origin()))
.map(|(_, x)| self.committee.stake(&x.origin()))
.sum();
//println!("ss stake {} round {} sswave {} size {}", stake, certificate.round(), ss_wave, ss_sets.len());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code

.entry(fb_wave)
.or_insert(BTreeSet::new())
.insert(certificate.origin());
//println!("fb_size round {} wave {} size {}", certificate.round(), fb_wave, state.fb_validator_sets.entry(fb_wave).or_insert(BTreeSet::new()).len());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code

Comment on lines 251 to 252
let ss_wave = ((certificate.round() as f64) / 2.0).ceil() as u64;
let fb_wave = ((certificate.round() as f64) / 4.0).ceil() as u64;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid float arithmetic, we should be able to work with u64

@@ -118,12 +118,13 @@ async fn commit_one() {

// Ensure the first 4 ordered certificates are from round 1 (they are the parents of the committed
// leader); then the leader's certificate should be committed.
for _ in 1..=4 {
/*for _ in 1..=1 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code

@@ -133,7 +134,7 @@ async fn dead_node() {
// Make the certificates.
let mut keys: Vec<_> = keys().into_iter().map(|(x, _)| x).collect();
keys.sort(); // Ensure we don't remove one of the leaders.
let _ = keys.pop().unwrap();
//let _ = keys.pop().unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code

Comment on lines 238 to 239
//let (_, certificate) = mock_certificate(keys[1], 5, parents);
//certificates.push_back(certificate);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code

@@ -252,7 +258,7 @@ async fn not_enough_support() {
}

// We should commit 2 leaders (rounds 2 and 4).
for _ in 1..=3 {
/*for _ in 1..=3 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code

}

// Run for 7 dag rounds. Node 0 (the leader of round 2) is missing for rounds 1 and 2,
// Run for 5 dag rounds. Node 0 (the leader of round 2) is missing for rounds 1 and 2,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was testing the fallback commit code path. Since the fallback wave 1 consists of rounds 1-4, we run for 5 DAG rounds so that the certificate in round 5 triggers a fallback commit.

Comment on lines 202 to 203
let ss_wave = certificate.round() / 2;
let fb_wave = certificate.round() / 4;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't there a missing offset of 1? (if not, why were you using 'ceil'?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed all of the wave indices to be 0-indexed, which means that ceil is no longer needed. For example, round 1 before corresponded to steady state wave 1 (ceil(round / 2)) whereas now it corresponds to steady state wave 0.

// in the fallback
let fb_leader = self.try_fallback_commit(&certificate, max(fb_wave - 1, 1), state);
// in the current steady state wave
let fb_leader = self.try_fallback_commit(&certificate, fb_wave - 1, state);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this underflow?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, since if fb_wave = 0 then either ss_wave = 0 or ss_wave = 1. If ss_wave is 0 then the function returns None from if statement from before. If ss_wave = 1 then the mode is already determined since all validators begin from steady state wave 1, and so the function will return None. I will add an explicit underflow check to be safe.


if state
.fb_validator_sets
.entry(max(fb_wave - 1, 1))
.entry(fb_wave - 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment

}

// Run for 5 dag rounds. The leaders of round 2 does not have enough support, but the leader of
// round 4 does. The leader of rounds 2 and 4 should thus be committed.
// Run for 7 dag rounds. The leaders of round 2 does not have enough support (f+1 votes), but the leader of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the threshold back to 2f+1 now that we have a fallback?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes the threshold is 2f+1 but once the fallback leader in fallback wave 1 (leader of round 4) is committed we must check whether earlier leaders may have been committed. We thus commit the steady state leader of round 2 (steady state wave 1) since there are f+1 votes for it and less than f+1 votes for the fallback leader of fallback wave 0.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants