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

catchpoints: more support for EnableOnlineAccountCatchpoints #6214

Merged
8 changes: 8 additions & 0 deletions cmd/catchpointdump/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@
if err != nil {
reportErrorf("Unable to print state proof verification database : %v", err)
}
err = printOnlineAccounts(ledgerTrackerFilename, ledgerTrackerStaging, outFile)
if err != nil {
reportErrorf("Unable to print online accounts : %v", err)

Check warning on line 93 in cmd/catchpointdump/database.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/database.go#L91-L93

Added lines #L91 - L93 were not covered by tests
}
err = printOnlineRoundParams(ledgerTrackerFilename, ledgerTrackerStaging, outFile)
if err != nil {
reportErrorf("Unable to print online round params : %v", err)

Check warning on line 97 in cmd/catchpointdump/database.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/database.go#L95-L97

Added lines #L95 - L97 were not covered by tests
}
},
}

Expand Down
86 changes: 84 additions & 2 deletions cmd/catchpointdump/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,14 @@
if err != nil {
reportErrorf("Unable to print state proof verification database : %v", err)
}
err = printOnlineAccounts("./ledger.tracker.sqlite", true, outFile)
if err != nil {
reportErrorf("Unable to print online accounts : %v", err)

Check warning on line 147 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L145-L147

Added lines #L145 - L147 were not covered by tests
}
err = printOnlineRoundParams("./ledger.tracker.sqlite", true, outFile)
if err != nil {
reportErrorf("Unable to print online round params : %v", err)

Check warning on line 151 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L149-L151

Added lines #L149 - L151 were not covered by tests
}
}
},
}
Expand Down Expand Up @@ -219,8 +227,17 @@
if err != nil {
return fileHeader, err
}
fmt.Printf("accounts digest=%s, spver digest=%s, onlineaccounts digest=%s onlineroundparams digest=%s\n\n",
fmt.Printf("accounts digest=%s, spver digest=%s, onlineaccounts digest=%s onlineroundparams digest=%s\n",

Check warning on line 230 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L230

Added line #L230 was not covered by tests
balanceHash, spverHash, onlineAccountsHash, onlineRoundParamsHash)

fmt.Printf("Catchpoint label: %s\n", fileHeader.Catchpoint)

Check warning on line 233 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L233

Added line #L233 was not covered by tests
algorandskiy marked this conversation as resolved.
Show resolved Hide resolved
// make v7 label
v7Label := ledgercore.MakeCatchpointLabelMakerV7(fileHeader.BlocksRound, &fileHeader.BlockHeaderDigest, &balanceHash, fileHeader.Totals, &spverHash)
fmt.Printf("catchpoint v7 label: %s\n", ledgercore.MakeLabel(v7Label))

Check warning on line 236 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L235-L236

Added lines #L235 - L236 were not covered by tests
gmalouf marked this conversation as resolved.
Show resolved Hide resolved

// make v8 label (current)
v8Label := ledgercore.MakeCatchpointLabelMakerCurrent(fileHeader.BlocksRound, &fileHeader.BlockHeaderDigest, &balanceHash, fileHeader.Totals, &spverHash, &onlineAccountsHash, &onlineRoundParamsHash)
fmt.Printf("catchpoint v8 label: %s\n\n", ledgercore.MakeLabel(v8Label))

Check warning on line 240 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L239-L240

Added lines #L239 - L240 were not covered by tests
}
return fileHeader, nil
}
Expand Down Expand Up @@ -296,6 +313,8 @@
"Catchpoint: %s",
"Total Accounts: %d",
"Total KVs: %d",
"Total Online Accounts: %d",
"Total Online Round Params: %d",

Check warning on line 317 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L316-L317

Added lines #L316 - L317 were not covered by tests
"Total Chunks: %d",
}
var headerValues = []interface{}{
Expand All @@ -306,6 +325,8 @@
fileHeader.Catchpoint,
fileHeader.TotalAccounts,
fileHeader.TotalKVs,
fileHeader.TotalOnlineAccounts,
fileHeader.TotalOnlineRoundParams,

Check warning on line 329 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L328-L329

Added lines #L328 - L329 were not covered by tests
fileHeader.TotalChunks,
}
// safety check
Expand Down Expand Up @@ -511,7 +532,6 @@
}

func printKeyValueStore(databaseName string, stagingTables bool, outFile *os.File) error {
fmt.Printf("\n")
printDumpingCatchpointProgressLine(0, 50, 0)
lastProgressUpdate := time.Now()
progress := uint64(0)
Expand Down Expand Up @@ -560,3 +580,65 @@
return nil
})
}

func printOnlineAccounts(databaseName string, stagingTables bool, outFile *os.File) error {
fileWriter := bufio.NewWriterSize(outFile, 1024*1024)
defer fileWriter.Flush()

Check warning on line 586 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L584-L586

Added lines #L584 - L586 were not covered by tests

dbAccessor, err := db.MakeAccessor(databaseName, true, false)
if err != nil || dbAccessor.Handle == nil {
return err

Check warning on line 590 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L588-L590

Added lines #L588 - L590 were not covered by tests
}

return dbAccessor.Atomic(func(ctx context.Context, tx *sql.Tx) error {
rows, err := sqlitedriver.MakeOnlineAccountsIter(ctx, tx, stagingTables, 0)
if err != nil {
return err

Check warning on line 596 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L593-L596

Added lines #L593 - L596 were not covered by tests
}
defer rows.Close()
for rows.Next() {
row, err := rows.GetItem()
if err != nil {
return err

Check warning on line 602 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L598-L602

Added lines #L598 - L602 were not covered by tests
}
jsonData, err := json.Marshal(row)
if err != nil {
return err

Check warning on line 606 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L604-L606

Added lines #L604 - L606 were not covered by tests
}

fmt.Fprintf(fileWriter, "onlineaccount: %s\n", string(jsonData))

Check warning on line 609 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L609

Added line #L609 was not covered by tests
}
return nil

Check warning on line 611 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L611

Added line #L611 was not covered by tests
})
}

func printOnlineRoundParams(databaseName string, stagingTables bool, outFile *os.File) error {
fileWriter := bufio.NewWriterSize(outFile, 1024*1024)
defer fileWriter.Flush()

Check warning on line 617 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L615-L617

Added lines #L615 - L617 were not covered by tests

dbAccessor, err := db.MakeAccessor(databaseName, true, false)
if err != nil || dbAccessor.Handle == nil {
return err

Check warning on line 621 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L619-L621

Added lines #L619 - L621 were not covered by tests
}

return dbAccessor.Atomic(func(ctx context.Context, tx *sql.Tx) error {
rows, err := sqlitedriver.MakeOnlineRoundParamsIter(ctx, tx, stagingTables, 0)
if err != nil {
return err

Check warning on line 627 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L624-L627

Added lines #L624 - L627 were not covered by tests
}
defer rows.Close()
for rows.Next() {
row, err := rows.GetItem()
if err != nil {
return err

Check warning on line 633 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L629-L633

Added lines #L629 - L633 were not covered by tests
}
jsonData, err := json.Marshal(row)
if err != nil {
return err

Check warning on line 637 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L635-L637

Added lines #L635 - L637 were not covered by tests
}

fmt.Fprintf(fileWriter, "onlineroundparams: %s\n", string(jsonData))

Check warning on line 640 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L640

Added line #L640 was not covered by tests
}
return nil

Check warning on line 642 in cmd/catchpointdump/file.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/file.go#L642

Added line #L642 was not covered by tests
})
}
9 changes: 8 additions & 1 deletion cmd/catchpointdump/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,14 @@
if err != nil {
return err
}

err = printOnlineAccounts("./ledger.tracker.sqlite", true, outFile)
if err != nil {
return err

Check warning on line 370 in cmd/catchpointdump/net.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/net.go#L368-L370

Added lines #L368 - L370 were not covered by tests
}
err = printOnlineRoundParams("./ledger.tracker.sqlite", true, outFile)
if err != nil {
return err

Check warning on line 374 in cmd/catchpointdump/net.go

View check run for this annotation

Codecov / codecov/patch

cmd/catchpointdump/net.go#L372-L374

Added lines #L372 - L374 were not covered by tests
}
}
return nil
}
94 changes: 92 additions & 2 deletions ledger/acctdeltas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2750,6 +2750,27 @@ func TestAccountOnlineRoundParams(t *testing.T) {
require.Equal(t, onlineRoundParams, dbOnlineRoundParams[1:])
require.Equal(t, maxRounds, int(endRound))

// Use MakeOnlineRoundParamsIter to dump all data, starting from 10
iter, err := sqlitedriver.MakeOnlineRoundParamsIter(context.Background(), tx, false, 10)
require.NoError(t, err)
defer iter.Close()
var roundParamsIterData []ledgercore.OnlineRoundParamsData
var roundParamsIterLastRound basics.Round
for iter.Next() {
item, err := iter.GetItem()
require.NoError(t, err)

var orpData ledgercore.OnlineRoundParamsData
err = protocol.Decode(item.Data, &orpData)
require.NoError(t, err)
roundParamsIterLastRound = item.Round

roundParamsIterData = append(roundParamsIterData, orpData)
}
require.Equal(t, onlineRoundParams[9:], roundParamsIterData)
require.Equal(t, maxRounds, int(roundParamsIterLastRound))

// Prune online round params to rnd 10
err = arw.AccountsPruneOnlineRoundParams(10)
require.NoError(t, err)

Expand All @@ -2772,6 +2793,15 @@ func TestAccountOnlineRoundParams(t *testing.T) {
func TestOnlineAccountsDeletion(t *testing.T) {
partitiontest.PartitionTest(t)

t.Run("delete", func(t *testing.T) {
runTestOnlineAccountsDeletion(t, testOnlineAccountsDeletion)
})
t.Run("excludeBefore", func(t *testing.T) {
runTestOnlineAccountsDeletion(t, testOnlineAccountsExcludeBefore)
})
}

func runTestOnlineAccountsDeletion(t *testing.T, assertFunc func(*testing.T, basics.Address, basics.Address, *sql.Tx)) {
dbs, _ := storetesting.DbOpenTest(t, true)
storetesting.SetDbLogging(t, dbs)
defer dbs.Close()
Expand All @@ -2783,8 +2813,6 @@ func TestOnlineAccountsDeletion(t *testing.T) {
var accts map[basics.Address]basics.AccountData
sqlitedriver.AccountsInitTest(t, tx, accts, protocol.ConsensusCurrentVersion)

arw := sqlitedriver.NewAccountsSQLReaderWriter(tx)

updates := compactOnlineAccountDeltas{}
addrA := ledgertesting.RandomAddress()
addrB := ledgertesting.RandomAddress()
Expand Down Expand Up @@ -2837,6 +2865,12 @@ func TestOnlineAccountsDeletion(t *testing.T) {
require.NoError(t, err)
require.Len(t, updated, 5)

assertFunc(t, addrA, addrB, tx)
}

func testOnlineAccountsDeletion(t *testing.T, addrA, addrB basics.Address, tx *sql.Tx) {
arw := sqlitedriver.NewAccountsSQLReaderWriter(tx)

queries, err := sqlitedriver.OnlineAccountsInitDbQueries(tx)
require.NoError(t, err)

Expand Down Expand Up @@ -2898,6 +2932,62 @@ func TestOnlineAccountsDeletion(t *testing.T) {
}
}

// same assertions as testOnlineAccountsDeletion but with excludeBefore
func testOnlineAccountsExcludeBefore(t *testing.T, addrA, addrB basics.Address, tx *sql.Tx) {
// Use MakeOnlineAccountsIter to dump all data, starting from rnd
getAcctDataForRound := func(rnd basics.Round, expectedCount int64) map[basics.Address][]*encoded.OnlineAccountRecordV6 {
it, err := sqlitedriver.MakeOnlineAccountsIter(context.Background(), tx, false, rnd)
require.NoError(t, err)

var count int64
ret := make(map[basics.Address][]*encoded.OnlineAccountRecordV6)
for it.Next() {
acct, err := it.GetItem()
require.NoError(t, err)
ret[acct.Address] = append(ret[acct.Address], acct)
count++
}
require.Equal(t, expectedCount, count)
return ret
}

for _, rnd := range []basics.Round{1, 2, 3} {
vals := getAcctDataForRound(rnd, 5)

history, ok := vals[addrA]
require.True(t, ok)
require.Len(t, history, 3)

history, ok = vals[addrB]
require.True(t, ok)
require.Len(t, history, 2)
}

for _, rnd := range []basics.Round{4, 5, 6, 7} {
vals := getAcctDataForRound(rnd, 3)

history, ok := vals[addrA]
require.True(t, ok)
require.Len(t, history, 1)

history, ok = vals[addrB]
require.True(t, ok)
require.Len(t, history, 2)
}

for _, rnd := range []basics.Round{8, 9} {
vals := getAcctDataForRound(rnd, 2)

history, ok := vals[addrA]
require.True(t, ok)
require.Len(t, history, 1)

history, ok = vals[addrB]
require.True(t, ok)
require.Len(t, history, 1)
}
}

type mockOnlineAccountsErrorWriter struct {
}

Expand Down
49 changes: 49 additions & 0 deletions ledger/acctonline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,7 @@ func TestAcctOnlineVotersLongerHistory(t *testing.T) {
require.NoError(t, err)
require.Equal(t, oa.latest()-basics.Round(conf.MaxAcctLookback), endRound)
require.Equal(t, maxBlocks-int(lowest)-int(conf.MaxAcctLookback)+1, len(dbOnlineRoundParams))
require.Equal(t, endRound, oa.cachedDBRoundOnline)

_, err = oa.onlineTotalsEx(lowest)
require.NoError(t, err)
Expand All @@ -1324,6 +1325,54 @@ func TestAcctOnlineVotersLongerHistory(t *testing.T) {
// ensure the cache size for addrA does not have more entries than maxBalLookback + 1
// +1 comes from the deletion before X without checking account state at X
require.Equal(t, maxBalLookback+1, oa.onlineAccountsCache.accounts[addrA].Len())

// Test if "excludeBefore" argument works for MakeOnlineAccountsIter & MakeOnlineRoundParamsIter
// when longer history is being used. Exclude rows older than round=lowest+2
excludeRound := lowest + 2

// Test MakeOnlineAccountsIter
var foundCount int
err = oa.dbs.Snapshot(func(ctx context.Context, tx trackerdb.SnapshotScope) error {
// read staging = false, excludeBefore = excludeRound
it, err2 := tx.MakeOnlineAccountsIter(ctx, false, excludeRound)
require.NoError(t, err2)
defer it.Close()

firstSeen := make(map[basics.Address]basics.Round)
for it.Next() {
acct, acctErr := it.GetItem()
require.NoError(t, acctErr)
// We expect all rows to either:
// - have updRound >= excludeRound
// - or have updRound < excludeRound, and only appear once in the iteration (no updates since excludeRound)
if acct.UpdateRound < excludeRound {
require.NotContains(t, firstSeen, acct.Address, "MakeOnlineAccountsIter produced two rows acct %s for dbRound %d updRound %d < excludeRound %d (first seen %d)", acct.Address, endRound, acct.UpdateRound, excludeRound, firstSeen[acct.Address])
}
firstSeen[acct.Address] = acct.UpdateRound
foundCount++
}
return nil
})
require.NoError(t, err)
require.True(t, foundCount > 0, "Should see some accounts that satisfy updRound >= excludeRound")

// Test MakeOnlineRoundParamsIter
foundCount = 0
err = oa.dbs.Snapshot(func(ctx context.Context, tx trackerdb.SnapshotScope) error {
it, err2 := tx.MakeOnlineRoundParamsIter(ctx, false, excludeRound)
require.NoError(t, err2)
defer it.Close()

for it.Next() {
roundParams, roundParamsErr := it.GetItem()
require.NoError(t, roundParamsErr)
require.True(t, roundParams.Round >= excludeRound, "MakeOnlineRoundParamsIter produced row for round %d < excludeRound %d", roundParams.Round, excludeRound)
foundCount++
}
return nil
})
require.NoError(t, err)
require.EqualValues(t, endRound-excludeRound+1, foundCount, "Should see all round params for rounds >= excludeRound")
}

// compareTopAccounts makes sure that accounts returned from OnlineTop function are sorted and contains the online accounts on the test
Expand Down
Loading
Loading