Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: Fix flaky TestAccountSelected test #5788

Merged
merged 4 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 13 additions & 5 deletions data/committee/common_test.go
Expand Up @@ -47,11 +47,19 @@ func signTx(s *crypto.SignatureSecrets, t transactions.Transaction) transactions
return t.Sign(s)
}

func testingenv(t testing.TB, numAccounts, numTxs int) (selectionParameterFn, selectionParameterListFn, basics.Round, []basics.Address, []*crypto.SignatureSecrets, []*crypto.VrfPrivkey, []*crypto.OneTimeSignatureSecrets, []transactions.SignedTxn) {
return testingenvMoreKeys(t, numAccounts, numTxs, uint(5))
// testingenv creates a random set of participating accounts and random transactions between them, and
// the associated selection parameters for use testing committee membership and credential validation.
// seedGen is provided as an external source of randomness for the selection seed and transaction notes;
// if the caller persists seedGen between calls to testingenv, each iteration that calls testingenv will
// exercise a new selection seed.
func testingenv(t testing.TB, numAccounts, numTxs int, seedGen io.Reader) (selectionParameterFn, selectionParameterListFn, basics.Round, []basics.Address, []*crypto.SignatureSecrets, []*crypto.VrfPrivkey, []*crypto.OneTimeSignatureSecrets, []transactions.SignedTxn) {
return testingenvMoreKeys(t, numAccounts, numTxs, uint(5), seedGen)
}

func testingenvMoreKeys(t testing.TB, numAccounts, numTxs int, keyBatchesForward uint) (selectionParameterFn, selectionParameterListFn, basics.Round, []basics.Address, []*crypto.SignatureSecrets, []*crypto.VrfPrivkey, []*crypto.OneTimeSignatureSecrets, []transactions.SignedTxn) {
func testingenvMoreKeys(t testing.TB, numAccounts, numTxs int, keyBatchesForward uint, seedGen io.Reader) (selectionParameterFn, selectionParameterListFn, basics.Round, []basics.Address, []*crypto.SignatureSecrets, []*crypto.VrfPrivkey, []*crypto.OneTimeSignatureSecrets, []transactions.SignedTxn) {
algorandskiy marked this conversation as resolved.
Show resolved Hide resolved
if seedGen == nil {
seedGen = rand.New(rand.NewSource(1)) // same source as setting GODEBUG=randautoseed=0, same as pre-Go 1.20 default seed
}
P := numAccounts // n accounts
TXs := numTxs // n txns
maxMoneyAtStart := 100000 // max money start
Expand Down Expand Up @@ -89,7 +97,7 @@ func testingenvMoreKeys(t testing.TB, numAccounts, numTxs int, keyBatchesForward
}

var seed Seed
rand.Read(seed[:])
seedGen.Read(seed[:])

tx := make([]transactions.SignedTxn, TXs)
for i := 0; i < TXs; i++ {
Expand All @@ -115,7 +123,7 @@ func testingenvMoreKeys(t testing.TB, numAccounts, numTxs int, keyBatchesForward
Amount: amt,
},
}
rand.Read(t.Note)
seedGen.Read(t.Note) // to match output from previous versions, which shared global RNG for seed & note
tx[i] = t.Sign(secrets[send])
}

Expand Down
37 changes: 28 additions & 9 deletions data/committee/credential_test.go
Expand Up @@ -20,6 +20,7 @@ import (
"math/rand" // used for replicability of sortition benchmark
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/algorand/go-algorand/data/basics"
Expand All @@ -31,9 +32,10 @@ import (
func TestAccountSelected(t *testing.T) {
partitiontest.PartitionTest(t)

seedGen := rand.New(rand.NewSource(1))
N := 1
for i := 0; i < N; i++ {
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000, seedGen)
period := Period(0)

leaders := uint64(0)
Expand Down Expand Up @@ -85,13 +87,18 @@ func TestAccountSelected(t *testing.T) {
if (committee < uint64(0.8*float64(step.CommitteeSize(proto)))) || (committee > uint64(1.2*float64(step.CommitteeSize(proto)))) {
t.Errorf("bad number of committee members %v expected %v", committee, step.CommitteeSize(proto))
}
if i == 0 {
// pin down deterministic outputs for first iteration
assert.EqualValues(t, 17, leaders)
assert.EqualValues(t, 2918, committee)
}
}
}

func TestRichAccountSelected(t *testing.T) {
partitiontest.PartitionTest(t)

selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 10, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 10, 2000, nil)

period := Period(0)
ok, record, selectionSeed, _ := selParams(addresses[0])
Expand Down Expand Up @@ -139,16 +146,20 @@ func TestRichAccountSelected(t *testing.T) {
if (ccred.Weight < uint64(0.4*float64(step.CommitteeSize(proto)))) || (ccred.Weight > uint64(.6*float64(step.CommitteeSize(proto)))) {
t.Errorf("bad number of committee members %v expected %v", ccred.Weight, step.CommitteeSize(proto))
}
// pin down deterministic outputs, given initial seed values
assert.EqualValues(t, 6, lcred.Weight)
assert.EqualValues(t, 735, ccred.Weight)
}

func TestPoorAccountSelectedLeaders(t *testing.T) {
partitiontest.PartitionTest(t)

seedGen := rand.New(rand.NewSource(1))
N := 2
failsLeaders := 0
leaders := make([]uint64, N)
for i := 0; i < N; i++ {
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000, seedGen)
period := Period(0)
for j := range addresses {
ok, record, selectionSeed, _ := selParams(addresses[j])
Expand Down Expand Up @@ -184,15 +195,19 @@ func TestPoorAccountSelectedLeaders(t *testing.T) {
if failsLeaders == 2 {
t.Errorf("bad number of leaders %v expected %v", leaders, proto.NumProposers)
}
// pin down deterministic outputs, given initial seed values
assert.EqualValues(t, 18, leaders[0])
assert.EqualValues(t, 20, leaders[1])
}

func TestPoorAccountSelectedCommittee(t *testing.T) {
partitiontest.PartitionTest(t)

seedGen := rand.New(rand.NewSource(1))
N := 1
committee := uint64(0)
for i := 0; i < N; i++ {
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000, seedGen)
period := Period(0)

step := Cert
Expand Down Expand Up @@ -223,15 +238,19 @@ func TestPoorAccountSelectedCommittee(t *testing.T) {
if (committee < uint64(0.8*float64(step.CommitteeSize(proto)))) || (committee > uint64(1.2*float64(step.CommitteeSize(proto)))) {
t.Errorf("bad number of committee members %v expected %v", committee, step.CommitteeSize(proto))
}
if i == 0 { // pin down deterministic committee size, given initial seed value
assert.EqualValues(t, 1513, committee)
}
}
}

func TestNoMoneyAccountNotSelected(t *testing.T) {
partitiontest.PartitionTest(t)

seedGen := rand.New(rand.NewSource(1))
N := 1
for i := 0; i < N; i++ {
selParams, _, round, addresses, _, _, _, _ := testingenv(t, 10, 2000)
selParams, _, round, addresses, _, _, _, _ := testingenv(t, 10, 2000, seedGen)
lookback := basics.Round(2*proto.SeedRefreshInterval + proto.SeedLookback + 1)
gen := rand.New(rand.NewSource(2))
_, _, zeroVRFSecret, _ := newAccount(t, gen, lookback, 5)
Expand Down Expand Up @@ -262,7 +281,7 @@ func TestNoMoneyAccountNotSelected(t *testing.T) {
func TestLeadersSelected(t *testing.T) {
partitiontest.PartitionTest(t)

selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000, nil)

period := Period(0)
step := Propose
Expand Down Expand Up @@ -294,7 +313,7 @@ func TestLeadersSelected(t *testing.T) {
func TestCommitteeSelected(t *testing.T) {
partitiontest.PartitionTest(t)

selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000, nil)

period := Period(0)
step := Soft
Expand Down Expand Up @@ -326,7 +345,7 @@ func TestCommitteeSelected(t *testing.T) {
func TestAccountNotSelected(t *testing.T) {
partitiontest.PartitionTest(t)

selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(t, 100, 2000, nil)
period := Period(0)
leaders := uint64(0)
for i := range addresses {
Expand Down Expand Up @@ -356,7 +375,7 @@ func TestAccountNotSelected(t *testing.T) {

// TODO update to remove VRF verification overhead
func BenchmarkSortition(b *testing.B) {
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(b, 100, 2000)
selParams, _, round, addresses, _, vrfSecrets, _, _ := testingenv(b, 100, 2000, nil)

period := Period(0)
step := Soft
Expand Down