mirror of https://github.com/poanetwork/gecko.git
754 lines
16 KiB
Go
754 lines
16 KiB
Go
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package avalanche
|
|
|
|
import (
|
|
"math"
|
|
"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"
|
|
"github.com/ava-labs/gecko/snow/consensus/snowstorm"
|
|
)
|
|
|
|
func TestTopologicalParams(t *testing.T) { ParamsTest(t, TopologicalFactory{}) }
|
|
|
|
func TestTopologicalAdd(t *testing.T) { AddTest(t, TopologicalFactory{}) }
|
|
|
|
func TestTopologicalVertexIssued(t *testing.T) { VertexIssuedTest(t, TopologicalFactory{}) }
|
|
|
|
func TestTopologicalTxIssued(t *testing.T) { TxIssuedTest(t, TopologicalFactory{}) }
|
|
|
|
func TestAvalancheVoting(t *testing.T) {
|
|
params := Parameters{
|
|
Parameters: snowball.Parameters{
|
|
Metrics: prometheus.NewRegistry(),
|
|
K: 2,
|
|
Alpha: 2,
|
|
BetaVirtuous: 1,
|
|
BetaRogue: 2,
|
|
},
|
|
Parents: 2,
|
|
BatchSize: 1,
|
|
}
|
|
vts := []Vertex{&Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}, &Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}}
|
|
utxos := []ids.ID{GenerateID()}
|
|
|
|
ta := Topological{}
|
|
ta.Initialize(snow.DefaultContextTest(), params, vts)
|
|
|
|
tx0 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx0.Ins.Add(utxos[0])
|
|
|
|
vtx0 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx0},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
tx1 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx1.Ins.Add(utxos[0])
|
|
|
|
vtx1 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx1},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
ta.Add(vtx0)
|
|
ta.Add(vtx1)
|
|
|
|
sm := make(ids.UniqueBag)
|
|
sm.Add(0, vtx1.id)
|
|
sm.Add(1, vtx1.id)
|
|
ta.RecordPoll(sm)
|
|
|
|
if ta.Finalized() {
|
|
t.Fatalf("An avalanche instance finalized too early")
|
|
} else if !Matches([]ids.ID{vtx1.id}, ta.Preferences().List()) {
|
|
t.Fatalf("Initial frontier failed to be set")
|
|
}
|
|
|
|
ta.RecordPoll(sm)
|
|
|
|
if !ta.Finalized() {
|
|
t.Fatalf("An avalanche instance finalized too late")
|
|
} else if !Matches([]ids.ID{vtx1.id}, ta.Preferences().List()) {
|
|
t.Fatalf("Initial frontier failed to be set")
|
|
} else if tx0.Status() != choices.Rejected {
|
|
t.Fatalf("Tx should have been rejected")
|
|
} else if tx1.Status() != choices.Accepted {
|
|
t.Fatalf("Tx should have been accepted")
|
|
}
|
|
}
|
|
|
|
func TestAvalancheTransitiveVoting(t *testing.T) {
|
|
params := Parameters{
|
|
Parameters: snowball.Parameters{
|
|
Metrics: prometheus.NewRegistry(),
|
|
K: 2,
|
|
Alpha: 2,
|
|
BetaVirtuous: 1,
|
|
BetaRogue: 2,
|
|
},
|
|
Parents: 2,
|
|
BatchSize: 1,
|
|
}
|
|
vts := []Vertex{&Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}, &Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}}
|
|
utxos := []ids.ID{GenerateID(), GenerateID()}
|
|
|
|
ta := Topological{}
|
|
ta.Initialize(snow.DefaultContextTest(), params, vts)
|
|
|
|
tx0 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx0.Ins.Add(utxos[0])
|
|
|
|
vtx0 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx0},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
tx1 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx1.Ins.Add(utxos[1])
|
|
|
|
vtx1 := &Vtx{
|
|
dependencies: []Vertex{vtx0},
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx1},
|
|
height: 2,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
vtx2 := &Vtx{
|
|
dependencies: []Vertex{vtx1},
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx1},
|
|
height: 3,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
ta.Add(vtx0)
|
|
ta.Add(vtx1)
|
|
ta.Add(vtx2)
|
|
|
|
sm1 := make(ids.UniqueBag)
|
|
sm1.Add(0, vtx0.id)
|
|
sm1.Add(1, vtx2.id)
|
|
ta.RecordPoll(sm1)
|
|
|
|
if ta.Finalized() {
|
|
t.Fatalf("An avalanche instance finalized too early")
|
|
} else if !Matches([]ids.ID{vtx2.id}, ta.Preferences().List()) {
|
|
t.Fatalf("Initial frontier failed to be set")
|
|
} else if tx0.Status() != choices.Accepted {
|
|
t.Fatalf("Tx should have been accepted")
|
|
}
|
|
|
|
sm2 := make(ids.UniqueBag)
|
|
sm2.Add(0, vtx2.id)
|
|
sm2.Add(1, vtx2.id)
|
|
ta.RecordPoll(sm2)
|
|
|
|
if !ta.Finalized() {
|
|
t.Fatalf("An avalanche instance finalized too late")
|
|
} else if !Matches([]ids.ID{vtx2.id}, ta.Preferences().List()) {
|
|
t.Fatalf("Initial frontier failed to be set")
|
|
} else if tx0.Status() != choices.Accepted {
|
|
t.Fatalf("Tx should have been accepted")
|
|
} else if tx1.Status() != choices.Accepted {
|
|
t.Fatalf("Tx should have been accepted")
|
|
}
|
|
}
|
|
|
|
func TestAvalancheSplitVoting(t *testing.T) {
|
|
params := Parameters{
|
|
Parameters: snowball.Parameters{
|
|
Metrics: prometheus.NewRegistry(),
|
|
K: 2,
|
|
Alpha: 2,
|
|
BetaVirtuous: 1,
|
|
BetaRogue: 2,
|
|
},
|
|
Parents: 2,
|
|
BatchSize: 1,
|
|
}
|
|
vts := []Vertex{&Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}, &Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}}
|
|
utxos := []ids.ID{GenerateID()}
|
|
|
|
ta := Topological{}
|
|
ta.Initialize(snow.DefaultContextTest(), params, vts)
|
|
|
|
tx0 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx0.Ins.Add(utxos[0])
|
|
|
|
vtx0 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx0},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
vtx1 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx0},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
ta.Add(vtx0)
|
|
ta.Add(vtx1)
|
|
|
|
sm1 := make(ids.UniqueBag)
|
|
sm1.Add(0, vtx0.id)
|
|
sm1.Add(1, vtx1.id)
|
|
ta.RecordPoll(sm1)
|
|
|
|
if !ta.Finalized() {
|
|
t.Fatalf("An avalanche instance finalized too late")
|
|
} else if !Matches([]ids.ID{vtx0.id, vtx1.id}, ta.Preferences().List()) {
|
|
t.Fatalf("Initial frontier failed to be set")
|
|
} else if tx0.Status() != choices.Accepted {
|
|
t.Fatalf("Tx should have been accepted")
|
|
}
|
|
}
|
|
|
|
func TestAvalancheTransitiveRejection(t *testing.T) {
|
|
params := Parameters{
|
|
Parameters: snowball.Parameters{
|
|
Metrics: prometheus.NewRegistry(),
|
|
K: 2,
|
|
Alpha: 2,
|
|
BetaVirtuous: 1,
|
|
BetaRogue: 2,
|
|
},
|
|
Parents: 2,
|
|
BatchSize: 1,
|
|
}
|
|
vts := []Vertex{&Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}, &Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}}
|
|
utxos := []ids.ID{GenerateID(), GenerateID()}
|
|
|
|
ta := Topological{}
|
|
ta.Initialize(snow.DefaultContextTest(), params, vts)
|
|
|
|
tx0 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx0.Ins.Add(utxos[0])
|
|
|
|
vtx0 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx0},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
tx1 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx1.Ins.Add(utxos[0])
|
|
|
|
vtx1 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx1},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
tx2 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx2.Ins.Add(utxos[1])
|
|
|
|
vtx2 := &Vtx{
|
|
dependencies: []Vertex{vtx0},
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx2},
|
|
height: 2,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
ta.Add(vtx0)
|
|
ta.Add(vtx1)
|
|
ta.Add(vtx2)
|
|
|
|
sm := make(ids.UniqueBag)
|
|
sm.Add(0, vtx1.id)
|
|
sm.Add(1, vtx1.id)
|
|
ta.RecordPoll(sm)
|
|
|
|
if ta.Finalized() {
|
|
t.Fatalf("An avalanche instance finalized too early")
|
|
} else if !Matches([]ids.ID{vtx1.id}, ta.Preferences().List()) {
|
|
t.Fatalf("Initial frontier failed to be set")
|
|
}
|
|
|
|
ta.RecordPoll(sm)
|
|
|
|
if ta.Finalized() {
|
|
t.Fatalf("An avalanche instance finalized too early")
|
|
} else if !Matches([]ids.ID{vtx1.id}, ta.Preferences().List()) {
|
|
t.Fatalf("Initial frontier failed to be set")
|
|
} else if tx0.Status() != choices.Rejected {
|
|
t.Fatalf("Tx should have been rejected")
|
|
} else if tx1.Status() != choices.Accepted {
|
|
t.Fatalf("Tx should have been accepted")
|
|
} else if tx2.Status() != choices.Processing {
|
|
t.Fatalf("Tx should not have been decided")
|
|
}
|
|
|
|
ta.preferenceCache = make(map[[32]byte]bool)
|
|
ta.virtuousCache = make(map[[32]byte]bool)
|
|
|
|
ta.update(vtx2)
|
|
}
|
|
|
|
func TestAvalancheVirtuous(t *testing.T) {
|
|
params := Parameters{
|
|
Parameters: snowball.Parameters{
|
|
Metrics: prometheus.NewRegistry(),
|
|
K: 2,
|
|
Alpha: 2,
|
|
BetaVirtuous: 1,
|
|
BetaRogue: 2,
|
|
},
|
|
Parents: 2,
|
|
BatchSize: 1,
|
|
}
|
|
vts := []Vertex{&Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}, &Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}}
|
|
utxos := []ids.ID{GenerateID(), GenerateID()}
|
|
|
|
ta := Topological{}
|
|
ta.Initialize(snow.DefaultContextTest(), params, vts)
|
|
|
|
if virtuous := ta.Virtuous(); virtuous.Len() != 2 {
|
|
t.Fatalf("Wrong number of virtuous.")
|
|
} else if !virtuous.Contains(vts[0].ID()) {
|
|
t.Fatalf("Wrong virtuous")
|
|
} else if !virtuous.Contains(vts[1].ID()) {
|
|
t.Fatalf("Wrong virtuous")
|
|
}
|
|
|
|
tx0 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx0.Ins.Add(utxos[0])
|
|
|
|
vtx0 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx0},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
tx1 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx1.Ins.Add(utxos[0])
|
|
|
|
vtx1 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx1},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
tx2 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx2.Ins.Add(utxos[1])
|
|
|
|
vtx2 := &Vtx{
|
|
dependencies: []Vertex{vtx0},
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx2},
|
|
height: 2,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
ta.Add(vtx0)
|
|
|
|
if virtuous := ta.Virtuous(); virtuous.Len() != 1 {
|
|
t.Fatalf("Wrong number of virtuous.")
|
|
} else if !virtuous.Contains(vtx0.id) {
|
|
t.Fatalf("Wrong virtuous")
|
|
}
|
|
|
|
ta.Add(vtx1)
|
|
|
|
if virtuous := ta.Virtuous(); virtuous.Len() != 1 {
|
|
t.Fatalf("Wrong number of virtuous.")
|
|
} else if !virtuous.Contains(vtx0.id) {
|
|
t.Fatalf("Wrong virtuous")
|
|
}
|
|
|
|
ta.updateFrontiers()
|
|
|
|
if virtuous := ta.Virtuous(); virtuous.Len() != 2 {
|
|
t.Fatalf("Wrong number of virtuous.")
|
|
} else if !virtuous.Contains(vts[0].ID()) {
|
|
t.Fatalf("Wrong virtuous")
|
|
} else if !virtuous.Contains(vts[1].ID()) {
|
|
t.Fatalf("Wrong virtuous")
|
|
}
|
|
|
|
ta.Add(vtx2)
|
|
|
|
if virtuous := ta.Virtuous(); virtuous.Len() != 2 {
|
|
t.Fatalf("Wrong number of virtuous.")
|
|
} else if !virtuous.Contains(vts[0].ID()) {
|
|
t.Fatalf("Wrong virtuous")
|
|
} else if !virtuous.Contains(vts[1].ID()) {
|
|
t.Fatalf("Wrong virtuous")
|
|
}
|
|
|
|
ta.updateFrontiers()
|
|
|
|
if virtuous := ta.Virtuous(); virtuous.Len() != 2 {
|
|
t.Fatalf("Wrong number of virtuous.")
|
|
} else if !virtuous.Contains(vts[0].ID()) {
|
|
t.Fatalf("Wrong virtuous")
|
|
} else if !virtuous.Contains(vts[1].ID()) {
|
|
t.Fatalf("Wrong virtuous")
|
|
}
|
|
}
|
|
|
|
func TestAvalancheIsVirtuous(t *testing.T) {
|
|
params := Parameters{
|
|
Parameters: snowball.Parameters{
|
|
Metrics: prometheus.NewRegistry(),
|
|
K: 2,
|
|
Alpha: 2,
|
|
BetaVirtuous: 1,
|
|
BetaRogue: 2,
|
|
},
|
|
Parents: 2,
|
|
BatchSize: 1,
|
|
}
|
|
vts := []Vertex{&Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}, &Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}}
|
|
utxos := []ids.ID{GenerateID(), GenerateID()}
|
|
|
|
ta := Topological{}
|
|
ta.Initialize(snow.DefaultContextTest(), params, vts)
|
|
|
|
if virtuous := ta.Virtuous(); virtuous.Len() != 2 {
|
|
t.Fatalf("Wrong number of virtuous.")
|
|
} else if !virtuous.Contains(vts[0].ID()) {
|
|
t.Fatalf("Wrong virtuous")
|
|
} else if !virtuous.Contains(vts[1].ID()) {
|
|
t.Fatalf("Wrong virtuous")
|
|
}
|
|
|
|
tx0 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx0.Ins.Add(utxos[0])
|
|
|
|
vtx0 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx0},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
tx1 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx1.Ins.Add(utxos[0])
|
|
|
|
vtx1 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx1},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
if !ta.IsVirtuous(tx0) {
|
|
t.Fatalf("Should be virtuous.")
|
|
} else if !ta.IsVirtuous(tx1) {
|
|
t.Fatalf("Should be virtuous.")
|
|
}
|
|
|
|
ta.Add(vtx0)
|
|
|
|
if !ta.IsVirtuous(tx0) {
|
|
t.Fatalf("Should be virtuous.")
|
|
} else if ta.IsVirtuous(tx1) {
|
|
t.Fatalf("Should not be virtuous.")
|
|
}
|
|
|
|
ta.Add(vtx1)
|
|
|
|
if ta.IsVirtuous(tx0) {
|
|
t.Fatalf("Should not be virtuous.")
|
|
} else if ta.IsVirtuous(tx1) {
|
|
t.Fatalf("Should not be virtuous.")
|
|
}
|
|
}
|
|
|
|
func TestAvalancheQuiesce(t *testing.T) {
|
|
params := Parameters{
|
|
Parameters: snowball.Parameters{
|
|
Metrics: prometheus.NewRegistry(),
|
|
K: 1,
|
|
Alpha: 1,
|
|
BetaVirtuous: 1,
|
|
BetaRogue: 1,
|
|
},
|
|
Parents: 2,
|
|
BatchSize: 1,
|
|
}
|
|
vts := []Vertex{&Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}, &Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}}
|
|
utxos := []ids.ID{GenerateID(), GenerateID()}
|
|
|
|
ta := Topological{}
|
|
ta.Initialize(snow.DefaultContextTest(), params, vts)
|
|
|
|
tx0 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx0.Ins.Add(utxos[0])
|
|
|
|
vtx0 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx0},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
tx1 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx1.Ins.Add(utxos[0])
|
|
|
|
vtx1 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx1},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
tx2 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx2.Ins.Add(utxos[1])
|
|
|
|
vtx2 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx2},
|
|
height: 2,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
ta.Add(vtx0)
|
|
|
|
if ta.Quiesce() {
|
|
t.Fatalf("Shouldn't quiesce")
|
|
}
|
|
|
|
ta.Add(vtx1)
|
|
|
|
if !ta.Quiesce() {
|
|
t.Fatalf("Should quiesce")
|
|
}
|
|
|
|
ta.Add(vtx2)
|
|
|
|
if ta.Quiesce() {
|
|
t.Fatalf("Shouldn't quiesce")
|
|
}
|
|
|
|
sm := make(ids.UniqueBag)
|
|
sm.Add(0, vtx2.id)
|
|
ta.RecordPoll(sm)
|
|
|
|
if !ta.Quiesce() {
|
|
t.Fatalf("Should quiesce")
|
|
}
|
|
}
|
|
|
|
func TestAvalancheOrphans(t *testing.T) {
|
|
params := Parameters{
|
|
Parameters: snowball.Parameters{
|
|
Metrics: prometheus.NewRegistry(),
|
|
K: 1,
|
|
Alpha: 1,
|
|
BetaVirtuous: math.MaxInt32,
|
|
BetaRogue: math.MaxInt32,
|
|
},
|
|
Parents: 2,
|
|
BatchSize: 1,
|
|
}
|
|
vts := []Vertex{&Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}, &Vtx{
|
|
id: GenerateID(),
|
|
status: choices.Accepted,
|
|
}}
|
|
utxos := []ids.ID{GenerateID(), GenerateID()}
|
|
|
|
ta := Topological{}
|
|
ta.Initialize(snow.DefaultContextTest(), params, vts)
|
|
|
|
tx0 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx0.Ins.Add(utxos[0])
|
|
|
|
vtx0 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx0},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
tx1 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx1.Ins.Add(utxos[0])
|
|
|
|
vtx1 := &Vtx{
|
|
dependencies: vts,
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx1},
|
|
height: 1,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
tx2 := &snowstorm.TestTx{
|
|
Identifier: GenerateID(),
|
|
Stat: choices.Processing,
|
|
}
|
|
tx2.Ins.Add(utxos[1])
|
|
|
|
vtx2 := &Vtx{
|
|
dependencies: []Vertex{vtx0},
|
|
id: GenerateID(),
|
|
txs: []snowstorm.Tx{tx2},
|
|
height: 2,
|
|
status: choices.Processing,
|
|
}
|
|
|
|
ta.Add(vtx0)
|
|
|
|
if orphans := ta.Orphans(); orphans.Len() != 0 {
|
|
t.Fatalf("Wrong number of orphans")
|
|
}
|
|
|
|
ta.Add(vtx1)
|
|
|
|
if orphans := ta.Orphans(); orphans.Len() != 0 {
|
|
t.Fatalf("Wrong number of orphans")
|
|
}
|
|
|
|
ta.Add(vtx2)
|
|
|
|
if orphans := ta.Orphans(); orphans.Len() != 0 {
|
|
t.Fatalf("Wrong number of orphans")
|
|
}
|
|
|
|
sm := make(ids.UniqueBag)
|
|
sm.Add(0, vtx1.id)
|
|
ta.RecordPoll(sm)
|
|
|
|
if orphans := ta.Orphans(); orphans.Len() != 1 {
|
|
t.Fatalf("Wrong number of orphans")
|
|
} else if !orphans.Contains(tx2.ID()) {
|
|
t.Fatalf("Wrong orphan")
|
|
}
|
|
}
|