From b6bb9f0789ab4899cb798a89d7132933cbdc3369 Mon Sep 17 00:00:00 2001 From: StephenButtolph Date: Tue, 17 Mar 2020 23:29:38 -0400 Subject: [PATCH] Removed redundent filter in unaryNode and added test for filtering in binaryNode --- ids/bag.go | 2 +- snow/consensus/snowball/tree.go | 13 +++- snow/consensus/snowball/tree_test.go | 105 +++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/ids/bag.go b/ids/bag.go index 1022489..5a8aab4 100644 --- a/ids/bag.go +++ b/ids/bag.go @@ -95,7 +95,7 @@ func (b *Bag) Mode() (ID, int) { return b.mode, b.modeFreq } func (b *Bag) Threshold() Set { return b.metThreshold } // Filter returns the bag of ids with the same counts as this bag, except all -// the ids in the returned bag must have the same bits in the range [start, end] +// the ids in the returned bag must have the same bits in the range [start, end) // as id. func (b *Bag) Filter(start, end int, id ID) Bag { newBag := Bag{} diff --git a/snow/consensus/snowball/tree.go b/snow/consensus/snowball/tree.go index ad6554b..d5983d4 100644 --- a/snow/consensus/snowball/tree.go +++ b/snow/consensus/snowball/tree.go @@ -409,13 +409,18 @@ func (u *unaryNode) RecordPoll(votes ids.Bag, reset bool) node { u.snowball.RecordSuccessfulPoll() if u.child != nil { - decidedPrefix := u.child.DecidedPrefix() - filteredVotes := votes.Filter(u.commonPrefix, decidedPrefix, u.preference) + // We are guaranteed that u.commonPrefix will equal + // u.child.DecidedPrefix(). Otherwise, there must have been a + // decision under this node, which isn't possible because + // beta1 <= beta2. That means that filtering the votes between + // u.commonPrefix and u.child.DecidedPrefix() would always result in + // the same set being returned. + // If I'm now decided, return my child if u.Finalized() { - return u.child.RecordPoll(filteredVotes, u.shouldReset) + return u.child.RecordPoll(votes, u.shouldReset) } - u.child = u.child.RecordPoll(filteredVotes, u.shouldReset) + u.child = u.child.RecordPoll(votes, u.shouldReset) // The child's preference may have changed u.preference = u.child.Preference() } diff --git a/snow/consensus/snowball/tree_test.go b/snow/consensus/snowball/tree_test.go index 56904e1..428de3a 100644 --- a/snow/consensus/snowball/tree_test.go +++ b/snow/consensus/snowball/tree_test.go @@ -533,3 +533,108 @@ func TestSnowballConsistent(t *testing.T) { t.Fatalf("Network agreed on inconsistent values") } } + +func TestSnowballFilterBinaryChildren(t *testing.T) { + c0000 := ids.NewID([32]byte{0b00000000}) + c1000 := ids.NewID([32]byte{0b00000001}) + c0100 := ids.NewID([32]byte{0b00000010}) + c0010 := ids.NewID([32]byte{0b00000100}) + + params := Parameters{ + Metrics: prometheus.NewRegistry(), + K: 1, Alpha: 1, BetaVirtuous: 1, BetaRogue: 2, + } + tree := Tree{} + tree.Initialize(params, c0000) + { + expected := "SB(NumSuccessfulPolls = 0, Confidence = 0, Finalized = false) Bits = [0, 256)" + if pref := tree.Preference(); !c0000.Equals(pref) { + t.Fatalf("Wrong preference. Expected %s got %s", c0000, pref) + } else if tree.Finalized() { + t.Fatalf("Finalized too early") + } else if str := tree.String(); expected != str { + t.Fatalf("Wrong string. Expected:\n%s\ngot:\n%s", expected, str) + } + } + + tree.Add(c1000) + { + expected := "SB(Preference = 0, NumSuccessfulPolls[0] = 0, NumSuccessfulPolls[1] = 0, SF = SF(Preference = 0, Confidence = 0, Finalized = false)) Bit = 0\n"+ + " SB(NumSuccessfulPolls = 0, Confidence = 0, Finalized = false) Bits = [1, 256)\n"+ + " SB(NumSuccessfulPolls = 0, Confidence = 0, Finalized = false) Bits = [1, 256)" + if pref := tree.Preference(); !c0000.Equals(pref) { + t.Fatalf("Wrong preference. Expected %s got %s", c0000, pref) + } else if tree.Finalized() { + t.Fatalf("Finalized too early") + } else if str := tree.String(); expected != str { + t.Fatalf("Wrong string. Expected:\n%s\ngot:\n%s", expected, str) + } + } + + tree.Add(c0010) + { + expected := "SB(Preference = 0, NumSuccessfulPolls[0] = 0, NumSuccessfulPolls[1] = 0, SF = SF(Preference = 0, Confidence = 0, Finalized = false)) Bit = 0\n"+ + " SB(NumSuccessfulPolls = 0, Confidence = 0, Finalized = false) Bits = [1, 2)\n"+ + " SB(Preference = 0, NumSuccessfulPolls[0] = 0, NumSuccessfulPolls[1] = 0, SF = SF(Preference = 0, Confidence = 0, Finalized = false)) Bit = 2\n"+ + " SB(NumSuccessfulPolls = 0, Confidence = 0, Finalized = false) Bits = [3, 256)\n"+ + " SB(NumSuccessfulPolls = 0, Confidence = 0, Finalized = false) Bits = [3, 256)\n"+ + " SB(NumSuccessfulPolls = 0, Confidence = 0, Finalized = false) Bits = [1, 256)" + if pref := tree.Preference(); !c0000.Equals(pref) { + t.Fatalf("Wrong preference. Expected %s got %s", c0000, pref) + } else if tree.Finalized() { + t.Fatalf("Finalized too early") + } else if str := tree.String(); expected != str { + t.Fatalf("Wrong string. Expected:\n%s\ngot:\n%s", expected, str) + } + } + + c0000Bag := ids.Bag{} + c0000Bag.Add(c0000) + tree.RecordPoll(c0000Bag) + { + expected := "SB(Preference = 0, NumSuccessfulPolls[0] = 1, NumSuccessfulPolls[1] = 0, SF = SF(Preference = 0, Confidence = 1, Finalized = false)) Bit = 0\n"+ + " SB(Preference = 0, NumSuccessfulPolls[0] = 1, NumSuccessfulPolls[1] = 0, SF = SF(Preference = 0, Confidence = 1, Finalized = false)) Bit = 2\n"+ + " SB(NumSuccessfulPolls = 1, Confidence = 1, Finalized = true) Bits = [3, 256)\n"+ + " SB(NumSuccessfulPolls = 0, Confidence = 0, Finalized = false) Bits = [3, 256)\n"+ + " SB(NumSuccessfulPolls = 0, Confidence = 0, Finalized = false) Bits = [1, 256)" + if pref := tree.Preference(); !c0000.Equals(pref) { + t.Fatalf("Wrong preference. Expected %s got %s", c0000, pref) + } else if tree.Finalized() { + t.Fatalf("Finalized too early") + } else if str := tree.String(); expected != str { + t.Fatalf("Wrong string. Expected:\n%s\ngot:\n%s", expected, str) + } + } + + tree.Add(c0100) + { + expected := "SB(Preference = 0, NumSuccessfulPolls[0] = 1, NumSuccessfulPolls[1] = 0, SF = SF(Preference = 0, Confidence = 1, Finalized = false)) Bit = 0\n"+ + " SB(Preference = 0, NumSuccessfulPolls[0] = 1, NumSuccessfulPolls[1] = 0, SF = SF(Preference = 0, Confidence = 1, Finalized = false)) Bit = 2\n"+ + " SB(NumSuccessfulPolls = 1, Confidence = 1, Finalized = true) Bits = [3, 256)\n"+ + " SB(NumSuccessfulPolls = 0, Confidence = 0, Finalized = false) Bits = [3, 256)\n"+ + " SB(NumSuccessfulPolls = 0, Confidence = 0, Finalized = false) Bits = [1, 256)" + if pref := tree.Preference(); !c0000.Equals(pref) { + t.Fatalf("Wrong preference. Expected %s got %s", c0000, pref) + } else if tree.Finalized() { + t.Fatalf("Finalized too early") + } else if str := tree.String(); expected != str { + t.Fatalf("Wrong string. Expected:\n%s\ngot:\n%s", expected, str) + } + } + + c0100Bag := ids.Bag{} + c0100Bag.Add(c0100) + tree.RecordPoll(c0100Bag) + { + expected := "SB(Preference = 0, NumSuccessfulPolls[0] = 1, NumSuccessfulPolls[1] = 0, SF = SF(Preference = 0, Confidence = 0, Finalized = false)) Bit = 2\n"+ + " SB(NumSuccessfulPolls = 1, Confidence = 1, Finalized = true) Bits = [3, 256)\n"+ + " SB(NumSuccessfulPolls = 0, Confidence = 0, Finalized = false) Bits = [3, 256)" + if pref := tree.Preference(); !c0000.Equals(pref) { + t.Fatalf("Wrong preference. Expected %s got %s", c0000, pref) + } else if tree.Finalized() { + t.Fatalf("Finalized too early") + } else if str := tree.String(); expected != str { + t.Fatalf("Wrong string. Expected:\n%s\ngot:\n%s", expected, str) + } + } +}