Merge pull request #23 from StephenButtolph/tree-tests

Snowball tree cleanup + filter testing
This commit is contained in:
Stephen Buttolph 2020-03-18 17:05:30 -04:00 committed by GitHub
commit 998ed8b3a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 115 additions and 5 deletions

View File

@ -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{}

View File

@ -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()
}

View File

@ -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)
}
}
}