mirror of https://github.com/poanetwork/gecko.git
644 lines
13 KiB
Go
644 lines
13 KiB
Go
|
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
||
|
// See the file LICENSE for licensing terms.
|
||
|
|
||
|
package snowman
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"math/rand"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/prometheus/client_golang/prometheus"
|
||
|
|
||
|
"github.com/ava-labs/gecko/ids"
|
||
|
"github.com/ava-labs/gecko/snow"
|
||
|
"github.com/ava-labs/gecko/snow/choices"
|
||
|
"github.com/ava-labs/gecko/snow/consensus/snowball"
|
||
|
)
|
||
|
|
||
|
func ParamsTest(t *testing.T, factory Factory) {
|
||
|
sm := factory.New()
|
||
|
|
||
|
ctx := snow.DefaultContextTest()
|
||
|
params := snowball.Parameters{
|
||
|
Namespace: fmt.Sprintf("gecko_%s", ctx.ChainID),
|
||
|
Metrics: prometheus.NewRegistry(),
|
||
|
K: 1, Alpha: 1, BetaVirtuous: 3, BetaRogue: 5,
|
||
|
}
|
||
|
|
||
|
numProcessing := prometheus.NewGauge(
|
||
|
prometheus.GaugeOpts{
|
||
|
Namespace: params.Namespace,
|
||
|
Name: "processing",
|
||
|
})
|
||
|
numAccepted := prometheus.NewCounter(
|
||
|
prometheus.CounterOpts{
|
||
|
Namespace: params.Namespace,
|
||
|
Name: "accepted",
|
||
|
})
|
||
|
numRejected := prometheus.NewCounter(
|
||
|
prometheus.CounterOpts{
|
||
|
Namespace: params.Namespace,
|
||
|
Name: "rejected",
|
||
|
})
|
||
|
|
||
|
params.Metrics.Register(numProcessing)
|
||
|
params.Metrics.Register(numAccepted)
|
||
|
params.Metrics.Register(numRejected)
|
||
|
|
||
|
sm.Initialize(ctx, params, Genesis.ID())
|
||
|
|
||
|
if p := sm.Parameters(); p.K != params.K {
|
||
|
t.Fatalf("Wrong K parameter")
|
||
|
} else if p.Alpha != params.Alpha {
|
||
|
t.Fatalf("Wrong Alpha parameter")
|
||
|
} else if p.BetaVirtuous != params.BetaVirtuous {
|
||
|
t.Fatalf("Wrong Beta1 parameter")
|
||
|
} else if p.BetaRogue != params.BetaRogue {
|
||
|
t.Fatalf("Wrong Beta2 parameter")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func AddTest(t *testing.T, factory Factory) {
|
||
|
sm := factory.New()
|
||
|
|
||
|
params := snowball.Parameters{
|
||
|
Metrics: prometheus.NewRegistry(),
|
||
|
K: 1, Alpha: 1, BetaVirtuous: 3, BetaRogue: 5,
|
||
|
}
|
||
|
sm.Initialize(snow.DefaultContextTest(), params, Genesis.ID())
|
||
|
|
||
|
if pref := sm.Preference(); !pref.Equals(Genesis.ID()) {
|
||
|
t.Fatalf("Wrong preference. Expected %s, got %s", Genesis.ID(), pref)
|
||
|
}
|
||
|
|
||
|
dep0 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.Empty.Prefix(1),
|
||
|
}
|
||
|
sm.Add(dep0)
|
||
|
if pref := sm.Preference(); !pref.Equals(dep0.id) {
|
||
|
t.Fatalf("Wrong preference. Expected %s, got %s", dep0.id, pref)
|
||
|
}
|
||
|
|
||
|
dep1 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.Empty.Prefix(2),
|
||
|
}
|
||
|
sm.Add(dep1)
|
||
|
if pref := sm.Preference(); !pref.Equals(dep0.id) {
|
||
|
t.Fatalf("Wrong preference. Expected %s, got %s", dep0.id, pref)
|
||
|
}
|
||
|
|
||
|
dep2 := &Blk{
|
||
|
parent: dep0,
|
||
|
id: ids.Empty.Prefix(3),
|
||
|
}
|
||
|
sm.Add(dep2)
|
||
|
if pref := sm.Preference(); !pref.Equals(dep2.id) {
|
||
|
t.Fatalf("Wrong preference. Expected %s, got %s", dep2.id, pref)
|
||
|
}
|
||
|
|
||
|
dep3 := &Blk{
|
||
|
parent: &Blk{id: ids.Empty.Prefix(4)},
|
||
|
id: ids.Empty.Prefix(5),
|
||
|
}
|
||
|
sm.Add(dep3)
|
||
|
if pref := sm.Preference(); !pref.Equals(dep2.id) {
|
||
|
t.Fatalf("Wrong preference. Expected %s, got %s", dep2.id, pref)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func CollectTest(t *testing.T, factory Factory) {
|
||
|
sm := factory.New()
|
||
|
|
||
|
params := snowball.Parameters{
|
||
|
Metrics: prometheus.NewRegistry(),
|
||
|
K: 2, Alpha: 2, BetaVirtuous: 1, BetaRogue: 2,
|
||
|
}
|
||
|
sm.Initialize(snow.DefaultContextTest(), params, Genesis.ID())
|
||
|
|
||
|
dep1 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.Empty.Prefix(2),
|
||
|
}
|
||
|
sm.Add(dep1)
|
||
|
|
||
|
dep0 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.Empty.Prefix(1),
|
||
|
}
|
||
|
sm.Add(dep0)
|
||
|
|
||
|
dep2 := &Blk{
|
||
|
parent: dep0,
|
||
|
id: ids.Empty.Prefix(3),
|
||
|
}
|
||
|
sm.Add(dep2)
|
||
|
|
||
|
dep3 := &Blk{
|
||
|
parent: dep0,
|
||
|
id: ids.Empty.Prefix(4),
|
||
|
}
|
||
|
sm.Add(dep3)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// G
|
||
|
// / \
|
||
|
// 0 1
|
||
|
// / \
|
||
|
// 2 3
|
||
|
// Tail = 1
|
||
|
|
||
|
dep2_2 := ids.Bag{}
|
||
|
dep2_2.AddCount(dep2.id, 2)
|
||
|
sm.RecordPoll(dep2_2)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// G
|
||
|
// / \
|
||
|
// 0 1
|
||
|
// / \
|
||
|
// 2 3
|
||
|
// Tail = 2
|
||
|
|
||
|
if sm.Finalized() {
|
||
|
t.Fatalf("Finalized too early")
|
||
|
} else if !dep2.id.Equals(sm.Preference()) {
|
||
|
t.Fatalf("Wrong preference listed")
|
||
|
}
|
||
|
|
||
|
dep3_2 := ids.Bag{}
|
||
|
dep3_2.AddCount(dep3.id, 2)
|
||
|
sm.RecordPoll(dep3_2)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// 0
|
||
|
// / \
|
||
|
// 2 3
|
||
|
// Tail = 2
|
||
|
|
||
|
if sm.Finalized() {
|
||
|
t.Fatalf("Finalized too early")
|
||
|
} else if !dep2.id.Equals(sm.Preference()) {
|
||
|
t.Fatalf("Wrong preference listed")
|
||
|
}
|
||
|
|
||
|
sm.RecordPoll(dep2_2)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// 0
|
||
|
// / \
|
||
|
// 2 3
|
||
|
// Tail = 2
|
||
|
|
||
|
if sm.Finalized() {
|
||
|
t.Fatalf("Finalized too early")
|
||
|
} else if !dep2.id.Equals(sm.Preference()) {
|
||
|
t.Fatalf("Wrong preference listed")
|
||
|
}
|
||
|
|
||
|
sm.RecordPoll(dep2_2)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// 2
|
||
|
// Tail = 2
|
||
|
|
||
|
if !sm.Finalized() {
|
||
|
t.Fatalf("Finalized too late")
|
||
|
} else if !dep2.id.Equals(sm.Preference()) {
|
||
|
t.Fatalf("Wrong preference listed")
|
||
|
}
|
||
|
|
||
|
if dep0.Status() != choices.Accepted {
|
||
|
t.Fatalf("Should have accepted")
|
||
|
} else if dep1.Status() != choices.Rejected {
|
||
|
t.Fatalf("Should have rejected")
|
||
|
} else if dep2.Status() != choices.Accepted {
|
||
|
t.Fatalf("Should have accepted")
|
||
|
} else if dep3.Status() != choices.Rejected {
|
||
|
t.Fatalf("Should have rejected")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func CollectNothingTest(t *testing.T, factory Factory) {
|
||
|
sm := factory.New()
|
||
|
|
||
|
params := snowball.Parameters{
|
||
|
Metrics: prometheus.NewRegistry(),
|
||
|
K: 1, Alpha: 1, BetaVirtuous: 1, BetaRogue: 2,
|
||
|
}
|
||
|
sm.Initialize(snow.DefaultContextTest(), params, Genesis.ID())
|
||
|
|
||
|
// Current graph structure:
|
||
|
// G
|
||
|
// Tail = G
|
||
|
|
||
|
genesis1 := ids.Bag{}
|
||
|
genesis1.AddCount(Genesis.ID(), 1)
|
||
|
sm.RecordPoll(genesis1)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// G
|
||
|
// Tail = G
|
||
|
|
||
|
if !sm.Finalized() {
|
||
|
t.Fatalf("Finalized too late")
|
||
|
} else if !Genesis.ID().Equals(sm.Preference()) {
|
||
|
t.Fatalf("Wrong preference listed")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func CollectTransRejectTest(t *testing.T, factory Factory) {
|
||
|
sm := factory.New()
|
||
|
|
||
|
params := snowball.Parameters{
|
||
|
Metrics: prometheus.NewRegistry(),
|
||
|
K: 1, Alpha: 1, BetaVirtuous: 1, BetaRogue: 2,
|
||
|
}
|
||
|
sm.Initialize(snow.DefaultContextTest(), params, Genesis.ID())
|
||
|
|
||
|
dep1 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.Empty.Prefix(2),
|
||
|
}
|
||
|
sm.Add(dep1)
|
||
|
|
||
|
dep0 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.Empty.Prefix(1),
|
||
|
}
|
||
|
sm.Add(dep0)
|
||
|
|
||
|
dep2 := &Blk{
|
||
|
parent: dep0,
|
||
|
id: ids.Empty.Prefix(3),
|
||
|
}
|
||
|
sm.Add(dep2)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// G
|
||
|
// / \
|
||
|
// 0 1
|
||
|
// /
|
||
|
// 2
|
||
|
// Tail = 1
|
||
|
|
||
|
dep1_1 := ids.Bag{}
|
||
|
dep1_1.AddCount(dep1.id, 1)
|
||
|
sm.RecordPoll(dep1_1)
|
||
|
sm.RecordPoll(dep1_1)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// 1
|
||
|
// Tail = 1
|
||
|
|
||
|
if !sm.Finalized() {
|
||
|
t.Fatalf("Finalized too late")
|
||
|
} else if !dep1.id.Equals(sm.Preference()) {
|
||
|
t.Fatalf("Wrong preference listed")
|
||
|
}
|
||
|
|
||
|
if dep0.Status() != choices.Rejected {
|
||
|
t.Fatalf("Should have rejected")
|
||
|
} else if dep1.Status() != choices.Accepted {
|
||
|
t.Fatalf("Should have accepted")
|
||
|
} else if dep2.Status() != choices.Rejected {
|
||
|
t.Fatalf("Should have rejected")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func CollectTransResetTest(t *testing.T, factory Factory) {
|
||
|
sm := factory.New()
|
||
|
|
||
|
params := snowball.Parameters{
|
||
|
Metrics: prometheus.NewRegistry(),
|
||
|
K: 1, Alpha: 1, BetaVirtuous: 1, BetaRogue: 2,
|
||
|
}
|
||
|
sm.Initialize(snow.DefaultContextTest(), params, Genesis.ID())
|
||
|
|
||
|
dep1 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.Empty.Prefix(2),
|
||
|
status: choices.Processing,
|
||
|
}
|
||
|
sm.Add(dep1)
|
||
|
|
||
|
dep0 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.Empty.Prefix(1),
|
||
|
status: choices.Processing,
|
||
|
}
|
||
|
sm.Add(dep0)
|
||
|
|
||
|
dep2 := &Blk{
|
||
|
parent: dep0,
|
||
|
id: ids.Empty.Prefix(3),
|
||
|
status: choices.Processing,
|
||
|
}
|
||
|
sm.Add(dep2)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// G
|
||
|
// / \
|
||
|
// 0 1
|
||
|
// /
|
||
|
// 2
|
||
|
// Tail = 1
|
||
|
|
||
|
dep1_1 := ids.Bag{}
|
||
|
dep1_1.AddCount(dep1.id, 1)
|
||
|
sm.RecordPoll(dep1_1)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// G
|
||
|
// / \
|
||
|
// 0 1
|
||
|
// /
|
||
|
// 2
|
||
|
// Tail = 1
|
||
|
|
||
|
dep2_1 := ids.Bag{}
|
||
|
dep2_1.AddCount(dep2.id, 1)
|
||
|
sm.RecordPoll(dep2_1)
|
||
|
|
||
|
if sm.Finalized() {
|
||
|
t.Fatalf("Finalized too early")
|
||
|
} else if status := dep0.Status(); status != choices.Processing {
|
||
|
t.Fatalf("Shouldn't have accepted yet %s", status)
|
||
|
}
|
||
|
|
||
|
if !dep1.id.Equals(sm.Preference()) {
|
||
|
t.Fatalf("Wrong preference listed")
|
||
|
}
|
||
|
|
||
|
sm.RecordPoll(dep2_1)
|
||
|
sm.RecordPoll(dep2_1)
|
||
|
|
||
|
if !sm.Finalized() {
|
||
|
t.Fatalf("Finalized too late")
|
||
|
} else if dep0.Status() != choices.Accepted {
|
||
|
t.Fatalf("Should have accepted")
|
||
|
} else if dep1.Status() != choices.Rejected {
|
||
|
t.Fatalf("Should have rejected")
|
||
|
} else if dep2.Status() != choices.Accepted {
|
||
|
t.Fatalf("Should have accepted")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func CollectTransVoteTest(t *testing.T, factory Factory) {
|
||
|
sm := factory.New()
|
||
|
|
||
|
params := snowball.Parameters{
|
||
|
Metrics: prometheus.NewRegistry(),
|
||
|
K: 3, Alpha: 3, BetaVirtuous: 1, BetaRogue: 1,
|
||
|
}
|
||
|
sm.Initialize(snow.DefaultContextTest(), params, Genesis.ID())
|
||
|
|
||
|
dep0 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.Empty.Prefix(1),
|
||
|
}
|
||
|
sm.Add(dep0)
|
||
|
|
||
|
dep1 := &Blk{
|
||
|
parent: dep0,
|
||
|
id: ids.Empty.Prefix(2),
|
||
|
}
|
||
|
sm.Add(dep1)
|
||
|
|
||
|
dep2 := &Blk{
|
||
|
parent: dep1,
|
||
|
id: ids.Empty.Prefix(3),
|
||
|
}
|
||
|
sm.Add(dep2)
|
||
|
|
||
|
dep3 := &Blk{
|
||
|
parent: dep0,
|
||
|
id: ids.Empty.Prefix(4),
|
||
|
}
|
||
|
sm.Add(dep3)
|
||
|
|
||
|
dep4 := &Blk{
|
||
|
parent: dep3,
|
||
|
id: ids.Empty.Prefix(5),
|
||
|
}
|
||
|
sm.Add(dep4)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// G
|
||
|
// /
|
||
|
// 0
|
||
|
// / \
|
||
|
// 1 3
|
||
|
// / \
|
||
|
// 2 4
|
||
|
// Tail = 2
|
||
|
|
||
|
dep0_2_4_1 := ids.Bag{}
|
||
|
dep0_2_4_1.AddCount(dep0.id, 1)
|
||
|
dep0_2_4_1.AddCount(dep2.id, 1)
|
||
|
dep0_2_4_1.AddCount(dep4.id, 1)
|
||
|
sm.RecordPoll(dep0_2_4_1)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// 0
|
||
|
// / \
|
||
|
// 1 3
|
||
|
// / \
|
||
|
// 2 4
|
||
|
// Tail = 2
|
||
|
|
||
|
if !dep2.id.Equals(sm.Preference()) {
|
||
|
t.Fatalf("Wrong preference listed")
|
||
|
}
|
||
|
|
||
|
dep2_3 := ids.Bag{}
|
||
|
dep2_3.AddCount(dep2.id, 3)
|
||
|
sm.RecordPoll(dep2_3)
|
||
|
|
||
|
// Current graph structure:
|
||
|
// 2
|
||
|
// Tail = 2
|
||
|
|
||
|
if !dep2.id.Equals(sm.Preference()) {
|
||
|
t.Fatalf("Wrong preference listed")
|
||
|
}
|
||
|
|
||
|
if !sm.Finalized() {
|
||
|
t.Fatalf("Finalized too late")
|
||
|
} else if dep0.Status() != choices.Accepted {
|
||
|
t.Fatalf("Should have accepted")
|
||
|
} else if dep1.Status() != choices.Accepted {
|
||
|
t.Fatalf("Should have accepted")
|
||
|
} else if dep2.Status() != choices.Accepted {
|
||
|
t.Fatalf("Should have accepted")
|
||
|
} else if dep3.Status() != choices.Rejected {
|
||
|
t.Fatalf("Should have rejected")
|
||
|
} else if dep4.Status() != choices.Rejected {
|
||
|
t.Fatalf("Should have rejected")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func DivergedVotingTest(t *testing.T, factory Factory) {
|
||
|
sm := factory.New()
|
||
|
|
||
|
params := snowball.Parameters{
|
||
|
Metrics: prometheus.NewRegistry(),
|
||
|
K: 1, Alpha: 1, BetaVirtuous: 1, BetaRogue: 2,
|
||
|
}
|
||
|
sm.Initialize(snow.DefaultContextTest(), params, Genesis.ID())
|
||
|
|
||
|
dep0 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.NewID([32]byte{0x0f}), // 0b1111
|
||
|
}
|
||
|
sm.Add(dep0)
|
||
|
|
||
|
dep1 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.NewID([32]byte{0x08}), // 0b1000
|
||
|
}
|
||
|
sm.Add(dep1)
|
||
|
|
||
|
dep0_1 := ids.Bag{}
|
||
|
dep0_1.AddCount(dep0.id, 1)
|
||
|
sm.RecordPoll(dep0_1)
|
||
|
|
||
|
dep2 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.NewID([32]byte{0x01}), // 0b0001
|
||
|
}
|
||
|
sm.Add(dep2)
|
||
|
|
||
|
// dep2 is already rejected.
|
||
|
|
||
|
dep3 := &Blk{
|
||
|
parent: dep2,
|
||
|
id: ids.Empty.Prefix(3),
|
||
|
}
|
||
|
sm.Add(dep3)
|
||
|
|
||
|
if dep0.Status() == choices.Accepted {
|
||
|
t.Fatalf("Shouldn't be accepted yet")
|
||
|
}
|
||
|
|
||
|
// Transitively increases dep2. However, dep2 shares the first bit with
|
||
|
// dep0. Because dep2 is already rejected, this will accept dep0.
|
||
|
dep3_1 := ids.Bag{}
|
||
|
dep3_1.AddCount(dep3.id, 1)
|
||
|
sm.RecordPoll(dep3_1)
|
||
|
|
||
|
if !sm.Finalized() {
|
||
|
t.Fatalf("Finalized too late")
|
||
|
} else if dep0.Status() != choices.Accepted {
|
||
|
t.Fatalf("Should be accepted")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func IssuedTest(t *testing.T, factory Factory) {
|
||
|
sm := factory.New()
|
||
|
|
||
|
params := snowball.Parameters{
|
||
|
Metrics: prometheus.NewRegistry(),
|
||
|
K: 1, Alpha: 1, BetaVirtuous: 1, BetaRogue: 2,
|
||
|
}
|
||
|
|
||
|
sm.Initialize(snow.DefaultContextTest(), params, Genesis.ID())
|
||
|
|
||
|
dep0 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.NewID([32]byte{0}),
|
||
|
status: choices.Processing,
|
||
|
}
|
||
|
|
||
|
if sm.Issued(dep0) {
|
||
|
t.Fatalf("Hasn't been issued yet")
|
||
|
}
|
||
|
|
||
|
sm.Add(dep0)
|
||
|
|
||
|
if !sm.Issued(dep0) {
|
||
|
t.Fatalf("Has been issued")
|
||
|
}
|
||
|
|
||
|
dep1 := &Blk{
|
||
|
parent: Genesis,
|
||
|
id: ids.NewID([32]byte{0x1}), // 0b0001
|
||
|
status: choices.Accepted,
|
||
|
}
|
||
|
|
||
|
if !sm.Issued(dep1) {
|
||
|
t.Fatalf("Has accepted status")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func MetricsErrorTest(t *testing.T, factory Factory) {
|
||
|
sm := factory.New()
|
||
|
|
||
|
ctx := snow.DefaultContextTest()
|
||
|
params := snowball.Parameters{
|
||
|
Namespace: fmt.Sprintf("gecko_%s", ctx.ChainID),
|
||
|
Metrics: prometheus.NewRegistry(),
|
||
|
K: 1, Alpha: 1, BetaVirtuous: 1, BetaRogue: 2,
|
||
|
}
|
||
|
|
||
|
numProcessing := prometheus.NewGauge(
|
||
|
prometheus.GaugeOpts{
|
||
|
Namespace: params.Namespace,
|
||
|
Name: "processing",
|
||
|
})
|
||
|
numAccepted := prometheus.NewCounter(
|
||
|
prometheus.CounterOpts{
|
||
|
Namespace: params.Namespace,
|
||
|
Name: "accepted",
|
||
|
})
|
||
|
numRejected := prometheus.NewCounter(
|
||
|
prometheus.CounterOpts{
|
||
|
Namespace: params.Namespace,
|
||
|
Name: "rejected",
|
||
|
})
|
||
|
|
||
|
if err := params.Metrics.Register(numProcessing); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
if err := params.Metrics.Register(numAccepted); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
if err := params.Metrics.Register(numRejected); err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
sm.Initialize(ctx, params, Genesis.ID())
|
||
|
}
|
||
|
|
||
|
func ConsistentTest(t *testing.T, factory Factory) {
|
||
|
numColors := 50
|
||
|
numNodes := 100
|
||
|
params := snowball.Parameters{
|
||
|
Metrics: prometheus.NewRegistry(),
|
||
|
K: 20,
|
||
|
Alpha: 15,
|
||
|
BetaVirtuous: 20,
|
||
|
BetaRogue: 30,
|
||
|
}
|
||
|
seed := int64(0)
|
||
|
|
||
|
rand.Seed(seed)
|
||
|
|
||
|
n := Network{}
|
||
|
n.Initialize(params, numColors)
|
||
|
|
||
|
for i := 0; i < numNodes; i++ {
|
||
|
n.AddNode(factory.New())
|
||
|
}
|
||
|
|
||
|
for !n.Finalized() {
|
||
|
n.Round()
|
||
|
}
|
||
|
|
||
|
if !n.Agreement() {
|
||
|
t.Fatalf("Network agreed on inconsistent values")
|
||
|
}
|
||
|
}
|