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

Testing: Fix voterTracker tests #4441

Merged
merged 1 commit into from
Aug 22, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 65 additions & 21 deletions ledger/voters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"testing"

"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/crypto/merklesignature"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
Expand All @@ -30,12 +31,46 @@ import (
"github.com/stretchr/testify/require"
)

func addBlockToAccountsUpdate(blk bookkeeping.Block, ao *onlineAccounts) {
func addBlockToAccountsUpdate(blk bookkeeping.Block, ao *onlineAccounts, totals ledgercore.AccountTotals) {
updates := ledgercore.MakeAccountDeltas(1)
delta := ledgercore.MakeStateDelta(&blk.BlockHeader, 0, updates.Len(), 0)
delta.Accts.MergeAccounts(updates)
delta.Totals = totals
ao.newBlock(blk, delta)
}

func checkVoters(a *require.Assertions, ao *onlineAccounts, expectedSize uint64) {
a.Equal(expectedSize, uint64(len(ao.voters.votersForRoundCache)))
for _, v := range ao.voters.votersForRoundCache {
err := v.Wait()
a.NoError(err)
a.NotZero(v.TotalWeight)
a.NotZero(len(v.Participants))
a.NotZero(v.Tree.NumOfElements)
}
}

func makeRandomOnlineAccounts(numberOfAccounts uint64) map[basics.Address]basics.AccountData {
res := make(map[basics.Address]basics.AccountData)

for i := uint64(0); i < numberOfAccounts; i++ {
var data basics.AccountData

// Avoid overflowing totals
data.MicroAlgos.Raw = crypto.RandUint64() % (1 << 32)

data.Status = basics.Online
data.VoteLastValid = 10000000

data.VoteFirstValid = 0
data.RewardsBase = 0

res[ledgertesting.RandomAddress()] = data
}

return res
}

func TestVoterTrackerDeleteVotersAfterStateproofConfirmed(t *testing.T) {
partitiontest.PartitionTest(t)
a := require.New(t)
Expand All @@ -44,7 +79,7 @@ func TestVoterTrackerDeleteVotersAfterStateproofConfirmed(t *testing.T) {
numOfIntervals := config.Consensus[protocol.ConsensusCurrentVersion].StateProofMaxRecoveryIntervals - 1
lookbackForTest := config.Consensus[protocol.ConsensusCurrentVersion].StateProofVotersLookback

accts := []map[basics.Address]basics.AccountData{ledgertesting.RandomAccounts(20, true)}
accts := []map[basics.Address]basics.AccountData{makeRandomOnlineAccounts(20)}

pooldata := basics.AccountData{}
pooldata.MicroAlgos.Raw = 1000 * 1000 * 1000 * 1000
Expand All @@ -64,15 +99,18 @@ func TestVoterTrackerDeleteVotersAfterStateproofConfirmed(t *testing.T) {
defer au.close()
defer ao.close()

_, totals, err := au.LatestTotals()
require.NoError(t, err)

i := uint64(1)
// adding blocks to the voterstracker (in order to pass the numOfIntervals*stateproofInterval we add 1)
for ; i < (numOfIntervals*intervalForTest)+1; i++ {
block := randomBlock(basics.Round(i))
block.block.CurrentProtocol = protocol.ConsensusCurrentVersion
addBlockToAccountsUpdate(block.block, ao)
addBlockToAccountsUpdate(block.block, ao, totals)
}

a.Equal(numOfIntervals, uint64(len(ao.voters.votersForRoundCache)))
checkVoters(a, ao, numOfIntervals)
a.Equal(basics.Round(intervalForTest-lookbackForTest), ao.voters.lowestRound(basics.Round(i)))

block := randomBlock(basics.Round(i))
Expand All @@ -84,23 +122,23 @@ func TestVoterTrackerDeleteVotersAfterStateproofConfirmed(t *testing.T) {
stateTracking.StateProofNextRound = basics.Round((numOfIntervals - 1) * intervalForTest)
block.block.BlockHeader.StateProofTracking = make(map[protocol.StateProofType]bookkeeping.StateProofTrackingData)
block.block.BlockHeader.StateProofTracking[protocol.StateProofBasic] = stateTracking
addBlockToAccountsUpdate(block.block, ao)
addBlockToAccountsUpdate(block.block, ao, totals)

// the tracker should have 3 entries
// - voters to confirm the numOfIntervals - 1 th interval
// - voters to confirm the numOfIntervals th interval
// - voters to confirm the numOfIntervals + 1 th interval
a.Equal(uint64(3), uint64(len(ao.voters.votersForRoundCache)))
checkVoters(a, ao, 3)
a.Equal(basics.Round((numOfIntervals-2)*intervalForTest-lookbackForTest), ao.voters.lowestRound(basics.Round(i)))

block = randomBlock(basics.Round(i))
block.block.CurrentProtocol = protocol.ConsensusCurrentVersion
stateTracking.StateProofNextRound = basics.Round(numOfIntervals * intervalForTest)
block.block.BlockHeader.StateProofTracking = make(map[protocol.StateProofType]bookkeeping.StateProofTrackingData)
block.block.BlockHeader.StateProofTracking[protocol.StateProofBasic] = stateTracking
addBlockToAccountsUpdate(block.block, ao)
addBlockToAccountsUpdate(block.block, ao, totals)

a.Equal(uint64(2), uint64(len(ao.voters.votersForRoundCache)))
checkVoters(a, ao, 2)
a.Equal(basics.Round((numOfIntervals-1)*intervalForTest-lookbackForTest), ao.voters.lowestRound(basics.Round(i)))
}

Expand All @@ -112,7 +150,7 @@ func TestLimitVoterTracker(t *testing.T) {
recoveryIntervalForTests := config.Consensus[protocol.ConsensusCurrentVersion].StateProofMaxRecoveryIntervals
lookbackForTest := config.Consensus[protocol.ConsensusCurrentVersion].StateProofVotersLookback

accts := []map[basics.Address]basics.AccountData{ledgertesting.RandomAccounts(20, true)}
accts := []map[basics.Address]basics.AccountData{makeRandomOnlineAccounts(20)}

pooldata := basics.AccountData{}
pooldata.MicroAlgos.Raw = 1000 * 1000 * 1000 * 1000
Expand All @@ -132,6 +170,9 @@ func TestLimitVoterTracker(t *testing.T) {
defer au.close()
defer ao.close()

_, totals, err := au.LatestTotals()
require.NoError(t, err)

i := uint64(1)

// since the first state proof is expected to happen on stateproofInterval*2 we would start give-up on state proofs
Expand All @@ -141,51 +182,51 @@ func TestLimitVoterTracker(t *testing.T) {
for ; i < intervalForTest*(recoveryIntervalForTests+2); i++ {
block := randomBlock(basics.Round(i))
block.block.CurrentProtocol = protocol.ConsensusCurrentVersion
addBlockToAccountsUpdate(block.block, ao)
addBlockToAccountsUpdate(block.block, ao, totals)
}

// the votersForRoundCache should contains recoveryIntervalForTests+2 elements:
// recoveryIntervalForTests - since this is the recovery interval
// + 1 - since votersForRoundCache would contain the votersForRound for the next state proof to come
// + 1 - in order to confirm recoveryIntervalForTests number of state proofs we need recoveryIntervalForTests + 1 headers (for the commitment)
a.Equal(recoveryIntervalForTests+2, uint64(len(ao.voters.votersForRoundCache)))
checkVoters(a, ao, recoveryIntervalForTests+2)
a.Equal(basics.Round(config.Consensus[protocol.ConsensusCurrentVersion].StateProofInterval-lookbackForTest), ao.voters.lowestRound(basics.Round(i)))

// after adding the round intervalForTest*(recoveryIntervalForTests+3)+1 we expect the voter tracker to remove voters
for ; i < intervalForTest*(recoveryIntervalForTests+3)+1; i++ {
block := randomBlock(basics.Round(i))
block.block.CurrentProtocol = protocol.ConsensusCurrentVersion
addBlockToAccountsUpdate(block.block, ao)
addBlockToAccountsUpdate(block.block, ao, totals)
}

a.Equal(recoveryIntervalForTests+2, uint64(len(ao.voters.votersForRoundCache)))
checkVoters(a, ao, recoveryIntervalForTests+2)
a.Equal(basics.Round(config.Consensus[protocol.ConsensusCurrentVersion].StateProofInterval*2-lookbackForTest), ao.voters.lowestRound(basics.Round(i)))

// after adding the round intervalForTest*(recoveryIntervalForTests+3)+1 we expect the voter tracker to remove voters
for ; i < intervalForTest*(recoveryIntervalForTests+4)+1; i++ {
block := randomBlock(basics.Round(i))
block.block.CurrentProtocol = protocol.ConsensusCurrentVersion
addBlockToAccountsUpdate(block.block, ao)
addBlockToAccountsUpdate(block.block, ao, totals)
}
a.Equal(recoveryIntervalForTests+2, uint64(len(ao.voters.votersForRoundCache)))
checkVoters(a, ao, recoveryIntervalForTests+2)
a.Equal(basics.Round(config.Consensus[protocol.ConsensusCurrentVersion].StateProofInterval*3-lookbackForTest), ao.voters.lowestRound(basics.Round(i)))

// if the last round of the intervalForTest has not been added to the ledger the votersTracker would
// retain one more element
for ; i < intervalForTest*(recoveryIntervalForTests+5); i++ {
block := randomBlock(basics.Round(i))
block.block.CurrentProtocol = protocol.ConsensusCurrentVersion
addBlockToAccountsUpdate(block.block, ao)
addBlockToAccountsUpdate(block.block, ao, totals)
}
a.Equal(recoveryIntervalForTests+3, uint64(len(ao.voters.votersForRoundCache)))
checkVoters(a, ao, recoveryIntervalForTests+3)
a.Equal(basics.Round(config.Consensus[protocol.ConsensusCurrentVersion].StateProofInterval*3-lookbackForTest), ao.voters.lowestRound(basics.Round(i)))

for ; i < intervalForTest*(recoveryIntervalForTests+5)+1; i++ {
block := randomBlock(basics.Round(i))
block.block.CurrentProtocol = protocol.ConsensusCurrentVersion
addBlockToAccountsUpdate(block.block, ao)
addBlockToAccountsUpdate(block.block, ao, totals)
}
a.Equal(recoveryIntervalForTests+2, uint64(len(ao.voters.votersForRoundCache)))
checkVoters(a, ao, recoveryIntervalForTests+2)
a.Equal(basics.Round(config.Consensus[protocol.ConsensusCurrentVersion].StateProofInterval*4-lookbackForTest), ao.voters.lowestRound(basics.Round(i)))
}

Expand All @@ -196,7 +237,7 @@ func TestTopNAccountsThatHaveNoMssKeys(t *testing.T) {
intervalForTest := config.Consensus[protocol.ConsensusCurrentVersion].StateProofInterval
lookbackForTest := config.Consensus[protocol.ConsensusCurrentVersion].StateProofVotersLookback

accts := []map[basics.Address]basics.AccountData{ledgertesting.RandomAccounts(20, true)}
accts := []map[basics.Address]basics.AccountData{makeRandomOnlineAccounts(20)}

pooldata := basics.AccountData{}
pooldata.MicroAlgos.Raw = 1000 * 1000 * 1000 * 1000
Expand All @@ -216,11 +257,14 @@ func TestTopNAccountsThatHaveNoMssKeys(t *testing.T) {
defer au.close()
defer ao.close()

_, totals, err := au.LatestTotals()
require.NoError(t, err)

i := uint64(1)
for ; i < (intervalForTest)+1; i++ {
block := randomBlock(basics.Round(i))
block.block.CurrentProtocol = protocol.ConsensusCurrentVersion
addBlockToAccountsUpdate(block.block, ao)
addBlockToAccountsUpdate(block.block, ao, totals)
}

top, err := ao.voters.getVoters(basics.Round(intervalForTest - lookbackForTest))
Expand Down