diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml
index 90b90cec8b..064f100f4a 100644
--- a/.github/workflows/tools.yml
+++ b/.github/workflows/tools.yml
@@ -9,9 +9,6 @@ on:
- 'tools/block-generator/**'
- 'tools/x-repo-types/**'
pull_request:
- paths:
- - 'tools/block-generator/**'
- - 'tools/x-repo-types/**'
jobs:
tools_test:
diff --git a/cmd/algons/dnsaddrCmd.go b/cmd/algons/dnsaddrCmd.go
index c7ab7d9546..82dcca59e0 100644
--- a/cmd/algons/dnsaddrCmd.go
+++ b/cmd/algons/dnsaddrCmd.go
@@ -78,7 +78,6 @@ var dnsaddrTreeCmd = &cobra.Command{
}
},
}
-
var dnsaddrTreeDeleteCmd = &cobra.Command{
Use: "delete",
Short: "Recursively resolves and deletes the dnsaddr entries of the given domain",
@@ -97,8 +96,8 @@ var dnsaddrTreeDeleteCmd = &cobra.Command{
}
cloudflareDNS := cloudflare.NewDNS(cfZoneID, cfToken)
var recordsToDelete []cloudflare.DNSRecordResponseEntry
- err = dnsaddr.Iterate(addr, controller, func(dnsaddr multiaddr.Multiaddr, entries []multiaddr.Multiaddr) error {
- domain, _ := dnsaddr.ValueForProtocol(multiaddr.P_DNSADDR)
+ err = dnsaddr.Iterate(addr, controller, func(entryFrom multiaddr.Multiaddr, entries []multiaddr.Multiaddr) error {
+ domain, _ := entryFrom.ValueForProtocol(multiaddr.P_DNSADDR)
name := fmt.Sprintf("_dnsaddr.%s", domain)
fmt.Printf("listing records for %s\n", name)
records, err := cloudflareDNS.ListDNSRecord(context.Background(), "TXT", name, "", "", "", "")
diff --git a/cmd/tealdbg/localLedger.go b/cmd/tealdbg/localLedger.go
index 03cf088f42..64dfe7329d 100644
--- a/cmd/tealdbg/localLedger.go
+++ b/cmd/tealdbg/localLedger.go
@@ -281,10 +281,6 @@ func (l *localLedger) BlockHdr(basics.Round) (bookkeeping.BlockHeader, error) {
return bookkeeping.BlockHeader{}, nil
}
-func (l *localLedger) BlockHdrCached(basics.Round) (bookkeeping.BlockHeader, error) {
- return bookkeeping.BlockHeader{}, nil
-}
-
func (l *localLedger) GetStateProofVerificationContext(_ basics.Round) (*ledgercore.StateProofVerificationContext, error) {
return nil, fmt.Errorf("localLedger: GetStateProofVerificationContext, needed for state proof verification, is not implemented in debugger")
}
diff --git a/daemon/algod/api/algod.oas2.json b/daemon/algod/api/algod.oas2.json
index 5adf017114..02e2349de3 100644
--- a/daemon/algod/api/algod.oas2.json
+++ b/daemon/algod/api/algod.oas2.json
@@ -1111,7 +1111,7 @@
"public",
"nonparticipating"
],
- "description": "Waits for a block to appear after round {round} and returns the node's status at the time.",
+ "description": "Waits for a block to appear after round {round} and returns the node's status at the time. There is a 1 minute timeout, when reached the current status is returned regardless of whether or not it is the round after the given round.",
"produces": [
"application/json"
],
@@ -1132,10 +1132,11 @@
],
"responses": {
"200": {
+ "description": "The round after the given round, or the current round if a timeout occurs.",
"$ref": "#/responses/NodeStatusResponse"
},
"400": {
- "description": "Bad Request -- number must be non-negative integer ",
+ "description": "Bad Request -- number must be non-negative integer",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
diff --git a/daemon/algod/api/algod.oas3.yml b/daemon/algod/api/algod.oas3.yml
index f29797fe4f..5b784af1ac 100644
--- a/daemon/algod/api/algod.oas3.yml
+++ b/daemon/algod/api/algod.oas3.yml
@@ -5499,7 +5499,7 @@
},
"/v2/status/wait-for-block-after/{round}": {
"get": {
- "description": "Waits for a block to appear after round {round} and returns the node's status at the time.",
+ "description": "Waits for a block to appear after round {round} and returns the node's status at the time. There is a 1 minute timeout, when reached the current status is returned regardless of whether or not it is the round after the given round.",
"operationId": "WaitForBlock",
"parameters": [
{
@@ -5648,7 +5648,7 @@
}
}
},
- "description": "Bad Request -- number must be non-negative integer "
+ "description": "Bad Request -- number must be non-negative integer"
},
"401": {
"content": {
diff --git a/daemon/algod/api/server/v2/dryrun.go b/daemon/algod/api/server/v2/dryrun.go
index 5b9309e449..ef0de80850 100644
--- a/daemon/algod/api/server/v2/dryrun.go
+++ b/daemon/algod/api/server/v2/dryrun.go
@@ -241,10 +241,6 @@ func (dl *dryrunLedger) BlockHdr(basics.Round) (bookkeeping.BlockHeader, error)
return bookkeeping.BlockHeader{}, nil
}
-func (dl *dryrunLedger) BlockHdrCached(basics.Round) (bookkeeping.BlockHeader, error) {
- return bookkeeping.BlockHeader{}, nil
-}
-
func (dl *dryrunLedger) CheckDup(config.ConsensusParams, basics.Round, basics.Round, basics.Round, transactions.Txid, ledgercore.Txlease) error {
return nil
}
diff --git a/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go b/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go
index 774d725580..5ad094a2aa 100644
--- a/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go
+++ b/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go
@@ -933,32 +933,33 @@ var swaggerSpec = []string{
"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",
- "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",
- "Fs2Hdx/+/wAAAP//3P3na2WCAQA=",
+ "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",
+ "RfPh3Yf/PwAA///0dvnw8YIBAA==",
}
// GetSwagger returns the content of the embedded swagger specification file
diff --git a/daemon/algod/api/server/v2/handlers.go b/daemon/algod/api/server/v2/handlers.go
index fb904f890b..cd9fbbbd4a 100644
--- a/daemon/algod/api/server/v2/handlers.go
+++ b/daemon/algod/api/server/v2/handlers.go
@@ -66,6 +66,9 @@ const MaxTealSourceBytes = 200_000
// become quite large, so we allow up to 1MB
const MaxTealDryrunBytes = 1_000_000
+// WaitForBlockTimeout is the timeout for the WaitForBlock endpoint.
+var WaitForBlockTimeout = 1 * time.Minute
+
// Handlers is an implementation to the V2 route handler interface defined by the generated code.
type Handlers struct {
Node NodeInterface
@@ -863,7 +866,7 @@ func (v2 *Handlers) WaitForBlock(ctx echo.Context, round uint64) error {
select {
case <-v2.Shutdown:
return internalError(ctx, err, errServiceShuttingDown, v2.Log)
- case <-time.After(1 * time.Minute):
+ case <-time.After(WaitForBlockTimeout):
case <-ledger.Wait(basics.Round(round + 1)):
}
diff --git a/daemon/algod/api/server/v2/test/handlers_test.go b/daemon/algod/api/server/v2/test/handlers_test.go
index a56577d549..de8a011458 100644
--- a/daemon/algod/api/server/v2/test/handlers_test.go
+++ b/daemon/algod/api/server/v2/test/handlers_test.go
@@ -72,16 +72,19 @@ import (
const stateProofInterval = uint64(256)
func setupMockNodeForMethodGet(t *testing.T, status node.StatusReport, devmode bool) (v2.Handlers, echo.Context, *httptest.ResponseRecorder, []account.Root, []transactions.SignedTxn, func()) {
+ return setupMockNodeForMethodGetWithShutdown(t, status, devmode, make(chan struct{}))
+}
+
+func setupMockNodeForMethodGetWithShutdown(t *testing.T, status node.StatusReport, devmode bool, shutdown chan struct{}) (v2.Handlers, echo.Context, *httptest.ResponseRecorder, []account.Root, []transactions.SignedTxn, func()) {
numAccounts := 1
numTransactions := 1
offlineAccounts := true
mockLedger, rootkeys, _, stxns, releasefunc := testingenv(t, numAccounts, numTransactions, offlineAccounts)
mockNode := makeMockNode(mockLedger, t.Name(), nil, status, devmode)
- dummyShutdownChan := make(chan struct{})
handler := v2.Handlers{
Node: mockNode,
Log: logging.Base(),
- Shutdown: dummyShutdownChan,
+ Shutdown: shutdown,
}
e := echo.New()
req := httptest.NewRequest(http.MethodGet, "/", nil)
@@ -585,9 +588,73 @@ func TestGetStatusAfterBlock(t *testing.T) {
defer releasefunc()
err := handler.WaitForBlock(c, 0)
require.NoError(t, err)
- // Expect 400 - the test ledger will always cause "errRequestedRoundInUnsupportedRound",
- // as it has not participated in agreement to build blockheaders
+
require.Equal(t, 400, rec.Code)
+ msg, err := io.ReadAll(rec.Body)
+ require.NoError(t, err)
+ require.Contains(t, string(msg), "requested round would reach only after the protocol upgrade which isn't supported")
+}
+
+func TestGetStatusAfterBlockShutdown(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ catchup := cannedStatusReportGolden
+ catchup.StoppedAtUnsupportedRound = false
+ shutdownChan := make(chan struct{})
+ handler, c, rec, _, _, releasefunc := setupMockNodeForMethodGetWithShutdown(t, catchup, false, shutdownChan)
+ defer releasefunc()
+
+ close(shutdownChan)
+ err := handler.WaitForBlock(c, 0)
+ require.NoError(t, err)
+
+ require.Equal(t, 500, rec.Code)
+ msg, err := io.ReadAll(rec.Body)
+ require.NoError(t, err)
+ require.Contains(t, string(msg), "operation aborted as server is shutting down")
+}
+
+func TestGetStatusAfterBlockDuringCatchup(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ catchup := cannedStatusReportGolden
+ catchup.StoppedAtUnsupportedRound = false
+ catchup.Catchpoint = "catchpoint"
+ handler, c, rec, _, _, releasefunc := setupTestForMethodGet(t, catchup)
+ defer releasefunc()
+
+ err := handler.WaitForBlock(c, 0)
+ require.NoError(t, err)
+
+ require.Equal(t, 503, rec.Code)
+ msg, err := io.ReadAll(rec.Body)
+ require.NoError(t, err)
+ require.Contains(t, string(msg), "operation not available during catchup")
+}
+
+func TestGetStatusAfterBlockTimeout(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ supported := cannedStatusReportGolden
+ supported.StoppedAtUnsupportedRound = false
+ handler, c, rec, _, _, releasefunc := setupTestForMethodGet(t, supported)
+ defer releasefunc()
+
+ before := v2.WaitForBlockTimeout
+ defer func() { v2.WaitForBlockTimeout = before }()
+ v2.WaitForBlockTimeout = 1 * time.Millisecond
+ err := handler.WaitForBlock(c, 1000)
+ require.NoError(t, err)
+
+ require.Equal(t, 200, rec.Code)
+ dec := json.NewDecoder(rec.Body)
+ var resp model.NodeStatusResponse
+ err = dec.Decode(&resp)
+ require.NoError(t, err)
+ require.Equal(t, uint64(1), resp.LastRound)
}
func TestGetTransactionParams(t *testing.T) {
diff --git a/data/ledger_test.go b/data/ledger_test.go
index cd7d6297a0..452bdba158 100644
--- a/data/ledger_test.go
+++ b/data/ledger_test.go
@@ -366,9 +366,11 @@ func TestConsensusVersion(t *testing.T) {
require.NotNil(t, &l)
blk := genesisInitState.Block
+ flushOffset := uint64(129) // pendingDeltasFlushThreshold = 128 will flush every 128 rounds (RewardsPool acct)
+ // txTailRetainSize = MaxTxnLife + DeeperBlockHeaderHistory = 1000 + 1
- // add 5 blocks.
- for rnd := basics.Round(1); rnd < basics.Round(consensusParams.MaxTxnLife+5); rnd++ {
+ // add some blocks.
+ for rnd := basics.Round(1); rnd < basics.Round(consensusParams.MaxTxnLife+flushOffset); rnd++ {
blk.BlockHeader.Round++
blk.BlockHeader.Seed[0] = byte(uint64(rnd))
blk.BlockHeader.Seed[1] = byte(uint64(rnd) / 256)
@@ -378,31 +380,38 @@ func TestConsensusVersion(t *testing.T) {
require.NoError(t, l.AddBlock(blk, agreement.Certificate{}))
l.WaitForCommit(rnd)
}
- // ensure that all the first 5 has the expected version.
- for rnd := basics.Round(consensusParams.MaxTxnLife); rnd < basics.Round(consensusParams.MaxTxnLife+5); rnd++ {
+ // ensure that all the first flushOffset have the expected version.
+ for rnd := basics.Round(consensusParams.MaxTxnLife); rnd < basics.Round(consensusParams.MaxTxnLife+flushOffset); rnd++ {
ver, err := l.ConsensusVersion(rnd)
require.NoError(t, err)
require.Equal(t, previousProtocol, ver)
}
// the next UpgradeVoteRounds can also be known to have the previous version.
- for rnd := basics.Round(consensusParams.MaxTxnLife + 5); rnd < basics.Round(consensusParams.MaxTxnLife+5+consensusParams.UpgradeVoteRounds); rnd++ {
+ for rnd := basics.Round(consensusParams.MaxTxnLife + flushOffset); rnd < basics.Round(consensusParams.MaxTxnLife+
+ flushOffset+consensusParams.UpgradeVoteRounds); rnd++ {
ver, err := l.ConsensusVersion(rnd)
require.NoError(t, err)
require.Equal(t, previousProtocol, ver)
}
// but two rounds ahead is not known.
- ver, err := l.ConsensusVersion(basics.Round(consensusParams.MaxTxnLife + 6 + consensusParams.UpgradeVoteRounds))
+ ver, err := l.ConsensusVersion(basics.Round(consensusParams.MaxTxnLife + flushOffset + 1 + consensusParams.UpgradeVoteRounds))
require.Equal(t, protocol.ConsensusVersion(""), ver)
- require.Equal(t, ledgercore.ErrNoEntry{Round: basics.Round(consensusParams.MaxTxnLife + 6 + consensusParams.UpgradeVoteRounds), Latest: basics.Round(consensusParams.MaxTxnLife + 4), Committed: basics.Round(consensusParams.MaxTxnLife + 4)}, err)
+ require.Equal(t, ledgercore.ErrNoEntry{
+ Round: basics.Round(consensusParams.MaxTxnLife + flushOffset + 1 + consensusParams.UpgradeVoteRounds),
+ Latest: basics.Round(consensusParams.MaxTxnLife + flushOffset - 1),
+ Committed: basics.Round(consensusParams.MaxTxnLife + flushOffset - 1)}, err)
// check round #1 which was already dropped.
ver, err = l.ConsensusVersion(basics.Round(1))
require.Equal(t, protocol.ConsensusVersion(""), ver)
- require.Equal(t, ledgercore.ErrNoEntry{Round: basics.Round(1), Latest: basics.Round(consensusParams.MaxTxnLife + 4), Committed: basics.Round(consensusParams.MaxTxnLife + 4)}, err)
+ require.Equal(t, ledgercore.ErrNoEntry{
+ Round: basics.Round(1),
+ Latest: basics.Round(consensusParams.MaxTxnLife + flushOffset - 1),
+ Committed: basics.Round(consensusParams.MaxTxnLife + flushOffset - 1)}, err)
// add another round, with upgrade
- rnd := basics.Round(consensusParams.MaxTxnLife + 5)
+ rnd := basics.Round(consensusParams.MaxTxnLife + flushOffset)
blk.BlockHeader.Round++
blk.BlockHeader.Seed[0] = byte(uint64(rnd))
blk.BlockHeader.Seed[1] = byte(uint64(rnd) / 256)
diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go
index 2044301702..f1d6983836 100644
--- a/data/transactions/logic/eval.go
+++ b/data/transactions/logic/eval.go
@@ -205,7 +205,7 @@ func computeMinAvmVersion(group []transactions.SignedTxnWithAD) uint64 {
// only exposes things that consensus has already agreed upon, so it is
// "stateless" for signature purposes.
type LedgerForSignature interface {
- BlockHdrCached(basics.Round) (bookkeeping.BlockHeader, error)
+ BlockHdr(basics.Round) (bookkeeping.BlockHeader, error)
}
// NoHeaderLedger is intended for debugging situations in which it is reasonable
@@ -213,8 +213,8 @@ type LedgerForSignature interface {
type NoHeaderLedger struct {
}
-// BlockHdrCached always errors
-func (NoHeaderLedger) BlockHdrCached(basics.Round) (bookkeeping.BlockHeader, error) {
+// BlockHdr always errors
+func (NoHeaderLedger) BlockHdr(basics.Round) (bookkeeping.BlockHeader, error) {
return bookkeeping.BlockHeader{}, fmt.Errorf("no block header access")
}
@@ -224,7 +224,6 @@ type LedgerForLogic interface {
Authorizer(addr basics.Address) (basics.Address, error)
Round() basics.Round
PrevTimestamp() int64
- BlockHdrCached(basics.Round) (bookkeeping.BlockHeader, error)
AssetHolding(addr basics.Address, assetIdx basics.AssetIndex) (basics.AssetHolding, error)
AssetParams(aidx basics.AssetIndex) (basics.AssetParams, basics.Address, error)
@@ -2949,7 +2948,7 @@ func (cx *EvalContext) txnFieldToStack(stxn *transactions.SignedTxnWithAD, fs *t
if err != nil {
return sv, err
}
- hdr, err := cx.SigLedger.BlockHdrCached(rnd)
+ hdr, err := cx.SigLedger.BlockHdr(rnd)
if err != nil {
return sv, err
}
@@ -5827,7 +5826,7 @@ func opBlock(cx *EvalContext) error {
return fmt.Errorf("invalid block field %s", f)
}
- hdr, err := cx.SigLedger.BlockHdrCached(round)
+ hdr, err := cx.SigLedger.BlockHdr(round)
if err != nil {
return err
}
diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go
index c7e73c0ba8..ee049d9d9c 100644
--- a/data/transactions/logic/eval_test.go
+++ b/data/transactions/logic/eval_test.go
@@ -175,8 +175,9 @@ func defaultAppParamsWithVersion(version uint64, txns ...transactions.SignedTxn)
ep := NewAppEvalParams(transactions.WrapSignedTxnsWithAD(txns), makeTestProtoV(version), &transactions.SpecialAddresses{})
if ep != nil { // If supplied no apps, ep is nil.
ep.Trace = &strings.Builder{}
- ep.Ledger = NewLedger(nil)
- ep.SigLedger = ep.Ledger
+ ledger := NewLedger(nil)
+ ep.Ledger = ledger
+ ep.SigLedger = ledger
}
return ep
}
@@ -6011,3 +6012,12 @@ pop
int 1
`, 8)
}
+
+func TestNoHeaderLedger(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ nhl := NoHeaderLedger{}
+ _, err := nhl.BlockHdr(1)
+ require.Error(t, err)
+ require.Equal(t, err, fmt.Errorf("no block header access"))
+}
diff --git a/data/transactions/logic/ledger_test.go b/data/transactions/logic/ledger_test.go
index 3016ae5298..a111eec131 100644
--- a/data/transactions/logic/ledger_test.go
+++ b/data/transactions/logic/ledger_test.go
@@ -215,8 +215,8 @@ func (l *Ledger) PrevTimestamp() int64 {
return int64(rand.Uint32() + 1)
}
-// BlockHdrCached returns the block header for the given round, if it is available
-func (l *Ledger) BlockHdrCached(round basics.Round) (bookkeeping.BlockHeader, error) {
+// BlockHdr returns the block header for the given round, if it is available
+func (l *Ledger) BlockHdr(round basics.Round) (bookkeeping.BlockHeader, error) {
hdr := bookkeeping.BlockHeader{}
// Return a fake seed that is different for each round
seed := committee.Seed{}
diff --git a/data/transactions/verify/txn_test.go b/data/transactions/verify/txn_test.go
index 9c7d001470..416c0e4c08 100644
--- a/data/transactions/verify/txn_test.go
+++ b/data/transactions/verify/txn_test.go
@@ -72,9 +72,6 @@ type DummyLedgerForSignature struct {
badHdr bool
}
-func (d *DummyLedgerForSignature) BlockHdrCached(basics.Round) (bookkeeping.BlockHeader, error) {
- return createDummyBlockHeader(), nil
-}
func (d *DummyLedgerForSignature) BlockHdr(rnd basics.Round) (blk bookkeeping.BlockHeader, err error) {
if d.badHdr {
return bookkeeping.BlockHeader{}, fmt.Errorf("test error block hdr")
diff --git a/ledger/acctupdates.go b/ledger/acctupdates.go
index bb495f3f8f..0408034ae2 100644
--- a/ledger/acctupdates.go
+++ b/ledger/acctupdates.go
@@ -723,7 +723,7 @@ type accountUpdatesLedgerEvaluator struct {
au *accountUpdates
// ao is onlineAccounts for voters access
ao *onlineAccounts
- // txtail allows implementation of BlockHdrCached
+ // txtail allows BlockHdr to serve blockHdr without going to disk
tail *txTail
// prevHeader is the previous header to the current one. The usage of this is only in the context of initializeCaches where we iteratively
// building the ledgercore.StateDelta, which requires a peek on the "previous" header information.
@@ -758,17 +758,11 @@ func (aul *accountUpdatesLedgerEvaluator) BlockHdr(r basics.Round) (bookkeeping.
if r == aul.prevHeader.Round {
return aul.prevHeader, nil
}
- return bookkeeping.BlockHeader{}, ledgercore.ErrNoEntry{}
-}
-
-// BlockHdrCached returns the header of the given round. We use the txTail
-// tracker directly to avoid the tracker registry lock.
-func (aul *accountUpdatesLedgerEvaluator) BlockHdrCached(r basics.Round) (bookkeeping.BlockHeader, error) {
hdr, ok := aul.tail.blockHeader(r)
- if !ok {
- return bookkeeping.BlockHeader{}, fmt.Errorf("no cached header data for round %d", r)
+ if ok {
+ return hdr, nil
}
- return hdr, nil
+ return bookkeeping.BlockHeader{}, ledgercore.ErrNoEntry{}
}
// LatestTotals returns the totals of all accounts for the most recent round, as well as the round number
diff --git a/ledger/acctupdates_test.go b/ledger/acctupdates_test.go
index d938b0d530..658cb71330 100644
--- a/ledger/acctupdates_test.go
+++ b/ledger/acctupdates_test.go
@@ -2711,3 +2711,16 @@ func TestAcctUpdatesLookupStateDelta(t *testing.T) {
require.Contains(t, data.Assets, aidx3)
require.NotContains(t, data.Assets, aidx2)
}
+
+func TestAccountUpdatesLedgerEvaluatorNoBlockHdr(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ aul := &accountUpdatesLedgerEvaluator{
+ prevHeader: bookkeeping.BlockHeader{},
+ tail: &txTail{},
+ }
+ hdr, err := aul.BlockHdr(99)
+ require.Error(t, err)
+ require.Equal(t, ledgercore.ErrNoEntry{}, err)
+ require.Equal(t, bookkeeping.BlockHeader{}, hdr)
+}
diff --git a/ledger/blockHeaderCache.go b/ledger/blockHeaderCache.go
deleted file mode 100644
index b0f27f78ec..0000000000
--- a/ledger/blockHeaderCache.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (C) 2019-2023 Algorand, Inc.
-// This file is part of go-algorand
-//
-// go-algorand is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// go-algorand is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with go-algorand. If not, see .
-
-package ledger
-
-import (
- "github.com/algorand/go-algorand/data/basics"
- "github.com/algorand/go-algorand/data/bookkeeping"
-
- "github.com/algorand/go-deadlock"
-)
-
-const latestHeaderCacheSize = 512
-const blockHeadersLRUCacheSize = 10
-
-// blockHeaderCache is a wrapper for all block header cache mechanisms used within the Ledger.
-type blockHeaderCache struct {
- lruCache heapLRUCache
- latestHeaderCache latestBlockHeaderCache
-}
-
-type latestBlockHeaderCache struct {
- blockHeaders [latestHeaderCacheSize]bookkeeping.BlockHeader
- mutex deadlock.RWMutex
-}
-
-func (c *blockHeaderCache) initialize() {
- c.lruCache.maxEntries = blockHeadersLRUCacheSize
-}
-
-func (c *blockHeaderCache) get(round basics.Round) (blockHeader bookkeeping.BlockHeader, exists bool) {
- // check latestHeaderCache first
- blockHeader, exists = c.latestHeaderCache.get(round)
- if exists {
- return
- }
-
- // if not found in latestHeaderCache, check LRUCache
- value, exists := c.lruCache.Get(round)
- if exists {
- blockHeader = value.(bookkeeping.BlockHeader)
- }
-
- return
-}
-
-func (c *blockHeaderCache) put(blockHeader bookkeeping.BlockHeader) {
- c.latestHeaderCache.put(blockHeader)
- c.lruCache.Put(blockHeader.Round, blockHeader)
-}
-
-func (c *latestBlockHeaderCache) get(round basics.Round) (blockHeader bookkeeping.BlockHeader, exists bool) {
- c.mutex.RLock()
- defer c.mutex.RUnlock()
-
- idx := round % latestHeaderCacheSize
- if round == 0 || c.blockHeaders[idx].Round != round { // blockHeader is empty or not requested round
- return bookkeeping.BlockHeader{}, false
- }
- blockHeader = c.blockHeaders[idx]
-
- return blockHeader, true
-}
-
-func (c *latestBlockHeaderCache) put(blockHeader bookkeeping.BlockHeader) {
- c.mutex.Lock()
- defer c.mutex.Unlock()
-
- idx := blockHeader.Round % latestHeaderCacheSize
- if blockHeader.Round > c.blockHeaders[idx].Round { // provided blockHeader is more recent than cached one
- c.blockHeaders[idx] = blockHeader
- }
-}
diff --git a/ledger/blockHeaderCache_test.go b/ledger/blockHeaderCache_test.go
deleted file mode 100644
index 6728e71c65..0000000000
--- a/ledger/blockHeaderCache_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (C) 2019-2023 Algorand, Inc.
-// This file is part of go-algorand
-//
-// go-algorand is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// go-algorand is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with go-algorand. If not, see .
-
-package ledger
-
-import (
- "testing"
-
- "github.com/stretchr/testify/require"
-
- "github.com/algorand/go-algorand/config"
- "github.com/algorand/go-algorand/data/basics"
- "github.com/algorand/go-algorand/data/bookkeeping"
- "github.com/algorand/go-algorand/protocol"
- "github.com/algorand/go-algorand/test/partitiontest"
-)
-
-func TestBlockHeaderCache(t *testing.T) {
- partitiontest.PartitionTest(t)
- a := require.New(t)
-
- var cache blockHeaderCache
- cache.initialize()
- for i := basics.Round(1024); i < 1024+latestHeaderCacheSize; i++ {
- hdr := bookkeeping.BlockHeader{Round: i}
- cache.put(hdr)
- }
-
- rnd := basics.Round(120)
- hdr := bookkeeping.BlockHeader{Round: rnd}
- cache.put(hdr)
-
- _, exists := cache.get(rnd)
- a.True(exists)
-
- _, exists = cache.lruCache.Get(rnd)
- a.True(exists)
-
- _, exists = cache.latestHeaderCache.get(rnd)
- a.False(exists)
-
- rnd = basics.Round(2048)
- hdr = bookkeeping.BlockHeader{Round: rnd}
- cache.put(hdr)
-
- _, exists = cache.latestHeaderCache.get(rnd)
- a.True(exists)
-
- _, exists = cache.lruCache.Get(rnd)
- a.True(exists)
-
-}
-
-func TestLatestBlockHeaderCache(t *testing.T) {
- partitiontest.PartitionTest(t)
- a := require.New(t)
-
- var cache latestBlockHeaderCache
- for i := basics.Round(123); i < latestHeaderCacheSize; i++ {
- hdr := bookkeeping.BlockHeader{Round: i}
- cache.put(hdr)
- }
-
- for i := basics.Round(0); i < 123; i++ {
- _, exists := cache.get(i)
- a.False(exists)
- }
-
- for i := basics.Round(123); i < latestHeaderCacheSize; i++ {
- hdr, exists := cache.get(i)
- a.True(exists)
- a.Equal(i, hdr.Round)
- }
-}
-
-func TestCacheSizeConsensus(t *testing.T) {
- partitiontest.PartitionTest(t)
- a := require.New(t)
-
- a.Equal(uint64(latestHeaderCacheSize), config.Consensus[protocol.ConsensusCurrentVersion].StateProofInterval*2)
-}
diff --git a/ledger/eval/applications.go b/ledger/eval/applications.go
index e126cfd309..5419bc9525 100644
--- a/ledger/eval/applications.go
+++ b/ledger/eval/applications.go
@@ -21,7 +21,6 @@ import (
"github.com/algorand/avm-abi/apps"
"github.com/algorand/go-algorand/data/basics"
- "github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/data/transactions/logic"
"github.com/algorand/go-algorand/ledger/apply"
"github.com/algorand/go-algorand/ledger/ledgercore"
@@ -129,10 +128,6 @@ func (cs *roundCowState) SetLocal(addr basics.Address, appIdx basics.AppIndex, k
return cs.setKey(addr, appIdx, false, key, value, accountIdx)
}
-func (cs *roundCowState) BlockHdrCached(round basics.Round) (bookkeeping.BlockHeader, error) {
- return cs.blockHdrCached(round)
-}
-
func (cs *roundCowState) DelLocal(addr basics.Address, appIdx basics.AppIndex, key string, accountIdx uint64) error {
return cs.delKey(addr, appIdx, false, key, accountIdx)
}
diff --git a/ledger/eval/cow.go b/ledger/eval/cow.go
index 8019dc69f7..d797a4a560 100644
--- a/ledger/eval/cow.go
+++ b/ledger/eval/cow.go
@@ -57,7 +57,6 @@ type roundCowParent interface {
getCreator(cidx basics.CreatableIndex, ctype basics.CreatableType) (basics.Address, bool, error)
GetStateProofNextRound() basics.Round
BlockHdr(rnd basics.Round) (bookkeeping.BlockHeader, error)
- blockHdrCached(rnd basics.Round) (bookkeeping.BlockHeader, error)
getStorageCounts(addr basics.Address, aidx basics.AppIndex, global bool) (basics.StateSchema, error)
// note: getStorageLimits is redundant with the other methods
// and is provided to optimize state schema lookups
@@ -250,10 +249,6 @@ func (cb *roundCowState) GetStateProofVerificationContext(stateProofLastAttested
return cb.lookupParent.GetStateProofVerificationContext(stateProofLastAttestedRound)
}
-func (cb *roundCowState) blockHdrCached(r basics.Round) (bookkeeping.BlockHeader, error) {
- return cb.lookupParent.blockHdrCached(r)
-}
-
func (cb *roundCowState) incTxnCount() {
cb.txnCount++
}
diff --git a/ledger/eval/eval.go b/ledger/eval/eval.go
index f0dde2b399..5fc72ff54e 100644
--- a/ledger/eval/eval.go
+++ b/ledger/eval/eval.go
@@ -40,7 +40,6 @@ import (
// LedgerForCowBase represents subset of Ledger functionality needed for cow business
type LedgerForCowBase interface {
BlockHdr(basics.Round) (bookkeeping.BlockHeader, error)
- BlockHdrCached(basics.Round) (bookkeeping.BlockHeader, error)
CheckDup(config.ConsensusParams, basics.Round, basics.Round, basics.Round, transactions.Txid, ledgercore.Txlease) error
LookupWithoutRewards(basics.Round, basics.Address) (ledgercore.AccountData, basics.Round, error)
LookupAsset(basics.Round, basics.Address, basics.AssetIndex) (ledgercore.AssetResource, error)
@@ -342,10 +341,6 @@ func (x *roundCowBase) GetStateProofVerificationContext(stateProofLastAttestedRo
return x.l.GetStateProofVerificationContext(stateProofLastAttestedRound)
}
-func (x *roundCowBase) blockHdrCached(r basics.Round) (bookkeeping.BlockHeader, error) {
- return x.l.BlockHdrCached(r)
-}
-
func (x *roundCowBase) allocated(addr basics.Address, aidx basics.AppIndex, global bool) (bool, error) {
// For global, check if app params exist
if global {
diff --git a/ledger/eval/eval_test.go b/ledger/eval/eval_test.go
index 783f975bbc..b916558314 100644
--- a/ledger/eval/eval_test.go
+++ b/ledger/eval/eval_test.go
@@ -940,10 +940,6 @@ func (ledger *evalTestLedger) BlockHdr(rnd basics.Round) (bookkeeping.BlockHeade
return block.BlockHeader, nil
}
-func (ledger *evalTestLedger) BlockHdrCached(rnd basics.Round) (bookkeeping.BlockHeader, error) {
- return ledger.BlockHdr(rnd)
-}
-
func (ledger *evalTestLedger) VotersForStateProof(rnd basics.Round) (*ledgercore.VotersForRound, error) {
return nil, errors.New("untested code path")
}
@@ -1041,10 +1037,6 @@ func (l *testCowBaseLedger) BlockHdr(basics.Round) (bookkeeping.BlockHeader, err
return bookkeeping.BlockHeader{}, errors.New("not implemented")
}
-func (l *testCowBaseLedger) BlockHdrCached(rnd basics.Round) (bookkeeping.BlockHeader, error) {
- return l.BlockHdr(rnd)
-}
-
func (l *testCowBaseLedger) CheckDup(config.ConsensusParams, basics.Round, basics.Round, basics.Round, transactions.Txid, ledgercore.Txlease) error {
return errors.New("not implemented")
}
diff --git a/ledger/eval/prefetcher/prefetcher_alignment_test.go b/ledger/eval/prefetcher/prefetcher_alignment_test.go
index efb9e683bf..81ce168d43 100644
--- a/ledger/eval/prefetcher/prefetcher_alignment_test.go
+++ b/ledger/eval/prefetcher/prefetcher_alignment_test.go
@@ -97,10 +97,6 @@ func (l *prefetcherAlignmentTestLedger) BlockHdr(round basics.Round) (bookkeepin
fmt.Errorf("BlockHdr() round %d not supported", round)
}
-func (l *prefetcherAlignmentTestLedger) BlockHdrCached(round basics.Round) (bookkeeping.BlockHeader, error) {
- return l.BlockHdr(round)
-}
-
func (l *prefetcherAlignmentTestLedger) CheckDup(config.ConsensusParams, basics.Round, basics.Round, basics.Round, transactions.Txid, ledgercore.Txlease) error {
return nil
}
diff --git a/ledger/evalindexer.go b/ledger/evalindexer.go
index 5ac28ce814..1caa7d8ef5 100644
--- a/ledger/evalindexer.go
+++ b/ledger/evalindexer.go
@@ -45,7 +45,7 @@ type indexerLedgerForEval interface {
LatestTotals() (ledgercore.AccountTotals, error)
LookupKv(basics.Round, string) ([]byte, error)
- BlockHdrCached(basics.Round) (bookkeeping.BlockHeader, error)
+ BlockHdr(basics.Round) (bookkeeping.BlockHeader, error)
}
// FoundAddress is a wrapper for an address and a boolean.
@@ -92,11 +92,6 @@ func (l indexerLedgerConnector) BlockHdr(round basics.Round) (bookkeeping.BlockH
return l.il.LatestBlockHdr()
}
-// BlockHdrCached is part of LedgerForEvaluator interface.
-func (l indexerLedgerConnector) BlockHdrCached(round basics.Round) (bookkeeping.BlockHeader, error) {
- return l.il.BlockHdrCached(round)
-}
-
// CheckDup is part of LedgerForEvaluator interface.
func (l indexerLedgerConnector) CheckDup(config.ConsensusParams, basics.Round, basics.Round, basics.Round, transactions.Txid, ledgercore.Txlease) error {
// This function is not used by evaluator.
diff --git a/ledger/evalindexer_test.go b/ledger/evalindexer_test.go
index d5636f27ca..8209bb9282 100644
--- a/ledger/evalindexer_test.go
+++ b/ledger/evalindexer_test.go
@@ -47,8 +47,8 @@ func (il indexerLedgerForEvalImpl) LatestBlockHdr() (bookkeeping.BlockHeader, er
return il.l.BlockHdr(il.latestRound)
}
-func (il indexerLedgerForEvalImpl) BlockHdrCached(round basics.Round) (bookkeeping.BlockHeader, error) {
- return il.l.BlockHdrCached(round)
+func (il indexerLedgerForEvalImpl) BlockHdr(round basics.Round) (bookkeeping.BlockHeader, error) {
+ return il.l.BlockHdr(round)
}
// The value of the returned map is nil iff the account was not found.
diff --git a/ledger/ledger.go b/ledger/ledger.go
index dd54529ee6..6c02951a92 100644
--- a/ledger/ledger.go
+++ b/ledger/ledger.go
@@ -91,8 +91,6 @@ type Ledger struct {
trackers trackerRegistry
trackerMu deadlock.RWMutex
- headerCache blockHeaderCache
-
// verifiedTxnCache holds all the verified transactions state
verifiedTxnCache verify.VerifiedTransactionCache
@@ -136,8 +134,6 @@ func OpenLedger(
tracer: tracer,
}
- l.headerCache.initialize()
-
defer func() {
if err != nil {
l.Close()
@@ -628,8 +624,6 @@ func (l *Ledger) OnlineCirculation(rnd basics.Round, voteRnd basics.Round) (basi
// CheckDup return whether a transaction is a duplicate one.
func (l *Ledger) CheckDup(currentProto config.ConsensusParams, current basics.Round, firstValid basics.Round, lastValid basics.Round, txid transactions.Txid, txl ledgercore.Txlease) error {
- l.trackerMu.RLock()
- defer l.trackerMu.RUnlock()
return l.txTail.checkDup(currentProto, current, firstValid, lastValid, txid, txl)
}
@@ -654,16 +648,22 @@ func (l *Ledger) Block(rnd basics.Round) (blk bookkeeping.Block, err error) {
// BlockHdr returns the BlockHeader of the block for round rnd.
func (l *Ledger) BlockHdr(rnd basics.Round) (blk bookkeeping.BlockHeader, err error) {
- blk, exists := l.headerCache.get(rnd)
- if exists {
- return
- }
- blk, err = l.blockQ.getBlockHdr(rnd)
- if err == nil {
- l.headerCache.put(blk)
+ // Expected availability range in txTail.blockHeader is [Latest - MaxTxnLife, Latest]
+ // allowing (MaxTxnLife + 1) = 1001 rounds back loopback.
+ // The depth besides the MaxTxnLife is controlled by DeeperBlockHeaderHistory parameter
+ // and currently set to 1.
+ // Explanation:
+ // Clients are expected to query blocks at rounds (txn.LastValid - (MaxTxnLife + 1)),
+ // and because a txn is alive when the current round <= txn.LastValid
+ // and valid if txn.LastValid - txn.FirstValid <= MaxTxnLife
+ // the deepest lookup happens when txn.LastValid == current => txn.LastValid == Latest + 1
+ // that gives Latest + 1 - (MaxTxnLife + 1) = Latest - MaxTxnLife as the first round to be accessible.
+ hdr, ok := l.txTail.blockHeader(rnd)
+ if !ok {
+ hdr, err = l.blockQ.getBlockHdr(rnd)
}
- return
+ return hdr, err
}
// EncodedBlockCert returns the encoded block and the corresponding encoded certificate of the block for round rnd.
@@ -712,7 +712,6 @@ func (l *Ledger) AddValidatedBlock(vb ledgercore.ValidatedBlock, cert agreement.
if err != nil {
return err
}
- l.headerCache.put(blk.BlockHeader)
l.trackers.newBlock(blk, vb.Delta())
l.log.Debugf("ledger.AddValidatedBlock: added blk %d", blk.Round())
return nil
@@ -755,27 +754,6 @@ func (l *Ledger) GenesisAccounts() map[basics.Address]basics.AccountData {
return l.genesisAccounts
}
-// BlockHdrCached returns the block header if available.
-// Expected availability range is [Latest - MaxTxnLife, Latest]
-// allowing (MaxTxnLife + 1) = 1001 rounds back loopback.
-// The depth besides the MaxTxnLife is controlled by DeeperBlockHeaderHistory parameter
-// and currently set to 1.
-// Explanation:
-// Clients are expected to query blocks at rounds (txn.LastValid - (MaxTxnLife + 1)),
-// and because a txn is alive when the current round <= txn.LastValid
-// and valid if txn.LastValid - txn.FirstValid <= MaxTxnLife
-// the deepest lookup happens when txn.LastValid == current => txn.LastValid == Latest + 1
-// that gives Latest + 1 - (MaxTxnLife + 1) = Latest - MaxTxnLife as the first round to be accessible.
-func (l *Ledger) BlockHdrCached(rnd basics.Round) (hdr bookkeeping.BlockHeader, err error) {
- l.trackerMu.RLock()
- defer l.trackerMu.RUnlock()
- hdr, ok := l.txTail.blockHeader(rnd)
- if !ok {
- err = fmt.Errorf("no cached header data for round %d", rnd)
- }
- return hdr, err
-}
-
// GetCatchpointCatchupState returns the current state of the catchpoint catchup.
func (l *Ledger) GetCatchpointCatchupState(ctx context.Context) (state CatchpointCatchupState, err error) {
return MakeCatchpointCatchupAccessor(l, l.log).GetState(ctx)
diff --git a/ledger/ledger_test.go b/ledger/ledger_test.go
index f7a847a11b..5edb6d20e1 100644
--- a/ledger/ledger_test.go
+++ b/ledger/ledger_test.go
@@ -1385,46 +1385,6 @@ func testLedgerRegressionFaultyLeaseFirstValidCheck2f3880f7(t *testing.T, versio
}
}
-func TestLedgerBlockHdrCaching(t *testing.T) {
- partitiontest.PartitionTest(t)
- a := require.New(t)
-
- dbName := fmt.Sprintf("%s.%d", t.Name(), crypto.RandUint64())
- genesisInitState := getInitState()
- const inMem = true
- cfg := config.GetDefaultLocal()
- cfg.Archival = true
- log := logging.TestingLog(t)
- log.SetLevel(logging.Info)
- l, err := OpenLedger(log, dbName, inMem, genesisInitState, cfg)
- a.NoError(err)
- defer l.Close()
-
- blk := genesisInitState.Block
-
- for i := 0; i < 1024; i++ {
- blk.BlockHeader.Round++
- blk.BlockHeader.TimeStamp += int64(crypto.RandUint64() % 100 * 1000)
- err := l.AddBlock(blk, agreement.Certificate{})
- a.NoError(err)
-
- hdr, err := l.BlockHdr(blk.BlockHeader.Round)
- a.NoError(err)
- a.Equal(blk.BlockHeader, hdr)
- }
-
- rnd := basics.Round(128)
- hdr, err := l.BlockHdr(rnd) // should update LRU cache but not latestBlockHeaderCache
- a.NoError(err)
- a.Equal(rnd, hdr.Round)
-
- _, exists := l.headerCache.lruCache.Get(rnd)
- a.True(exists)
-
- _, exists = l.headerCache.latestHeaderCache.get(rnd)
- a.False(exists)
-}
-
func BenchmarkLedgerBlockHdrCaching(b *testing.B) {
benchLedgerCache(b, 1024-256+1)
}
@@ -2629,7 +2589,7 @@ func TestLedgerTxTailCachedBlockHeaders(t *testing.T) {
latest := l.Latest()
for i := latest - basics.Round(proto.MaxTxnLife); i <= latest; i++ {
- blk, err := l.BlockHdrCached(i)
+ blk, err := l.BlockHdr(i)
require.NoError(t, err)
require.Equal(t, blk.Round, i)
}
@@ -2643,13 +2603,13 @@ func TestLedgerTxTailCachedBlockHeaders(t *testing.T) {
start := dbRound - basics.Round(proto.MaxTxnLife)
end := latest - basics.Round(proto.MaxTxnLife)
for i := start; i < end; i++ {
- blk, err := l.BlockHdrCached(i)
+ blk, err := l.BlockHdr(i)
require.NoError(t, err)
require.Equal(t, blk.Round, i)
}
- _, err = l.BlockHdrCached(start - 1)
- require.Error(t, err)
+ _, ok := l.txTail.blockHeader(start - 1)
+ require.False(t, ok)
}
// TestLedgerKeyregFlip generates keyreg transactions for flipping genesis accounts state.
diff --git a/ledger/lrukv.go b/ledger/lrukv.go
index 8955d3d2bc..8c407a9fc5 100644
--- a/ledger/lrukv.go
+++ b/ledger/lrukv.go
@@ -79,7 +79,7 @@ func (m *lruKV) read(key string) (data trackerdb.PersistedKVData, has bool) {
func (m *lruKV) flushPendingWrites() {
pendingEntriesCount := len(m.pendingKVs)
if pendingEntriesCount >= m.pendingWritesWarnThreshold {
- m.log.Warnf("lruKV: number of entries in pendingKVs(%d) exceed the warning threshold of %d", pendingEntriesCount, m.pendingWritesWarnThreshold)
+ m.log.Infof("lruKV: number of entries in pendingKVs(%d) exceed the warning threshold of %d", pendingEntriesCount, m.pendingWritesWarnThreshold)
}
for ; pendingEntriesCount > 0; pendingEntriesCount-- {
select {
diff --git a/ledger/lrukv_test.go b/ledger/lrukv_test.go
index 0b0347e240..35345091b2 100644
--- a/ledger/lrukv_test.go
+++ b/ledger/lrukv_test.go
@@ -18,6 +18,7 @@ package ledger
import (
"fmt"
+ "strings"
"testing"
"time"
@@ -162,8 +163,10 @@ type lruKVTestLogger struct {
warnMsgCount int
}
-func (cl *lruKVTestLogger) Warnf(s string, args ...interface{}) {
- cl.warnMsgCount++
+func (cl *lruKVTestLogger) Infof(s string, args ...interface{}) {
+ if strings.Contains(s, "exceed the warning threshold of") {
+ cl.warnMsgCount++
+ }
}
func TestLRUKVPendingWritesWarning(t *testing.T) {
diff --git a/ledger/lruresources.go b/ledger/lruresources.go
index 9886b29b12..f0a536350e 100644
--- a/ledger/lruresources.go
+++ b/ledger/lruresources.go
@@ -103,7 +103,7 @@ func (m *lruResources) readAll(addr basics.Address) (ret []trackerdb.PersistedRe
func (m *lruResources) flushPendingWrites() {
pendingEntriesCount := len(m.pendingResources)
if pendingEntriesCount >= m.pendingWritesWarnThreshold {
- m.log.Warnf("lruResources: number of entries in pendingResources(%d) exceed the warning threshold of %d", pendingEntriesCount, m.pendingWritesWarnThreshold)
+ m.log.Infof("lruResources: number of entries in pendingResources(%d) exceed the warning threshold of %d", pendingEntriesCount, m.pendingWritesWarnThreshold)
}
outer:
diff --git a/ledger/lruresources_test.go b/ledger/lruresources_test.go
index 9268889a58..b678ea742b 100644
--- a/ledger/lruresources_test.go
+++ b/ledger/lruresources_test.go
@@ -18,6 +18,7 @@ package ledger
import (
"encoding/binary"
+ "strings"
"testing"
"time"
@@ -180,8 +181,10 @@ type lruResourcesTestLogger struct {
warnMsgCount int
}
-func (cl *lruResourcesTestLogger) Warnf(s string, args ...interface{}) {
- cl.warnMsgCount++
+func (cl *lruResourcesTestLogger) Infof(s string, args ...interface{}) {
+ if strings.Contains(s, "exceed the warning threshold of") {
+ cl.warnMsgCount++
+ }
}
func TestLRUResourcesPendingWritesWarning(t *testing.T) {
diff --git a/ledger/roundlru.go b/ledger/roundlru.go
deleted file mode 100644
index 43d8639872..0000000000
--- a/ledger/roundlru.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (C) 2019-2023 Algorand, Inc.
-// This file is part of go-algorand
-//
-// go-algorand is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// go-algorand is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with go-algorand. If not, see .
-
-package ledger
-
-import (
- "container/heap"
-
- "github.com/algorand/go-deadlock"
-
- "github.com/algorand/go-algorand/data/basics"
-)
-
-type lruEntry struct {
- useIndex int
- r basics.Round
- x interface{}
-}
-
-type lruHeap struct {
- heap []lruEntry
- lookup map[basics.Round]int
-}
-
-// Len is part of heap.Interface
-func (h *lruHeap) Len() int {
- return len(h.heap)
-}
-
-// Less reports whether the element with
-// index i should sort before the element with index j.
-func (h *lruHeap) Less(i, j int) bool {
- return h.heap[i].useIndex < h.heap[j].useIndex
-}
-
-// Swap swaps the elements with indexes i and j.
-func (h *lruHeap) Swap(i, j int) {
- t := h.heap[i]
- h.heap[i] = h.heap[j]
- h.heap[j] = t
- h.lookup[h.heap[i].r] = i
- h.lookup[h.heap[j].r] = j
-}
-func (h *lruHeap) Push(x interface{}) {
- // add x as element Len()
- xv := x.(lruEntry)
- h.heap = append(h.heap, xv)
- h.lookup[xv.r] = len(h.heap) - 1
-}
-func (h *lruHeap) Pop() interface{} {
- // remove and return element Len() - 1.
- oldlen := len(h.heap)
- out := h.heap[oldlen-1]
- h.heap = h.heap[:oldlen-1]
- delete(h.lookup, out.r)
- return out
-}
-
-type heapLRUCache struct {
- entries lruHeap
- lock deadlock.Mutex
- nextUseIndex int
- maxEntries int
-}
-
-func (hlc *heapLRUCache) Get(r basics.Round) (ob interface{}, exists bool) {
- hlc.lock.Lock()
- defer hlc.lock.Unlock()
- if i, present := hlc.entries.lookup[r]; present {
- out := hlc.entries.heap[i].x
- hlc.entries.heap[i].useIndex = hlc.nextUseIndex
- hlc.inc()
- heap.Fix(&hlc.entries, i)
- return out, true
- }
- return nil, false
-}
-func (hlc *heapLRUCache) Put(r basics.Round, data interface{}) {
- hlc.lock.Lock()
- defer hlc.lock.Unlock()
- if hlc.entries.heap == nil {
- hlc.entries.heap = make([]lruEntry, 1)
- hlc.entries.heap[0] = lruEntry{hlc.nextUseIndex, r, data}
- hlc.inc()
- hlc.entries.lookup = make(map[basics.Round]int)
- hlc.entries.lookup[r] = 0
- return
- }
- if i, present := hlc.entries.lookup[r]; present {
- // update data, but don't adjust LRU order
- hlc.entries.heap[i].x = data
- return
- }
- heap.Push(&hlc.entries, lruEntry{hlc.nextUseIndex, r, data})
- for len(hlc.entries.heap) > hlc.maxEntries {
- heap.Remove(&hlc.entries, 0)
- }
- hlc.inc()
-}
-
-// MaxInt is the maximum int which might be int32 or int64
-const MaxInt = int((^uint(0)) >> 1)
-
-func (hlc *heapLRUCache) inc() {
- hlc.nextUseIndex++
- if hlc.nextUseIndex == MaxInt {
- hlc.reIndex()
- }
-}
-func (hlc *heapLRUCache) reIndex() {
- if len(hlc.entries.heap) == 0 {
- return
- }
- minprio := hlc.entries.heap[0].useIndex
- maxprio := hlc.entries.heap[0].useIndex
- for i := 1; i < len(hlc.entries.heap); i++ {
- xp := hlc.entries.heap[i].useIndex
- if xp < minprio {
- minprio = xp
- }
- if xp > maxprio {
- maxprio = xp
- }
- }
- for i := range hlc.entries.heap {
- hlc.entries.heap[i].useIndex -= minprio
- }
- hlc.nextUseIndex = maxprio + 1 - minprio
-}
diff --git a/ledger/roundlru_test.go b/ledger/roundlru_test.go
deleted file mode 100644
index 8033f34399..0000000000
--- a/ledger/roundlru_test.go
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (C) 2019-2023 Algorand, Inc.
-// This file is part of go-algorand
-//
-// go-algorand is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// go-algorand is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with go-algorand. If not, see .
-
-package ledger
-
-import (
- "testing"
-
- "github.com/stretchr/testify/require"
-
- "github.com/algorand/go-algorand/data/basics"
- "github.com/algorand/go-algorand/test/partitiontest"
-)
-
-func getEq(t *testing.T, cache *heapLRUCache, r basics.Round, expected string) {
- got, exists := cache.Get(r)
- if !exists {
- t.Fatalf("expected value for cache[%v] but not present", r)
- return
- }
- actual := got.(string)
- if actual != expected {
- t.Fatalf("expected %v but got %v for %v", expected, actual, r)
- }
-}
-
-func getNone(t *testing.T, cache *heapLRUCache, r basics.Round) {
- got, exists := cache.Get(r)
- if exists {
- t.Fatalf("expected none for cache[%v] but got %v", r, got)
- return
- }
-}
-
-func TestRoundLRUBasic(t *testing.T) {
- partitiontest.PartitionTest(t)
-
- cache := heapLRUCache{maxEntries: 3}
- cache.Put(1, "one")
- cache.Put(2, "two")
- cache.Put(3, "three")
- getEq(t, &cache, 1, "one")
- getEq(t, &cache, 2, "two")
- getEq(t, &cache, 3, "three")
- cache.Put(4, "four")
- getNone(t, &cache, 1)
- getEq(t, &cache, 3, "three")
- cache.Put(5, "five")
- cache.Put(6, "six")
- getEq(t, &cache, 3, "three")
- getNone(t, &cache, 2)
- getNone(t, &cache, 4)
-}
-
-func TestRoundLRUReIndex(t *testing.T) {
- partitiontest.PartitionTest(t)
-
- cache := heapLRUCache{
- entries: lruHeap{
- heap: []lruEntry{
- {
- useIndex: MaxInt - 2,
- },
- {
- useIndex: MaxInt - 1,
- },
- {
- useIndex: MaxInt - 3,
- },
- },
- },
- maxEntries: 3,
- nextUseIndex: MaxInt - 1,
- }
-
- cache.inc()
-
- require.Equal(t, 3, cache.nextUseIndex)
- require.Equal(t, 1, cache.entries.heap[0].useIndex)
- require.Equal(t, 2, cache.entries.heap[1].useIndex)
- require.Equal(t, 0, cache.entries.heap[2].useIndex)
-}
diff --git a/ledger/tracker.go b/ledger/tracker.go
index ebed56d785..8cfe71aff0 100644
--- a/ledger/tracker.go
+++ b/ledger/tracker.go
@@ -282,6 +282,8 @@ func (dcc deferredCommitContext) newBase() basics.Round {
var errMissingAccountUpdateTracker = errors.New("initializeTrackerCaches : called without a valid accounts update tracker")
func (tr *trackerRegistry) initialize(l ledgerForTracker, trackers []ledgerTracker, cfg config.Local) (err error) {
+ tr.mu.Lock()
+ defer tr.mu.Unlock()
tr.dbs = l.trackerDB()
tr.log = l.trackerLog()
diff --git a/ledger/txtail.go b/ledger/txtail.go
index 7d71ea27ef..31e44be77a 100644
--- a/ledger/txtail.go
+++ b/ledger/txtail.go
@@ -76,7 +76,8 @@ type txTail struct {
// lowestBlockHeaderRound is the lowest round in blockHeaderData, used as a starting point for old entries removal
lowestBlockHeaderRound basics.Round
- // tailMu is the synchronization mutex for accessing roundTailHashes, roundTailSerializedDeltas and blockHeaderData.
+ // tailMu is the synchronization mutex for accessing internal data including
+ // lastValid, recent, lowWaterMark, roundTailHashes, roundTailSerializedDeltas and blockHeaderData.
tailMu deadlock.RWMutex
lastValid map[basics.Round]map[transactions.Txid]struct{} // map tx.LastValid -> tx confirmed set
@@ -90,6 +91,9 @@ type txTail struct {
}
func (t *txTail) loadFromDisk(l ledgerForTracker, dbRound basics.Round) error {
+ t.tailMu.Lock()
+ defer t.tailMu.Unlock()
+
t.log = l.trackerLog()
var roundData []*trackerdb.TxTailRound
@@ -191,6 +195,9 @@ func (t *txTail) close() {
func (t *txTail) newBlock(blk bookkeeping.Block, delta ledgercore.StateDelta) {
rnd := blk.Round()
+ t.tailMu.Lock()
+ defer t.tailMu.Unlock()
+
if _, has := t.recent[rnd]; has {
// Repeat, ignore
return
@@ -202,7 +209,11 @@ func (t *txTail) newBlock(blk bookkeeping.Block, delta ledgercore.StateDelta) {
tail.Hdr = blk.BlockHeader
for txid, txnInc := range delta.Txids {
- t.putLV(txnInc.LastValid, txid)
+ if _, ok := t.lastValid[txnInc.LastValid]; !ok {
+ t.lastValid[txnInc.LastValid] = make(map[transactions.Txid]struct{})
+ }
+ t.lastValid[txnInc.LastValid][txid] = struct{}{}
+
tail.TxnIDs[txnInc.Intra] = txid
tail.LastValid[txnInc.Intra] = txnInc.LastValid
if blk.Payset[txnInc.Intra].Txn.Lease != [32]byte{} {
@@ -215,8 +226,6 @@ func (t *txTail) newBlock(blk bookkeeping.Block, delta ledgercore.StateDelta) {
}
encodedTail, tailHash := tail.Encode()
- t.tailMu.Lock()
- defer t.tailMu.Unlock()
t.recent[rnd] = roundLeases{
txleases: delta.Txleases,
proto: config.Consensus[blk.CurrentProtocol],
@@ -229,6 +238,9 @@ func (t *txTail) newBlock(blk bookkeeping.Block, delta ledgercore.StateDelta) {
}
func (t *txTail) committedUpTo(rnd basics.Round) (retRound, lookback basics.Round) {
+ t.tailMu.Lock()
+ defer t.tailMu.Unlock()
+
proto := t.recent[rnd].proto
maxlife := basics.Round(proto.MaxTxnLife)
@@ -333,6 +345,12 @@ func (t errTxTailMissingRound) Error() string {
// checkDup test to see if the given transaction id/lease already exists. It returns nil if neither exists, or
// TransactionInLedgerError / LeaseInLedgerError respectively.
func (t *txTail) checkDup(proto config.ConsensusParams, current basics.Round, firstValid basics.Round, lastValid basics.Round, txid transactions.Txid, txl ledgercore.Txlease) error {
+ // txTail does not use l.trackerMu, instead uses t.tailMu to make it thread-safe
+ // t.tailMu is sufficient because the state of txTail does not depend on any outside data field
+
+ t.tailMu.RLock()
+ defer t.tailMu.RUnlock()
+
if lastValid < t.lowWaterMark {
return &errTxTailMissingRound{round: lastValid}
}
@@ -359,13 +377,6 @@ func (t *txTail) checkDup(proto config.ConsensusParams, current basics.Round, fi
return nil
}
-func (t *txTail) putLV(lastValid basics.Round, id transactions.Txid) {
- if _, ok := t.lastValid[lastValid]; !ok {
- t.lastValid[lastValid] = make(map[transactions.Txid]struct{})
- }
- t.lastValid[lastValid][id] = struct{}{}
-}
-
func (t *txTail) recentTailHash(offset uint64, retainSize uint64) (crypto.Digest, error) {
// prepare a buffer to hash.
buffer := make([]byte, (retainSize)*crypto.DigestSize)
@@ -387,8 +398,5 @@ func (t *txTail) blockHeader(rnd basics.Round) (bookkeeping.BlockHeader, bool) {
t.tailMu.RLock()
defer t.tailMu.RUnlock()
hdr, ok := t.blockHeaderData[rnd]
- if !ok {
- t.log.Warnf("txtail failed to fetch blockHeader from rnd: %d", rnd)
- }
return hdr, ok
}
diff --git a/network/p2p/dnsaddr/resolve.go b/network/p2p/dnsaddr/resolve.go
index 9ac3010415..2289033aee 100644
--- a/network/p2p/dnsaddr/resolve.go
+++ b/network/p2p/dnsaddr/resolve.go
@@ -69,7 +69,7 @@ func MultiaddrsFromResolver(domain string, controller *MultiaddrDNSResolveContro
return nil, fmt.Errorf("unable to construct multiaddr for %s : %v", domain, err)
}
var resolved []multiaddr.Multiaddr
- err = Iterate(dnsaddr, controller, func(dnsaddr multiaddr.Multiaddr, entries []multiaddr.Multiaddr) error {
+ err = Iterate(dnsaddr, controller, func(_ multiaddr.Multiaddr, entries []multiaddr.Multiaddr) error {
for _, maddr := range entries {
if !isDnsaddr(maddr) {
resolved = append(resolved, maddr)
diff --git a/node/node.go b/node/node.go
index b3b508e91a..87ffd3e2a4 100644
--- a/node/node.go
+++ b/node/node.go
@@ -491,8 +491,19 @@ func (node *AlgorandFullNode) BroadcastInternalSignedTxGroup(txgroup []transacti
return node.broadcastSignedTxGroup(txgroup)
}
+var broadcastTxSucceeded = metrics.MakeCounter(metrics.BroadcastSignedTxGroupSucceeded)
+var broadcastTxFailed = metrics.MakeCounter(metrics.BroadcastSignedTxGroupFailed)
+
// broadcastSignedTxGroup broadcasts a transaction group that has already been signed.
func (node *AlgorandFullNode) broadcastSignedTxGroup(txgroup []transactions.SignedTxn) (err error) {
+ defer func() {
+ if err != nil {
+ broadcastTxFailed.Inc(nil)
+ } else {
+ broadcastTxSucceeded.Inc(nil)
+ }
+ }()
+
lastRound := node.ledger.Latest()
var b bookkeeping.BlockHeader
b, err = node.ledger.BlockHdr(lastRound)
diff --git a/stateproof/abstractions.go b/stateproof/abstractions.go
index 552acd0b82..67f4731882 100644
--- a/stateproof/abstractions.go
+++ b/stateproof/abstractions.go
@@ -18,6 +18,7 @@ package stateproof
import (
"context"
+
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/account"
"github.com/algorand/go-algorand/data/basics"
diff --git a/tools/block-generator/generator/generate.go b/tools/block-generator/generator/generate.go
index 6e9d9fc444..3a899a33b4 100644
--- a/tools/block-generator/generator/generate.go
+++ b/tools/block-generator/generator/generate.go
@@ -27,15 +27,15 @@ import (
"time"
cconfig "github.com/algorand/go-algorand/config"
- "github.com/algorand/go-algorand/ledger/ledgercore"
- "github.com/algorand/go-algorand/protocol"
- "github.com/algorand/go-algorand/rpcs"
-
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated/model"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
txn "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/ledger/ledgercore"
+ "github.com/algorand/go-algorand/logging"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-algorand/rpcs"
)
// ---- templates ----
@@ -55,14 +55,19 @@ var clearSwap string
// ---- constructors ----
// MakeGenerator initializes the Generator object.
-func MakeGenerator(dbround uint64, bkGenesis bookkeeping.Genesis, config GenerationConfig, verbose bool) (Generator, error) {
+func MakeGenerator(log logging.Logger, dbround uint64, bkGenesis bookkeeping.Genesis, config GenerationConfig, verbose bool) (Generator, error) {
if err := config.validateWithDefaults(false); err != nil {
return nil, fmt.Errorf("invalid generator configuration: %w", err)
}
+ if log == nil {
+ log = logging.Base()
+ }
+
var proto protocol.ConsensusVersion = "future"
gen := &generator{
verbose: verbose,
+ log: log,
config: config,
protocol: proto,
params: cconfig.Consensus[proto],
diff --git a/tools/block-generator/generator/generate_test.go b/tools/block-generator/generator/generate_test.go
index 4ae79d9e71..29a2613d64 100644
--- a/tools/block-generator/generator/generate_test.go
+++ b/tools/block-generator/generator/generate_test.go
@@ -24,15 +24,17 @@ import (
"testing"
"time"
+ "github.com/stretchr/testify/require"
+
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/bookkeeping"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/data/transactions/logic"
+ "github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/rpcs"
"github.com/algorand/go-algorand/test/partitiontest"
- "github.com/stretchr/testify/require"
)
func makePrivateGenerator(t *testing.T, round uint64, genesis bookkeeping.Genesis) *generator {
@@ -45,7 +47,7 @@ func makePrivateGenerator(t *testing.T, round uint64, genesis bookkeeping.Genesi
AssetCreateFraction: 1.0,
}
cfg.validateWithDefaults(true)
- publicGenerator, err := MakeGenerator(round, genesis, cfg, true)
+ publicGenerator, err := MakeGenerator(logging.Base(), round, genesis, cfg, true)
require.NoError(t, err)
return publicGenerator.(*generator)
}
@@ -355,7 +357,7 @@ func TestAppBoxesOptin(t *testing.T) {
paySiblingTxn := sgnTxns[1].Txn
require.Equal(t, protocol.PaymentTx, paySiblingTxn.Type)
-
+
g.finishRound()
// 2nd attempt to optin (with new sender) doesn't get replaced
g.startRound()
@@ -723,21 +725,21 @@ func TestCumulativeEffects(t *testing.T) {
partitiontest.PartitionTest(t)
report := Report{
- TxTypeID("app_boxes_optin"): {GenerationCount: uint64(42)},
- TxTypeID("app_boxes_create"): {GenerationCount: uint64(1337)},
- TxTypeID("pay_pay"): {GenerationCount: uint64(999)},
- TxTypeID("asset_optin_total"): {GenerationCount: uint64(13)},
- TxTypeID("app_boxes_call"): {GenerationCount: uint64(413)},
+ TxTypeID("app_boxes_optin"): {GenerationCount: uint64(42)},
+ TxTypeID("app_boxes_create"): {GenerationCount: uint64(1337)},
+ TxTypeID("pay_pay"): {GenerationCount: uint64(999)},
+ TxTypeID("asset_optin_total"): {GenerationCount: uint64(13)},
+ TxTypeID("app_boxes_call"): {GenerationCount: uint64(413)},
}
expectedEffectsReport := EffectsReport{
- "app_boxes_optin": uint64(42),
- "app_boxes_create": uint64(1337),
- "pay_pay": uint64(999),
- "asset_optin_total": uint64(13),
- "app_boxes_call": uint64(413),
- "effect_payment_sibling": uint64(42) + uint64(1337),
- "effect_inner_tx": uint64(2 * 42),
+ "app_boxes_optin": uint64(42),
+ "app_boxes_create": uint64(1337),
+ "pay_pay": uint64(999),
+ "asset_optin_total": uint64(13),
+ "app_boxes_call": uint64(413),
+ "effect_payment_sibling": uint64(42) + uint64(1337),
+ "effect_inner_tx": uint64(2 * 42),
}
require.Equal(t, expectedEffectsReport, CumulativeEffects(report))
@@ -772,7 +774,7 @@ func TestCountInners(t *testing.T) {
InnerTxns: []transactions.SignedTxnWithAD{
{
ApplyData: transactions.ApplyData{
- EvalDelta: transactions.EvalDelta{
+ EvalDelta: transactions.EvalDelta{
InnerTxns: []transactions.SignedTxnWithAD{{}, {}},
},
},
@@ -793,4 +795,3 @@ func TestCountInners(t *testing.T) {
})
}
}
-
diff --git a/tools/block-generator/generator/generator_ledger.go b/tools/block-generator/generator/generator_ledger.go
index c129065668..97fed9b344 100644
--- a/tools/block-generator/generator/generator_ledger.go
+++ b/tools/block-generator/generator/generator_ledger.go
@@ -31,7 +31,6 @@ import (
"github.com/algorand/go-algorand/ledger"
"github.com/algorand/go-algorand/ledger/eval"
"github.com/algorand/go-algorand/ledger/ledgercore"
- "github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/rpcs"
)
@@ -40,7 +39,7 @@ import (
func (g *generator) setBlockHeader(cert *rpcs.EncodedBlockCert) {
cert.Block.BlockHeader = bookkeeping.BlockHeader{
Round: basics.Round(g.round),
- TxnCounter: g.txnCounter,
+ TxnCounter: g.txnCounter,
Branch: bookkeeping.BlockHash{},
Seed: committee.Seed{},
TxnCommitments: bookkeeping.TxnCommitments{NativeSha512_256Commitment: crypto.Digest{}},
@@ -63,10 +62,9 @@ func (g *generator) setBlockHeader(cert *rpcs.EncodedBlockCert) {
}
}
-
// ---- ledger simulation and introspection ----
-// initializeLedger creates a new ledger
+// initializeLedger creates a new ledger
func (g *generator) initializeLedger() {
genBal := convertToGenesisBalances(g.balances)
// add rewards pool with min balance
@@ -85,7 +83,7 @@ func (g *generator) initializeLedger() {
} else {
prefix = g.genesisID
}
- l, err := ledger.OpenLedger(logging.Base(), prefix, true, ledgercore.InitState{
+ l, err := ledger.OpenLedger(g.log, prefix, true, ledgercore.InitState{
Block: block,
Accounts: bal.Balances,
GenesisHash: g.genesisHash,
diff --git a/tools/block-generator/generator/generator_types.go b/tools/block-generator/generator/generator_types.go
index c0ff24b4c0..6685ffe7c8 100644
--- a/tools/block-generator/generator/generator_types.go
+++ b/tools/block-generator/generator/generator_types.go
@@ -26,6 +26,7 @@ import (
"github.com/algorand/go-algorand/data/bookkeeping"
txn "github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/ledger"
+ "github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/protocol"
)
@@ -42,6 +43,7 @@ type Generator interface {
type generator struct {
verbose bool
+ log logging.Logger
config GenerationConfig
@@ -52,7 +54,7 @@ type generator struct {
numAccounts uint64
// Block stuff
- round uint64
+ round uint64
txnCounter uint64
prevBlockHash string
timestamp int64
diff --git a/tools/block-generator/generator/server.go b/tools/block-generator/generator/server.go
index 2aac4a4552..4de0d08322 100644
--- a/tools/block-generator/generator/server.go
+++ b/tools/block-generator/generator/server.go
@@ -24,6 +24,7 @@ import (
"time"
"github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/tools/block-generator/util"
)
@@ -32,7 +33,7 @@ func MakeServer(configFile string, addr string) (*http.Server, Generator) {
noOp := func(next http.Handler) http.Handler {
return next
}
- return MakeServerWithMiddleware(0, "", configFile, false, addr, noOp)
+ return MakeServerWithMiddleware(nil, 0, "", configFile, false, addr, noOp)
}
// BlocksMiddleware is a middleware for the blocks endpoint.
@@ -41,7 +42,7 @@ type BlocksMiddleware func(next http.Handler) http.Handler
// MakeServerWithMiddleware allows injecting a middleware for the blocks handler.
// This is needed to simplify tests by stopping block production while validation
// is done on the data.
-func MakeServerWithMiddleware(dbround uint64, genesisFile string, configFile string, verbose bool, addr string, blocksMiddleware BlocksMiddleware) (*http.Server, Generator) {
+func MakeServerWithMiddleware(log logging.Logger, dbround uint64, genesisFile string, configFile string, verbose bool, addr string, blocksMiddleware BlocksMiddleware) (*http.Server, Generator) {
cfg, err := initializeConfigFile(configFile)
util.MaybeFail(err, "problem loading config file. Use '--config' or create a config file.")
var bkGenesis bookkeeping.Genesis
@@ -50,7 +51,7 @@ func MakeServerWithMiddleware(dbround uint64, genesisFile string, configFile str
// TODO: consider using bkGenesis to set cfg.NumGenesisAccounts and cfg.GenesisAccountInitialBalance
util.MaybeFail(err, "Failed to parse genesis file '%s'", genesisFile)
}
- gen, err := MakeGenerator(dbround, bkGenesis, cfg, verbose)
+ gen, err := MakeGenerator(log, dbround, bkGenesis, cfg, verbose)
util.MaybeFail(err, "Failed to make generator with config file '%s'", configFile)
mux := http.NewServeMux()
diff --git a/tools/block-generator/go.mod b/tools/block-generator/go.mod
index e3036565d1..6eadc0421a 100644
--- a/tools/block-generator/go.mod
+++ b/tools/block-generator/go.mod
@@ -6,7 +6,7 @@ go 1.20
require (
github.com/algorand/avm-abi v0.2.0
- github.com/algorand/go-algorand v0.0.0-00010101000000-000000000000
+ github.com/algorand/go-algorand v0.0.0
github.com/algorand/go-codec/codec v1.1.10
github.com/algorand/go-deadlock v0.2.2
github.com/lib/pq v1.10.9
diff --git a/tools/block-generator/runner/run.go b/tools/block-generator/runner/run.go
index 626a4493a6..31c83dc91b 100644
--- a/tools/block-generator/runner/run.go
+++ b/tools/block-generator/runner/run.go
@@ -35,14 +35,18 @@ import (
"text/template"
"time"
+ "github.com/algorand/go-deadlock"
+
+ "github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/tools/block-generator/generator"
"github.com/algorand/go-algorand/tools/block-generator/util"
- "github.com/algorand/go-deadlock"
)
//go:embed template/conduit.yml.tmpl
var conduitConfigTmpl string
+const pad = " "
+
// Args are all the things needed to run a performance test.
type Args struct {
// Path is a directory when passed to RunBatch, otherwise a file path.
@@ -107,7 +111,9 @@ func Run(args Args) error {
}
runnerArgs := args
runnerArgs.Path = path
- fmt.Printf("Running test for configuration '%s'\n", path)
+ fmt.Println("----------------------------------------")
+ fmt.Printf("%sRunning test for configuration: %s\n", pad, info.Name())
+ fmt.Println("----------------------------------------")
return runnerArgs.run(reportDirectory)
})
if err != nil {
@@ -121,7 +127,8 @@ func (r *Args) run(reportDirectory string) error {
baseName := filepath.Base(r.Path)
baseNameNoExt := strings.TrimSuffix(baseName, filepath.Ext(baseName))
reportfile := path.Join(reportDirectory, fmt.Sprintf("%s.report", baseNameNoExt))
- logfile := path.Join(reportDirectory, fmt.Sprintf("%s.conduit-log", baseNameNoExt))
+ conduitlogfile := path.Join(reportDirectory, fmt.Sprintf("%s.conduit-log", baseNameNoExt))
+ ledgerlogfile := path.Join(reportDirectory, fmt.Sprintf("%s.ledger-log", baseNameNoExt))
dataDir := path.Join(reportDirectory, fmt.Sprintf("%s_data", baseNameNoExt))
// create the data directory.
if err := os.Mkdir(dataDir, os.ModeDir|os.ModePerm); err != nil {
@@ -155,35 +162,38 @@ func (r *Args) run(reportDirectory string) error {
} else if err != nil {
return fmt.Errorf("getNextRound err: %w", err)
}
+ fmt.Printf("%sPostgreSQL next round: %d\n", pad, nextRound)
}
// Start services
algodNet := fmt.Sprintf("localhost:%d", 11112)
metricsNet := fmt.Sprintf("localhost:%d", r.MetricsPort)
- generatorShutdownFunc, _ := startGenerator(r.Path, nextRound, r.GenesisFile, r.RunnerVerbose, algodNet, blockMiddleware)
+ generatorShutdownFunc, _ := startGenerator(ledgerlogfile, r.Path, nextRound, r.GenesisFile, r.RunnerVerbose, algodNet, blockMiddleware)
defer func() {
// Shutdown generator.
+ fmt.Printf("%sShutting down generator...\n", pad)
if err := generatorShutdownFunc(); err != nil {
fmt.Printf("failed to shutdown generator: %s\n", err)
}
}()
- // get conduit config template
+
+ // create conduit config from template
t, err := template.New("conduit").Parse(conduitConfigTmpl)
if err != nil {
return fmt.Errorf("unable to parse conduit config template: %w", err)
}
-
// create config file in the right data directory
f, err := os.Create(path.Join(dataDir, "conduit.yml"))
if err != nil {
return fmt.Errorf("problem creating conduit.yml: %w", err)
}
defer f.Close()
-
- conduitConfig := config{r.ConduitLogLevel, logfile,
- fmt.Sprintf(":%d", r.MetricsPort),
- algodNet, r.PostgresConnectionString,
+ conduitConfig := config{
+ LogLevel: r.ConduitLogLevel,
+ LogFile: conduitlogfile,
+ MetricsPort: fmt.Sprintf(":%d", r.MetricsPort),
+ AlgodNet: algodNet,
+ PostgresConnectionString: r.PostgresConnectionString,
}
-
err = t.Execute(f, conduitConfig)
if err != nil {
return fmt.Errorf("problem executing template file: %w", err)
@@ -196,6 +206,7 @@ func (r *Args) run(reportDirectory string) error {
}
defer func() {
// Shutdown conduit
+ fmt.Printf("%sShutting down Conduit...\n", pad)
if sdErr := conduitShutdownFunc(); sdErr != nil {
fmt.Printf("failed to shutdown Conduit: %s\n", sdErr)
}
@@ -225,6 +236,7 @@ func (r *Args) run(reportDirectory string) error {
if err = r.runTest(report, metricsNet, algodNet); err != nil {
return err
}
+ fmt.Printf("%sTest completed successfully\n", pad)
return nil
}
@@ -362,15 +374,19 @@ func (r *Args) runTest(report *os.File, metricsURL string, generatorURL string)
// Run for r.RunDuration
start := time.Now()
+ fmt.Printf("%sduration starting now: %s\n", pad, start)
count := 1
for time.Since(start) < r.RunDuration {
time.Sleep(r.RunDuration / 10)
+ fmt.Printf("%scollecting metrics (%d)\n", pad, count)
if err := collector.Collect(AllMetricNames...); err != nil {
return fmt.Errorf("problem collecting metrics (%d / %s): %w", count, time.Since(start), err)
}
count++
}
+
+ fmt.Printf("%scollecting final metrics\n", pad)
if err := collector.Collect(AllMetricNames...); err != nil {
return fmt.Errorf("problem collecting final metrics (%d / %s): %w", count, time.Since(start), err)
}
@@ -438,14 +454,20 @@ func (r *Args) runTest(report *os.File, metricsURL string, generatorURL string)
}
// startGenerator starts the generator server.
-func startGenerator(configFile string, dbround uint64, genesisFile string, verbose bool, addr string, blockMiddleware func(http.Handler) http.Handler) (func() error, generator.Generator) {
+func startGenerator(ledgerLogFile, configFile string, dbround uint64, genesisFile string, verbose bool, addr string, blockMiddleware func(http.Handler) http.Handler) (func() error, generator.Generator) {
+ f, err := os.OpenFile(ledgerLogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
+ util.MaybeFail(err, "unable to open ledger log file '%s'", ledgerLogFile)
+ log := logging.NewLogger()
+ log.SetLevel(logging.Warn)
+ log.SetOutput(f)
+
// Start generator.
- server, generator := generator.MakeServerWithMiddleware(dbround, genesisFile, configFile, verbose, addr, blockMiddleware)
+ server, generator := generator.MakeServerWithMiddleware(log, dbround, genesisFile, configFile, verbose, addr, blockMiddleware)
// Start the server
go func() {
// always returns error. ErrServerClosed on graceful close
- fmt.Printf("generator serving on %s\n", server.Addr)
+ fmt.Printf("%sgenerator serving on %s\n", pad, server.Addr)
if err := server.ListenAndServe(); err != http.ErrServerClosed {
util.MaybeFail(err, "ListenAndServe() failure to start with config file '%s'", configFile)
}
@@ -464,7 +486,7 @@ func startGenerator(configFile string, dbround uint64, genesisFile string, verbo
// startConduit starts the conduit binary.
func startConduit(dataDir string, conduitBinary string, round uint64) (func() error, error) {
- fmt.Printf("Conduit starting with data directory: %s", dataDir)
+ fmt.Printf("%sConduit starting with data directory: %s\n", pad, dataDir)
cmd := exec.Command(
conduitBinary,
"-r", strconv.FormatUint(round, 10),
@@ -472,9 +494,8 @@ func startConduit(dataDir string, conduitBinary string, round uint64) (func() er
)
var stdout bytes.Buffer
- var stderr bytes.Buffer
cmd.Stdout = &stdout
- cmd.Stderr = &stderr
+ cmd.Stderr = os.Stderr // pass errors to Stderr
if err := cmd.Start(); err != nil {
return nil, fmt.Errorf("failure calling Start(): %w", err)
@@ -489,7 +510,7 @@ func startConduit(dataDir string, conduitBinary string, round uint64) (func() er
}
}
if err := cmd.Wait(); err != nil {
- fmt.Printf("Conduit exiting: %s\n", err)
+ fmt.Printf("%sConduit exiting: %s\n", pad, err)
}
return nil
}, nil
diff --git a/tools/block-generator/runner/template/conduit.yml.tmpl b/tools/block-generator/runner/template/conduit.yml.tmpl
index c361426ee6..d461dd5647 100644
--- a/tools/block-generator/runner/template/conduit.yml.tmpl
+++ b/tools/block-generator/runner/template/conduit.yml.tmpl
@@ -5,7 +5,7 @@ log-level: {{.LogLevel}}
log-file: {{.LogFile}}
# Number of retries to perform after a pipeline plugin error.
-retry-count: 10
+retry-count: 120
# Time duration to wait between retry attempts.
retry-delay: "1s"
diff --git a/tools/x-repo-types/Makefile b/tools/x-repo-types/Makefile
index 05094a8484..900b492716 100644
--- a/tools/x-repo-types/Makefile
+++ b/tools/x-repo-types/Makefile
@@ -1,38 +1,51 @@
-all: goal-v-sdk goal-v-spv
+all: clean goal-v-sdk goal-v-spv
+
+clean:
+ rm x-repo-types
+
+x-repo-types:
+ go build
# go-algorand vs go-algorand-sdk:
goal-v-sdk: goal-v-sdk-state-delta goal-v-sdk-genesis goal-v-sdk-block goal-v-sdk-blockheader goal-v-sdk-stateproof
-goal-v-sdk-state-delta:
+goal-v-sdk-state-delta: x-repo-types
x-repo-types --x-package "github.com/algorand/go-algorand/ledger/ledgercore" \
--x-type "StateDelta" \
--y-branch "develop" \
--y-package "github.com/algorand/go-algorand-sdk/v2/types" \
--y-type "LedgerStateDelta"
-goal-v-sdk-genesis:
+goal-v-sdk-genesis: x-repo-types
x-repo-types --x-package "github.com/algorand/go-algorand/data/bookkeeping" \
--x-type "Genesis" \
--y-branch "develop" \
--y-package "github.com/algorand/go-algorand-sdk/v2/types" \
--y-type "Genesis"
-goal-v-sdk-block:
+goal-v-sdk-block: x-repo-types
x-repo-types --x-package "github.com/algorand/go-algorand/data/bookkeeping" \
--x-type "Block" \
--y-branch "develop" \
--y-package "github.com/algorand/go-algorand-sdk/v2/types" \
--y-type "Block"
-goal-v-sdk-blockheader:
+goal-v-sdk-blockheader: x-repo-types
x-repo-types --x-package "github.com/algorand/go-algorand/data/bookkeeping" \
--x-type "BlockHeader" \
--y-branch "develop" \
--y-package "github.com/algorand/go-algorand-sdk/v2/types" \
--y-type "BlockHeader"
-goal-v-sdk-stateproof:
+goal-v-sdk-consensus: x-repo-types
+ x-repo-types --x-package "github.com/algorand/go-algorand/config" \
+ --x-type "ConsensusParams" \
+ --y-branch "develop" \
+ --y-package "github.com/algorand/go-algorand-sdk/v2/protocol/config" \
+ --y-type "ConsensusParams"
+
+goal-v-sdk-stateproof: x-repo-types
x-repo-types --x-package "github.com/algorand/go-algorand/crypto/stateproof" \
--x-type "StateProof" \
--y-branch "develop" \
diff --git a/tools/x-repo-types/go.mod b/tools/x-repo-types/go.mod
index 8c0146b70c..df9ddf0114 100644
--- a/tools/x-repo-types/go.mod
+++ b/tools/x-repo-types/go.mod
@@ -5,7 +5,7 @@ go 1.20
replace github.com/algorand/go-algorand => ../..
require (
- github.com/algorand/go-algorand v0.0.0-20230502140608-e24a35add0bb
+ github.com/algorand/go-algorand v0.0.0
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
)
diff --git a/util/metrics/metrics.go b/util/metrics/metrics.go
index bd68ff4c1e..cb376eb0a3 100644
--- a/util/metrics/metrics.go
+++ b/util/metrics/metrics.go
@@ -132,4 +132,9 @@ var (
TransactionGroupTxSyncRemember = MetricName{Name: "algod_transaction_group_txsync_remember", Description: "Number of transaction groups remembered via txsync"}
// TransactionGroupTxSyncAlreadyCommitted "Number of duplicate or error transaction groups received via txsync"
TransactionGroupTxSyncAlreadyCommitted = MetricName{Name: "algod_transaction_group_txsync_err_or_committed", Description: "Number of duplicate or error transaction groups received via txsync"}
+
+ // BroadcastSignedTxGroupSucceeded "Number of successful broadcasts of local signed transaction groups"
+ BroadcastSignedTxGroupSucceeded = MetricName{Name: "algod_broadcast_txgroup_succeeded", Description: "Number of successful broadcasts of local signed transaction groups"}
+ // BroadcastSignedTxGroupFailed "Number of failed broadcasts of local signed transaction groups"
+ BroadcastSignedTxGroupFailed = MetricName{Name: "algod_broadcast_txgroup_failed", Description: "Number of failed broadcasts of local signed transaction groups"}
)