diff --git a/.circleci/config.yml b/.circleci/config.yml
index b9ac9f3faf..8208fe063b 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -303,7 +303,7 @@ jobs:
parameters:
platform:
type: string
- executor: << parameters.platform >>_medium
+ executor: << parameters.platform >>_large
working_directory: << pipeline.parameters.build_dir >>/project
parallelism: 10
environment:
@@ -319,7 +319,7 @@ jobs:
parameters:
platform:
type: string
- executor: << parameters.platform >>_medium
+ executor: << parameters.platform >>_large
working_directory: << pipeline.parameters.build_dir >>/project
parallelism: 2
environment:
diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml
index 5e11c6cac9..bd7c93f7e5 100644
--- a/.github/workflows/benchmarks.yml
+++ b/.github/workflows/benchmarks.yml
@@ -17,7 +17,7 @@ jobs:
name: Performance regression check
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3.5.3
+ - uses: actions/checkout@v4
- uses: actions/setup-go@v4.0.1
with:
go-version-file: 'go.mod'
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 785304b0db..0c08e8abbb 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -17,7 +17,7 @@ jobs:
update: true
path-type: inherit
- name: Check out code
- uses: actions/checkout@v3.5.3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine Go version
diff --git a/.github/workflows/codegen_verification.yml b/.github/workflows/codegen_verification.yml
index a01e3e5e9c..ad90754d10 100644
--- a/.github/workflows/codegen_verification.yml
+++ b/.github/workflows/codegen_verification.yml
@@ -14,7 +14,7 @@ jobs:
- 8080:8080
steps:
- name: Check out code
- uses: actions/checkout@v3.5.3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
path: go-algorand
diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml
index 75134a6d6a..074196e01a 100644
--- a/.github/workflows/container.yml
+++ b/.github/workflows/container.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
- uses: actions/checkout@v3.5.3
+ uses: actions/checkout@v4
- name: Generate Container Metadata
id: meta
@@ -59,7 +59,7 @@ jobs:
# if: github.ref == format('refs/heads/{0}', 'master')
# steps:
# - name: Checkout Code
- # uses: actions/checkout@v3.5.3
+ # uses: actions/checkout@v4
# - name: Update DockerHub Repository Description
# uses: peter-evans/dockerhub-description@v3
diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml
index efa0d75217..1eff6ac578 100644
--- a/.github/workflows/reviewdog.yml
+++ b/.github/workflows/reviewdog.yml
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
- uses: actions/checkout@v3.5.3
+ uses: actions/checkout@v4
with:
fetch-depth: 0 # required for new-from-rev option in .golangci.yml
# move go out of the way temporarily to avoid "go list ./..." from installing modules
@@ -32,7 +32,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
- uses: actions/checkout@v3.5.3
+ uses: actions/checkout@v4
with:
fetch-depth: 0 # required for new-from-rev option in .golangci.yml
# move go out of the way temporarily to avoid "go list ./..." from installing modules
diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml
index 064f100f4a..95acb22474 100644
--- a/.github/workflows/tools.yml
+++ b/.github/workflows/tools.yml
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
- uses: actions/checkout@v3.5.3
+ uses: actions/checkout@v4
# move go out of the way temporarily to avoid "go list ./..." from installing modules
- name: Make libsodium.a
run: sudo mv /usr/bin/go /usr/bin/go.bak && make crypto/libs/linux/amd64/lib/libsodium.a && sudo mv /usr/bin/go.bak /usr/bin/go
diff --git a/CODEOWNERS b/CODEOWNERS
deleted file mode 100644
index 3c88c6e71e..0000000000
--- a/CODEOWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-.github/ @algorand/devops
-.circleci/ @algorand/devops
diff --git a/agreement/proposal.go b/agreement/proposal.go
index e696bfeb4b..e8d506c4b5 100644
--- a/agreement/proposal.go
+++ b/agreement/proposal.go
@@ -277,7 +277,7 @@ func verifyProposer(p unauthenticatedProposal, ledger LedgerReader) error {
// the header lacks it, the returned balanceRecord will be the right record.
func payoutEligible(rnd basics.Round, proposer basics.Address, ledger LedgerReader, cparams config.ConsensusParams) (bool, basics.OnlineAccountData, error) {
// Check the balance from the agreement round
- balanceRound := balanceRound(rnd, cparams)
+ balanceRound := BalanceRound(rnd, cparams)
balanceRecord, err := ledger.LookupAgreement(balanceRound, proposer)
if err != nil {
return false, basics.OnlineAccountData{}, err
diff --git a/agreement/proposalManager.go b/agreement/proposalManager.go
index 6ec8d2e1b6..472e8bb975 100644
--- a/agreement/proposalManager.go
+++ b/agreement/proposalManager.go
@@ -245,7 +245,7 @@ func (m *proposalManager) handleMessageEvent(r routerHandle, p player, e filtera
}
}
-// filterVote filters a vote, checking if it is both fresh and not a duplicate, returning
+// filterProposalVote filters a vote, checking if it is both fresh and not a duplicate, returning
// an errProposalManagerPVNotFresh or errProposalManagerPVDuplicate if so, else nil.
// It also returns a bool indicating whether this proposal-vote should still be verified for tracking credential history.
func (m *proposalManager) filterProposalVote(p player, r routerHandle, uv unauthenticatedVote, freshData freshnessData) (bool, error) {
diff --git a/agreement/pseudonode.go b/agreement/pseudonode.go
index fe5423c025..32e42cd374 100644
--- a/agreement/pseudonode.go
+++ b/agreement/pseudonode.go
@@ -220,7 +220,7 @@ func (n *asyncPseudonode) loadRoundParticipationKeys(voteRound basics.Round) []a
n.participationKeys = nil
return nil
}
- balanceRound := balanceRound(voteRound, cparams)
+ balanceRound := BalanceRound(voteRound, cparams)
// measure the time it takes to acquire the voting keys.
beforeVotingKeysTime := time.Now()
@@ -422,6 +422,9 @@ func (t pseudonodeVotesTask) execute(verifier *AsyncVoteVerifier, quit chan stru
Type: logspec.VoteBroadcast,
Sender: vote.R.Sender.String(),
Hash: vote.R.Proposal.BlockDigest.String(),
+ Round: uint64(t.round),
+ Period: uint64(t.period),
+ Step: uint64(t.step),
ObjectRound: uint64(vote.R.Round),
ObjectPeriod: uint64(vote.R.Period),
ObjectStep: uint64(vote.R.Step),
@@ -549,6 +552,8 @@ func (t pseudonodeProposalsTask) execute(verifier *AsyncVoteVerifier, quit chan
logEvent := logspec.AgreementEvent{
Type: logspec.ProposalBroadcast,
Hash: vote.R.Proposal.BlockDigest.String(),
+ Round: uint64(t.round),
+ Period: uint64(t.period),
ObjectRound: uint64(vote.R.Round),
ObjectPeriod: uint64(vote.R.Period),
}
diff --git a/agreement/pseudonode_test.go b/agreement/pseudonode_test.go
index ee83061ba0..fdc92f1805 100644
--- a/agreement/pseudonode_test.go
+++ b/agreement/pseudonode_test.go
@@ -449,7 +449,7 @@ func TestPseudonodeLoadingOfParticipationKeys(t *testing.T) {
for rnd := basics.Round(3); rnd < 1000; rnd += 43 {
keyManagerProxy.target = func(votingRound, balanceRnd basics.Round) []account.ParticipationRecordForRound {
require.Equal(t, rnd, votingRound)
- require.Equal(t, balanceRound(rnd, cparams), balanceRnd)
+ require.Equal(t, BalanceRound(rnd, cparams), balanceRnd)
return keyManager.VotingKeys(votingRound, balanceRnd)
}
pb.loadRoundParticipationKeys(basics.Round(rnd))
diff --git a/agreement/selector.go b/agreement/selector.go
index 76f9d5a312..2d0f980ac3 100644
--- a/agreement/selector.go
+++ b/agreement/selector.go
@@ -47,7 +47,10 @@ func (sel selector) CommitteeSize(proto config.ConsensusParams) uint64 {
return sel.Step.committeeSize(proto)
}
-func balanceRound(r basics.Round, cparams config.ConsensusParams) basics.Round {
+// BalanceRound returns the round that should be considered by agreement when
+// looking at online stake (and status and key material). It is exported so that
+// AVM can provide opcodes that return the same data.
+func BalanceRound(r basics.Round, cparams config.ConsensusParams) basics.Round {
return r.SubSaturate(basics.Round(2 * cparams.SeedRefreshInterval * cparams.SeedLookback))
}
@@ -61,7 +64,7 @@ func membership(l LedgerReader, addr basics.Address, r basics.Round, p period, s
if err != nil {
return
}
- balanceRound := balanceRound(r, cparams)
+ balanceRound := BalanceRound(r, cparams)
seedRound := seedRound(r, cparams)
record, err := l.LookupAgreement(balanceRound, addr)
diff --git a/catchup/catchpointService.go b/catchup/catchpointService.go
index 3954c1cd6c..974f5964f1 100644
--- a/catchup/catchpointService.go
+++ b/catchup/catchpointService.go
@@ -698,7 +698,7 @@ func (cs *CatchpointCatchupService) fetchBlock(round basics.Round, retryCount ui
return blk, cert, downloadDuration, psp, false, nil
}
-// processStageLedgerDownload is the fifth catchpoint catchup stage. It completes the catchup process, swap the new tables and restart the node functionality.
+// processStageSwitch is the fifth catchpoint catchup stage. It completes the catchup process, swap the new tables and restart the node functionality.
func (cs *CatchpointCatchupService) processStageSwitch() (err error) {
err = cs.ledgerAccessor.CompleteCatchup(cs.ctx)
if err != nil {
diff --git a/catchup/universalFetcher.go b/catchup/universalFetcher.go
index 926c85bb48..31d82adc98 100644
--- a/catchup/universalFetcher.go
+++ b/catchup/universalFetcher.go
@@ -43,7 +43,7 @@ type universalBlockFetcher struct {
log logging.Logger
}
-// makeUniversalFetcher returns a fetcher for http and ws peers.
+// makeUniversalBlockFetcher returns a fetcher for http and ws peers.
func makeUniversalBlockFetcher(log logging.Logger, net network.GossipNode, config config.Local) *universalBlockFetcher {
return &universalBlockFetcher{
config: config,
diff --git a/cmd/goal/application.go b/cmd/goal/application.go
index 922540b726..0a42f65b5d 100644
--- a/cmd/goal/application.go
+++ b/cmd/goal/application.go
@@ -1179,7 +1179,7 @@ const maxAppArgs = 16
// minus 1 for the final app argument becoming a tuple of the remaining method args
const methodArgsTupleThreshold = maxAppArgs - 2
-// parseArgJSONtoByteSlice convert input method arguments to ABI encoded bytes
+// parseMethodArgJSONtoByteSlice convert input method arguments to ABI encoded bytes
// it converts funcArgTypes into a tuple type and apply changes over input argument string (in JSON format)
// if there are greater or equal to 15 inputs, then we compact the tailing inputs into one tuple
func parseMethodArgJSONtoByteSlice(argTypes []string, jsonArgs []string, applicationArgs *[][]byte) error {
diff --git a/cmd/netgoal/network.go b/cmd/netgoal/network.go
index 69fecbac26..d4ed3c277c 100644
--- a/cmd/netgoal/network.go
+++ b/cmd/netgoal/network.go
@@ -168,9 +168,9 @@ func runBuildNetwork() error {
return fmt.Errorf("error resolving bootstrap file: %v", err)
}
net.BootstrappedNet = fileTemplate
- net.SetUseBoostrappedFiles(bootstrapLoadingFile)
+ net.SetUseBootstrappedFiles(bootstrapLoadingFile)
} else {
- net.SetUseBoostrappedFiles(false)
+ net.SetUseBootstrappedFiles(false)
}
net.SetUseExistingGenesisFiles(networkUseGenesisFiles)
diff --git a/cmd/tealdbg/localLedger.go b/cmd/tealdbg/localLedger.go
index d97c8df70f..d495fbb328 100644
--- a/cmd/tealdbg/localLedger.go
+++ b/cmd/tealdbg/localLedger.go
@@ -336,6 +336,34 @@ func (l *localLedger) LookupWithoutRewards(rnd basics.Round, addr basics.Address
return ledgercore.ToAccountData(ad), rnd, nil
}
+func (l *localLedger) LookupAgreement(rnd basics.Round, addr basics.Address) (basics.OnlineAccountData, error) {
+ // tealdbg does not understand rewards, so no pending rewards are applied.
+ // Further, it has no history, so we return the _current_ information,
+ // ignoring the `rnd` argument.
+ ad := l.balances[addr]
+ if ad.Status != basics.Online {
+ return basics.OnlineAccountData{}, nil
+ }
+
+ return basics.OnlineAccountData{
+ MicroAlgosWithRewards: ad.MicroAlgos,
+ VotingData: basics.VotingData{
+ VoteID: ad.VoteID,
+ SelectionID: ad.SelectionID,
+ StateProofID: ad.StateProofID,
+ VoteFirstValid: ad.VoteFirstValid,
+ VoteLastValid: ad.VoteLastValid,
+ VoteKeyDilution: ad.VoteKeyDilution,
+ },
+ IncentiveEligible: ad.IncentiveEligible,
+ }, nil
+}
+
+func (l *localLedger) OnlineCirculation(rnd basics.Round, voteRound basics.Round) (basics.MicroAlgos, error) {
+ // A constant is fine for tealdbg
+ return basics.Algos(1_000_000_000), nil // 1B
+}
+
func (l *localLedger) GetCreatorForRound(rnd basics.Round, cidx basics.CreatableIndex, ctype basics.CreatableType) (basics.Address, bool, error) {
switch ctype {
case basics.AssetCreatable:
diff --git a/config/version.go b/config/version.go
index 643ac34e86..8716fbcdcb 100644
--- a/config/version.go
+++ b/config/version.go
@@ -33,7 +33,7 @@ const VersionMajor = 3
// VersionMinor is the Minor semantic version number (x.#.z) - changed when backwards-compatible features are introduced.
// Not enforced until after initial public release (x > 0).
-const VersionMinor = 24
+const VersionMinor = 25
// Version is the type holding our full version information.
type Version struct {
diff --git a/daemon/algod/api/algod.oas2.json b/daemon/algod/api/algod.oas2.json
index 704b8a4638..36e4f34861 100644
--- a/daemon/algod/api/algod.oas2.json
+++ b/daemon/algod/api/algod.oas2.json
@@ -178,6 +178,44 @@
}
}
},
+ "/debug/settings/pprof": {
+ "get": {
+ "description": "Retrieves the current settings for blocking and mutex profiles",
+ "tags": [
+ "private"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "schemes": [
+ "http"
+ ],
+ "operationId": "GetDebugSettingsProf",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/DebugSettingsProfResponse"
+ }
+ }
+ },
+ "put": {
+ "description": "Enables blocking and mutex profiles, and returns the old settings",
+ "tags": [
+ "private"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "schemes": [
+ "http"
+ ],
+ "operationId": "PutDebugSettingsProf",
+ "responses": {
+ "200": {
+ "$ref": "#/responses/DebugSettingsProfResponse"
+ }
+ }
+ }
+ },
"/v2/accounts/{address}": {
"get": {
"description": "Given a specific account public key, this call returns the accounts status, balance and spendable amounts",
@@ -4053,6 +4091,26 @@
}
}
},
+ "DebugSettingsProf": {
+ "description": "algod mutex and blocking profiling state.",
+ "type": "object",
+ "title": "algod mutex and blocking profiling state.",
+ "tags": [
+ "private"
+ ],
+ "properties": {
+ "block-rate": {
+ "description": "The rate of blocking events. The profiler aims to sample an average of one blocking event per rate nanoseconds spent blocked. To turn off profiling entirely, pass rate 0.",
+ "example": 1000,
+ "type": "integer"
+ },
+ "mutex-rate": {
+ "description": "The rate of mutex events. On average 1/rate events are reported. To turn off profiling entirely, pass rate 0",
+ "example": 1000,
+ "type": "integer"
+ }
+ }
+ },
"BuildVersion": {
"tags": [
"common"
@@ -5500,6 +5558,12 @@
"schema": {
"$ref": "#/definitions/Version"
}
+ },
+ "DebugSettingsProfResponse": {
+ "description": "DebugPprof is the response to the /debug/extra/pprof endpoint",
+ "schema": {
+ "$ref": "#/definitions/DebugSettingsProf"
+ }
}
},
"securityDefinitions": {
diff --git a/daemon/algod/api/algod.oas3.yml b/daemon/algod/api/algod.oas3.yml
index 734dc4667a..6737a95072 100644
--- a/daemon/algod/api/algod.oas3.yml
+++ b/daemon/algod/api/algod.oas3.yml
@@ -520,6 +520,16 @@
},
"description": "Teal compile Result"
},
+ "DebugSettingsProfResponse": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/DebugSettingsProf"
+ }
+ }
+ },
+ "description": "DebugPprof is the response to the /debug/extra/pprof endpoint"
+ },
"DisassembleResponse": {
"content": {
"application/json": {
@@ -1790,6 +1800,23 @@
"title": "BuildVersion contains the current algod build version information.",
"type": "object"
},
+ "DebugSettingsProf": {
+ "description": "algod mutex and blocking profiling state.",
+ "properties": {
+ "block-rate": {
+ "description": "The rate of blocking events. The profiler aims to sample an average of one blocking event per rate nanoseconds spent blocked. To turn off profiling entirely, pass rate 0.",
+ "example": 1000,
+ "type": "integer"
+ },
+ "mutex-rate": {
+ "description": "The rate of mutex events. On average 1/rate events are reported. To turn off profiling entirely, pass rate 0",
+ "example": 1000,
+ "type": "integer"
+ }
+ },
+ "title": "algod mutex and blocking profiling state.",
+ "type": "object"
+ },
"DryrunRequest": {
"description": "Request data type for dryrun endpoint. Given the Transactions and simulated ledger state upload, run TEAL scripts and return debugging information.",
"properties": {
@@ -2748,6 +2775,46 @@
},
"openapi": "3.0.1",
"paths": {
+ "/debug/settings/pprof": {
+ "get": {
+ "description": "Retrieves the current settings for blocking and mutex profiles",
+ "operationId": "GetDebugSettingsProf",
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/DebugSettingsProf"
+ }
+ }
+ },
+ "description": "DebugPprof is the response to the /debug/extra/pprof endpoint"
+ }
+ },
+ "tags": [
+ "private"
+ ]
+ },
+ "put": {
+ "description": "Enables blocking and mutex profiles, and returns the old settings",
+ "operationId": "PutDebugSettingsProf",
+ "responses": {
+ "200": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/DebugSettingsProf"
+ }
+ }
+ },
+ "description": "DebugPprof is the response to the /debug/extra/pprof endpoint"
+ }
+ },
+ "tags": [
+ "private"
+ ]
+ }
+ },
"/genesis": {
"get": {
"description": "Returns the entire genesis file in json.",
diff --git a/daemon/algod/api/server/common/handlers.go b/daemon/algod/api/server/common/handlers.go
index 308017e98b..c771e1443b 100644
--- a/daemon/algod/api/server/common/handlers.go
+++ b/daemon/algod/api/server/common/handlers.go
@@ -186,8 +186,6 @@ func VersionsHandler(ctx lib.ReqContext, context echo.Context) {
},
}
json.NewEncoder(w).Encode(response.Body)
-
- return
}
// CORS
diff --git a/daemon/algod/api/server/v2/dryrun.go b/daemon/algod/api/server/v2/dryrun.go
index 9c3355cd10..d3924eaf1d 100644
--- a/daemon/algod/api/server/v2/dryrun.go
+++ b/daemon/algod/api/server/v2/dryrun.go
@@ -308,6 +308,32 @@ func (dl *dryrunLedger) LookupWithoutRewards(rnd basics.Round, addr basics.Addre
return ledgercore.ToAccountData(ad), rnd, nil
}
+func (dl *dryrunLedger) LookupAgreement(rnd basics.Round, addr basics.Address) (basics.OnlineAccountData, error) {
+ // dryrun does not understand rewards, so we build the result without adding pending rewards.
+ // we also have no history, so we return current values
+ ad, _, err := dl.lookup(rnd, addr)
+ if err != nil || ad.Status != basics.Online {
+ return basics.OnlineAccountData{}, err
+ }
+ return basics.OnlineAccountData{
+ MicroAlgosWithRewards: ad.MicroAlgos,
+ VotingData: basics.VotingData{
+ VoteID: ad.VoteID,
+ SelectionID: ad.SelectionID,
+ StateProofID: ad.StateProofID,
+ VoteFirstValid: ad.VoteFirstValid,
+ VoteLastValid: ad.VoteLastValid,
+ VoteKeyDilution: ad.VoteKeyDilution,
+ },
+ IncentiveEligible: ad.IncentiveEligible,
+ }, nil
+}
+
+func (dl *dryrunLedger) OnlineCirculation(rnd basics.Round, voteRnd basics.Round) (basics.MicroAlgos, error) {
+ // dryrun doesn't support setting the global online stake, so we'll just return a constant
+ return basics.Algos(1_000_000_000), nil // 1B
+}
+
func (dl *dryrunLedger) LookupApplication(rnd basics.Round, addr basics.Address, aidx basics.AppIndex) (ledgercore.AppResource, error) {
ad, _, err := dl.lookup(rnd, addr)
if err != nil {
diff --git a/daemon/algod/api/server/v2/generated/data/routes.go b/daemon/algod/api/server/v2/generated/data/routes.go
index 7f5cfbeb7a..504ee50c69 100644
--- a/daemon/algod/api/server/v2/generated/data/routes.go
+++ b/daemon/algod/api/server/v2/generated/data/routes.go
@@ -114,221 +114,225 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "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",
- "y8xbNdpOULPHJw9nH/93AAAA//8Oc6QNuAMBAA==",
+ "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",
}
// GetSwagger returns the content of the embedded swagger specification file
diff --git a/daemon/algod/api/server/v2/generated/experimental/routes.go b/daemon/algod/api/server/v2/generated/experimental/routes.go
index e6472ca97a..f78cbd49a6 100644
--- a/daemon/algod/api/server/v2/generated/experimental/routes.go
+++ b/daemon/algod/api/server/v2/generated/experimental/routes.go
@@ -168,188 +168,192 @@ var swaggerSpec = []string{
"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",
- "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",
- "AwAA///pfgaenwQBAA==",
+ "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",
+ "j08ezj7+/wAAAP//hDzDXLsHAQA=",
}
// GetSwagger returns the content of the embedded swagger specification file
diff --git a/daemon/algod/api/server/v2/generated/model/types.go b/daemon/algod/api/server/v2/generated/model/types.go
index 1755e868ee..e2d32257ba 100644
--- a/daemon/algod/api/server/v2/generated/model/types.go
+++ b/daemon/algod/api/server/v2/generated/model/types.go
@@ -562,6 +562,15 @@ type BuildVersion struct {
Minor uint64 `json:"minor"`
}
+// DebugSettingsProf algod mutex and blocking profiling state.
+type DebugSettingsProf struct {
+ // BlockRate The rate of blocking events. The profiler aims to sample an average of one blocking event per rate nanoseconds spent blocked. To turn off profiling entirely, pass rate 0.
+ BlockRate *uint64 `json:"block-rate,omitempty"`
+
+ // MutexRate The rate of mutex events. On average 1/rate events are reported. To turn off profiling entirely, pass rate 0
+ MutexRate *uint64 `json:"mutex-rate,omitempty"`
+}
+
// DryrunRequest Request data type for dryrun endpoint. Given the Transactions and simulated ledger state upload, run TEAL scripts and return debugging information.
type DryrunRequest struct {
Accounts []Account `json:"accounts"`
@@ -1189,6 +1198,9 @@ type CompileResponse struct {
Sourcemap *map[string]interface{} `json:"sourcemap,omitempty"`
}
+// DebugSettingsProfResponse algod mutex and blocking profiling state.
+type DebugSettingsProfResponse = DebugSettingsProf
+
// DisassembleResponse defines model for DisassembleResponse.
type DisassembleResponse struct {
// Result disassembled Teal code
diff --git a/daemon/algod/api/server/v2/generated/nonparticipating/private/routes.go b/daemon/algod/api/server/v2/generated/nonparticipating/private/routes.go
index 568ebbb8ae..bf31180ecc 100644
--- a/daemon/algod/api/server/v2/generated/nonparticipating/private/routes.go
+++ b/daemon/algod/api/server/v2/generated/nonparticipating/private/routes.go
@@ -21,6 +21,12 @@ import (
// ServerInterface represents all server handlers.
type ServerInterface interface {
+
+ // (GET /debug/settings/pprof)
+ GetDebugSettingsProf(ctx echo.Context) error
+
+ // (PUT /debug/settings/pprof)
+ PutDebugSettingsProf(ctx echo.Context) error
// Aborts a catchpoint catchup.
// (DELETE /v2/catchup/{catchpoint})
AbortCatchup(ctx echo.Context, catchpoint string) error
@@ -37,6 +43,28 @@ type ServerInterfaceWrapper struct {
Handler ServerInterface
}
+// GetDebugSettingsProf converts echo context to params.
+func (w *ServerInterfaceWrapper) GetDebugSettingsProf(ctx echo.Context) error {
+ var err error
+
+ ctx.Set(Api_keyScopes, []string{""})
+
+ // Invoke the callback with all the unmarshalled arguments
+ err = w.Handler.GetDebugSettingsProf(ctx)
+ return err
+}
+
+// PutDebugSettingsProf converts echo context to params.
+func (w *ServerInterfaceWrapper) PutDebugSettingsProf(ctx echo.Context) error {
+ var err error
+
+ ctx.Set(Api_keyScopes, []string{""})
+
+ // Invoke the callback with all the unmarshalled arguments
+ err = w.Handler.PutDebugSettingsProf(ctx)
+ return err
+}
+
// AbortCatchup converts echo context to params.
func (w *ServerInterfaceWrapper) AbortCatchup(ctx echo.Context) error {
var err error
@@ -130,6 +158,8 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
Handler: si,
}
+ router.GET(baseURL+"/debug/settings/pprof", wrapper.GetDebugSettingsProf, m...)
+ router.PUT(baseURL+"/debug/settings/pprof", wrapper.PutDebugSettingsProf, m...)
router.DELETE(baseURL+"/v2/catchup/:catchpoint", wrapper.AbortCatchup, m...)
router.POST(baseURL+"/v2/catchup/:catchpoint", wrapper.StartCatchup, m...)
router.POST(baseURL+"/v2/shutdown", wrapper.ShutdownNode, m...)
@@ -139,224 +169,230 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "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",
- "NYXFJk9OHk0+/t8AAAD//5YZK+EHBgEA",
+ "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",
+ "h/8fAAD//3HzSP3DCwEA",
}
// GetSwagger returns the content of the embedded swagger specification file
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 815a346434..18ea670c4d 100644
--- a/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go
+++ b/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go
@@ -746,302 +746,306 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "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",
- "IGsT4ujB5N7ow/8LAAD//5pnmKfruQEA",
+ "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",
}
// GetSwagger returns the content of the embedded swagger specification file
diff --git a/daemon/algod/api/server/v2/generated/participating/private/routes.go b/daemon/algod/api/server/v2/generated/participating/private/routes.go
index d64047fe99..24f66d0cde 100644
--- a/daemon/algod/api/server/v2/generated/participating/private/routes.go
+++ b/daemon/algod/api/server/v2/generated/participating/private/routes.go
@@ -21,6 +21,12 @@ import (
// ServerInterface represents all server handlers.
type ServerInterface interface {
+
+ // (GET /debug/settings/pprof)
+ GetDebugSettingsProf(ctx echo.Context) error
+
+ // (PUT /debug/settings/pprof)
+ PutDebugSettingsProf(ctx echo.Context) error
// Return a list of participation keys
// (GET /v2/participation)
GetParticipationKeys(ctx echo.Context) error
@@ -46,6 +52,28 @@ type ServerInterfaceWrapper struct {
Handler ServerInterface
}
+// GetDebugSettingsProf converts echo context to params.
+func (w *ServerInterfaceWrapper) GetDebugSettingsProf(ctx echo.Context) error {
+ var err error
+
+ ctx.Set(Api_keyScopes, []string{""})
+
+ // Invoke the callback with all the unmarshalled arguments
+ err = w.Handler.GetDebugSettingsProf(ctx)
+ return err
+}
+
+// PutDebugSettingsProf converts echo context to params.
+func (w *ServerInterfaceWrapper) PutDebugSettingsProf(ctx echo.Context) error {
+ var err error
+
+ ctx.Set(Api_keyScopes, []string{""})
+
+ // Invoke the callback with all the unmarshalled arguments
+ err = w.Handler.PutDebugSettingsProf(ctx)
+ return err
+}
+
// GetParticipationKeys converts echo context to params.
func (w *ServerInterfaceWrapper) GetParticipationKeys(ctx echo.Context) error {
var err error
@@ -191,6 +219,8 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
Handler: si,
}
+ router.GET(baseURL+"/debug/settings/pprof", wrapper.GetDebugSettingsProf, m...)
+ router.PUT(baseURL+"/debug/settings/pprof", wrapper.PutDebugSettingsProf, m...)
router.GET(baseURL+"/v2/participation", wrapper.GetParticipationKeys, m...)
router.POST(baseURL+"/v2/participation", wrapper.AddParticipationKey, m...)
router.POST(baseURL+"/v2/participation/generate/:address", wrapper.GenerateParticipationKeys, m...)
@@ -203,227 +233,233 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "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",
+ "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",
}
// GetSwagger returns the content of the embedded swagger specification file
diff --git a/daemon/algod/api/server/v2/generated/participating/public/routes.go b/daemon/algod/api/server/v2/generated/participating/public/routes.go
index 409fd4ca65..4548badf2c 100644
--- a/daemon/algod/api/server/v2/generated/participating/public/routes.go
+++ b/daemon/algod/api/server/v2/generated/participating/public/routes.go
@@ -177,233 +177,237 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "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",
- "AAD//23D8FrbHAEA",
+ "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",
+ "8aePjk8nH/5/AAAA//9iOfQe9x8BAA==",
}
// 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 3d581dbd78..f338c38b1f 100644
--- a/daemon/algod/api/server/v2/handlers.go
+++ b/daemon/algod/api/server/v2/handlers.go
@@ -26,8 +26,10 @@ import (
"math"
"net/http"
"os"
+ "runtime"
"strconv"
"strings"
+ "sync/atomic"
"time"
"github.com/labstack/echo/v4"
@@ -2083,3 +2085,66 @@ func (v2 *Handlers) SetBlockTimeStampOffset(ctx echo.Context, offset uint64) err
}
return ctx.NoContent(http.StatusOK)
}
+
+// savedBlockingRate is the current blocking rate
+var savedBlockingRate atomic.Int32
+
+// GetDebugSettingsProf returns the current mutex and blocking rates.
+func (v2 *Handlers) GetDebugSettingsProf(ctx echo.Context) error {
+ mutexRate := uint64(runtime.SetMutexProfileFraction(-1))
+ blockingRate := uint64(savedBlockingRate.Load())
+
+ response := model.DebugSettingsProf{
+ MutexRate: &mutexRate,
+ BlockRate: &blockingRate,
+ }
+
+ return ctx.JSON(http.StatusOK, response)
+}
+
+// PutDebugSettingsProf sets the mutex and blocking rates and returns the old values.
+func (v2 *Handlers) PutDebugSettingsProf(ctx echo.Context) error {
+ req := ctx.Request()
+ buf := new(bytes.Buffer)
+ req.Body = http.MaxBytesReader(nil, req.Body, 128)
+ _, err := buf.ReadFrom(ctx.Request().Body)
+ if err != nil {
+ return badRequest(ctx, err, err.Error(), v2.Log)
+ }
+ data := buf.Bytes()
+
+ var opts model.DebugSettingsProf
+ err = decode(protocol.JSONStrictHandle, data, &opts)
+ if err != nil {
+ return badRequest(ctx, err, err.Error(), v2.Log)
+ }
+
+ var response model.DebugSettingsProf
+
+ // validate input fiest
+ if opts.MutexRate != nil && *opts.MutexRate > math.MaxInt32 {
+ err = errors.New("blocking rate cannot be larger than max int32 value")
+ return badRequest(ctx, err, err.Error(), v2.Log)
+ }
+ if opts.BlockRate != nil && *opts.BlockRate > math.MaxInt32 {
+ err = errors.New("blocking rate cannot be larger than max int32 value")
+ return badRequest(ctx, err, err.Error(), v2.Log)
+ }
+
+ if opts.MutexRate != nil {
+ newMutexRate := int(*opts.MutexRate)
+ oldMutexRate := uint64(runtime.SetMutexProfileFraction(newMutexRate))
+ response.MutexRate = &oldMutexRate
+ }
+
+ if opts.BlockRate != nil {
+ newBlockingRate := int(*opts.BlockRate)
+ runtime.SetBlockProfileRate(newBlockingRate)
+
+ oldBlockingRate := uint64(savedBlockingRate.Load())
+ response.BlockRate = &oldBlockingRate
+ savedBlockingRate.Store(int32(newBlockingRate))
+ }
+
+ return ctx.JSON(http.StatusOK, response)
+}
diff --git a/daemon/algod/api/server/v2/test/handlers_test.go b/daemon/algod/api/server/v2/test/handlers_test.go
index 53ef65256c..1952c88e7a 100644
--- a/daemon/algod/api/server/v2/test/handlers_test.go
+++ b/daemon/algod/api/server/v2/test/handlers_test.go
@@ -2439,3 +2439,66 @@ func TestGeneratePartkeys(t *testing.T) {
}
}
+
+func TestDebugExtraPprofEndpoint(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ submit := func(t *testing.T, method string, body []byte, expectedCode int) []byte {
+ handler := v2.Handlers{
+ Node: nil,
+ Log: logging.Base(),
+ }
+ e := echo.New()
+
+ var bodyReader io.Reader
+ if body != nil {
+ bodyReader = bytes.NewReader(body)
+ }
+
+ req := httptest.NewRequest(method, "/debug/extra/pprof", bodyReader)
+ rec := httptest.NewRecorder()
+ c := e.NewContext(req, rec)
+
+ if method == http.MethodPut {
+ handler.PutDebugSettingsProf(c)
+ } else {
+ handler.GetDebugSettingsProf(c)
+ }
+ require.Equal(t, expectedCode, rec.Code)
+
+ return rec.Body.Bytes()
+ }
+
+ // check original values
+ body := submit(t, http.MethodGet, nil, http.StatusOK)
+ require.Contains(t, string(body), `"mutex-rate":0`)
+ require.Contains(t, string(body), `"block-rate":0`)
+
+ // enable mutex and blocking profiling, should return the original zero values
+ body = submit(t, http.MethodPut, []byte(`{"mutex-rate":1000, "block-rate":2000}`), http.StatusOK)
+ require.Contains(t, string(body), `"mutex-rate":0`)
+ require.Contains(t, string(body), `"block-rate":0`)
+
+ // check the new values
+ body = submit(t, http.MethodGet, nil, http.StatusOK)
+ require.Contains(t, string(body), `"mutex-rate":1000`)
+ require.Contains(t, string(body), `"block-rate":2000`)
+
+ // set invalid values
+ body = submit(t, http.MethodPut, []byte(`{"mutex-rate":-1, "block-rate":2000}`), http.StatusBadRequest)
+ require.Contains(t, string(body), "failed to decode object")
+
+ body = submit(t, http.MethodPut, []byte(`{"mutex-rate":1000, "block-rate":-2}`), http.StatusBadRequest)
+ require.Contains(t, string(body), "failed to decode object")
+
+ // disable mutex and blocking profiling
+ body = submit(t, http.MethodPut, []byte(`{"mutex-rate":0, "block-rate":0}`), http.StatusOK)
+ require.Contains(t, string(body), `"mutex-rate":1000`)
+ require.Contains(t, string(body), `"block-rate":2000`)
+
+ // check it is disabled
+ body = submit(t, http.MethodGet, nil, http.StatusOK)
+ require.Contains(t, string(body), `"mutex-rate":0`)
+ require.Contains(t, string(body), `"block-rate":0`)
+
+}
diff --git a/data/transactions/logic/assembler_test.go b/data/transactions/logic/assembler_test.go
index ec5537a701..79b37186df 100644
--- a/data/transactions/logic/assembler_test.go
+++ b/data/transactions/logic/assembler_test.go
@@ -427,6 +427,11 @@ match_label1:
pushbytess "1" "2" "1"
`
+const incentiveNonsense = `
+online_stake
+voter_params_get VoterIncentiveEligible
+`
+
const stateProofNonsense = `
pushbytes 0x0123456789abcd
sumhash512
@@ -445,7 +450,7 @@ const spliceNonsence = `
const v10Nonsense = v9Nonsense + pairingNonsense + spliceNonsence
-const v11Nonsense = v10Nonsense + stateProofNonsense
+const v11Nonsense = v10Nonsense + incentiveNonsense + stateProofNonsense
const v6Compiled = "2004010002b7a60c26050242420c68656c6c6f20776f726c6421070123456789abcd208dae2087fbba51304eb02b91f656948397a7946390e8cb70fc9ea4d95f92251d047465737400320032013202320380021234292929292b0431003101310231043105310731083109310a310b310c310d310e310f3111311231133114311533000033000133000233000433000533000733000833000933000a33000b33000c33000d33000e33000f3300113300123300133300143300152d2e01022581f8acd19181cf959a1281f8acd19181cf951a81f8acd19181cf1581f8acd191810f082209240a220b230c240d250e230f2310231123122313231418191a1b1c28171615400003290349483403350222231d4a484848482b50512a632223524100034200004322602261222704634848222862482864286548482228246628226723286828692322700048482371004848361c0037001a0031183119311b311d311e311f312023221e312131223123312431253126312731283129312a312b312c312d312e312f447825225314225427042455220824564c4d4b0222382124391c0081e80780046a6f686e2281d00f23241f880003420001892224902291922494249593a0a1a2a3a4a5a6a7a8a9aaabacadae24af3a00003b003c003d816472064e014f012a57000823810858235b235a2359b03139330039b1b200b322c01a23c1001a2323c21a23c3233e233f8120af06002a494905002a49490700b400b53a03b6b7043cb8033a0c2349c42a9631007300810881088120978101c53a8101c6003a"
@@ -467,9 +472,11 @@ const spliceCompiled = "d2d3"
const v10Compiled = v9Compiled + pairingCompiled + spliceCompiled
+const incentiveCompiled = "757401"
+
const stateProofCompiled = "80070123456789abcd86494985"
-const V11Compiled = v10Compiled + stateProofCompiled
+const V11Compiled = v10Compiled + incentiveCompiled + stateProofCompiled
var nonsense = map[uint64]string{
1: v1Nonsense,
diff --git a/data/transactions/logic/crypto_test.go b/data/transactions/logic/crypto_test.go
index 5aad230289..0ba695dce5 100644
--- a/data/transactions/logic/crypto_test.go
+++ b/data/transactions/logic/crypto_test.go
@@ -606,8 +606,8 @@ ecdsa_verify Secp256r1
ri, si, err := ecdsa.Sign(rand.Reader, key, msg[:])
require.NoError(t, err)
- r := ri.Bytes()
- s := si.Bytes()
+ r := ri.FillBytes(make([]byte, 32))
+ s := si.FillBytes(make([]byte, 32))
rTampered := slices.Clone(r)
rTampered[0] += byte(1) // intentional overflow
@@ -826,8 +826,8 @@ func benchmarkEcdsaGenData(b *testing.B, curve EcdsaCurve) (data []benchmarkEcds
} else if curve == Secp256r1 {
r, s, err := ecdsa.Sign(rand.Reader, key, data[i].msg[:])
require.NoError(b, err)
- data[i].r = r.Bytes()
- data[i].s = s.Bytes()
+ data[i].r = r.FillBytes(make([]byte, 32))
+ data[i].s = s.FillBytes(make([]byte, 32))
}
}
return data
diff --git a/data/transactions/logic/doc.go b/data/transactions/logic/doc.go
index fde870a9d4..3bab156561 100644
--- a/data/transactions/logic/doc.go
+++ b/data/transactions/logic/doc.go
@@ -250,6 +250,8 @@ var opDescByName = map[string]OpDesc{
"asset_params_get": {"X is field F from asset A. Y is 1 if A exists, else 0", "params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.", []string{"asset params field index"}},
"app_params_get": {"X is field F from app A. Y is 1 if A exists, else 0", "params: Txn.ForeignApps offset or an _available_ app id. Return: did_exist flag (1 if the application existed and 0 otherwise), value.", []string{"app params field index"}},
"acct_params_get": {"X is field F from account A. Y is 1 if A owns positive algos, else 0", "", []string{"account params field index"}},
+ "voter_params_get": {"X is field F from online account A as of the balance round: 320 rounds before the current round. Y is 1 if A had positive algos online in the agreement round, else Y is 0 and X is a type specific zero-value", "", []string{"voter params field index"}},
+ "online_stake": {"the total online stake in the agreement round", "", nil},
"assert": {"immediately fail unless A is a non-zero number", "", nil},
"callsub": {"branch unconditionally to TARGET, saving the next instruction on the call stack", "The call stack is separate from the data stack. Only `callsub`, `retsub`, and `proto` manipulate it.", []string{"branch offset"}},
"proto": {"Prepare top call frame for a retsub that will assume A args and R return values.", "Fails unless the last instruction executed was a `callsub`.", []string{"number of arguments", "number of return values"}},
@@ -355,7 +357,7 @@ var OpGroups = map[string][]string{
"Cryptography": {"sha256", "keccak256", "sha512_256", "sha3_256", "sumhash512", "falcon_verify", "ed25519verify", "ed25519verify_bare", "ecdsa_verify", "ecdsa_pk_recover", "ecdsa_pk_decompress", "vrf_verify", "ec_add", "ec_scalar_mul", "ec_pairing_check", "ec_multi_scalar_mul", "ec_subgroup_check", "ec_map_to"},
"Loading Values": {"intcblock", "intc", "intc_0", "intc_1", "intc_2", "intc_3", "pushint", "pushints", "bytecblock", "bytec", "bytec_0", "bytec_1", "bytec_2", "bytec_3", "pushbytes", "pushbytess", "bzero", "arg", "arg_0", "arg_1", "arg_2", "arg_3", "args", "txn", "gtxn", "txna", "txnas", "gtxna", "gtxnas", "gtxns", "gtxnsa", "gtxnsas", "global", "load", "loads", "store", "stores", "gload", "gloads", "gloadss", "gaid", "gaids"},
"Flow Control": {"err", "bnz", "bz", "b", "return", "pop", "popn", "dup", "dup2", "dupn", "dig", "bury", "cover", "uncover", "frame_dig", "frame_bury", "swap", "select", "assert", "callsub", "proto", "retsub", "switch", "match"},
- "State Access": {"balance", "min_balance", "app_opted_in", "app_local_get", "app_local_get_ex", "app_global_get", "app_global_get_ex", "app_local_put", "app_global_put", "app_local_del", "app_global_del", "asset_holding_get", "asset_params_get", "app_params_get", "acct_params_get", "log", "block"},
+ "State Access": {"balance", "min_balance", "app_opted_in", "app_local_get", "app_local_get_ex", "app_global_get", "app_global_get_ex", "app_local_put", "app_global_put", "app_local_del", "app_global_del", "asset_holding_get", "asset_params_get", "app_params_get", "acct_params_get", "voter_params_get", "online_stake", "log", "block"},
"Box Access": {"box_create", "box_extract", "box_replace", "box_splice", "box_del", "box_len", "box_get", "box_put", "box_resize"},
"Inner Transactions": {"itxn_begin", "itxn_next", "itxn_field", "itxn_submit", "itxn", "itxna", "itxnas", "gitxn", "gitxna", "gitxnas"},
}
diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go
index 3008250a54..36ba3bb788 100644
--- a/data/transactions/logic/eval.go
+++ b/data/transactions/logic/eval.go
@@ -248,6 +248,11 @@ type LedgerForLogic interface {
Round() basics.Round
PrevTimestamp() int64
+ // These are simplifications of the underlying Ledger methods that take a
+ // round argument. They implicitly use agreement's BalanceRound (320 back).
+ AgreementData(addr basics.Address) (basics.OnlineAccountData, error)
+ OnlineStake() (basics.MicroAlgos, error)
+
AssetHolding(addr basics.Address, assetIdx basics.AssetIndex) (basics.AssetHolding, error)
AssetParams(aidx basics.AssetIndex) (basics.AssetParams, basics.Address, error)
AppParams(aidx basics.AppIndex) (basics.AppParams, basics.Address, error)
@@ -3736,7 +3741,7 @@ func (cx *EvalContext) globalFieldToValue(fs globalFieldSpec) (sv stackValue, er
return sv, fmt.Errorf("invalid global field %s", fs.field)
}
- if fs.ftype.AVMType != sv.avmType() {
+ if err == nil && fs.ftype.AVMType != sv.avmType() {
return sv, fmt.Errorf("%s expected field type is %s but got %s", fs.field, fs.ftype, sv.avmType())
}
@@ -5019,12 +5024,62 @@ func opAcctParamsGet(cx *EvalContext) error {
value.Uint = account.TotalBoxes
case AcctTotalBoxBytes:
value.Uint = account.TotalBoxBytes
+ case AcctIncentiveEligible:
+ value = boolToSV(account.IncentiveEligible)
+ case AcctLastHeartbeat:
+ value.Uint = uint64(account.LastHeartbeat)
+ case AcctLastProposed:
+ value.Uint = uint64(account.LastProposed)
+ default:
+ return fmt.Errorf("invalid account field %s", fs.field)
}
cx.Stack[last] = value
cx.Stack = append(cx.Stack, boolToSV(account.MicroAlgos.Raw > 0))
return nil
}
+func opVoterParamsGet(cx *EvalContext) error {
+ last := len(cx.Stack) - 1 // acct
+ addr, _, err := cx.accountReference(cx.Stack[last])
+ if err != nil {
+ return err
+ }
+
+ paramField := VoterParamsField(cx.program[cx.pc+1])
+ fs, ok := voterParamsFieldSpecByField(paramField)
+ if !ok || fs.version > cx.version {
+ return fmt.Errorf("invalid voter_params_get field %d", paramField)
+ }
+
+ account, err := cx.Ledger.AgreementData(addr)
+ if err != nil {
+ return err
+ }
+
+ var value stackValue
+
+ switch fs.field {
+ case VoterBalance:
+ value.Uint = account.MicroAlgosWithRewards.Raw
+ case VoterIncentiveEligible:
+ value = boolToSV(account.IncentiveEligible)
+ default:
+ return fmt.Errorf("invalid voter field %s", fs.field)
+ }
+ cx.Stack[last] = value
+ cx.Stack = append(cx.Stack, boolToSV(account.MicroAlgosWithRewards.Raw > 0))
+ return nil
+}
+
+func opOnlineStake(cx *EvalContext) error {
+ amount, err := cx.Ledger.OnlineStake()
+ if err != nil {
+ return err
+ }
+ cx.Stack = append(cx.Stack, stackValue{Uint: amount.Raw})
+ return nil
+}
+
func opLog(cx *EvalContext) error {
last := len(cx.Stack) - 1
diff --git a/data/transactions/logic/evalStateful_test.go b/data/transactions/logic/evalStateful_test.go
index 91ad91d1fe..abff0ddb83 100644
--- a/data/transactions/logic/evalStateful_test.go
+++ b/data/transactions/logic/evalStateful_test.go
@@ -348,6 +348,8 @@ log
"int 0; int 0; app_params_get AppApprovalProgram": 5,
"byte 0x01; log": 5,
sender + "acct_params_get AcctBalance": 7,
+ sender + "voter_params_get VoterBalance": 11,
+ "online_stake": 11,
"byte 0x1234; int 12; box_create": 8,
"byte 0x1234; int 12; int 4; box_extract": 8,
@@ -487,6 +489,9 @@ func testApp(t *testing.T, program string, ep *EvalParams, problems ...string) (
return testAppBytes(t, ops.Program, ep, problems...)
}
+// testAppCreator is the creator of the 888 app that is inserted when testing an app call
+const testAppCreator = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU"
+
func testAppBytes(t *testing.T, program []byte, ep *EvalParams, problems ...string) (transactions.EvalDelta, error) {
t.Helper()
if ep == nil {
@@ -497,6 +502,12 @@ func testAppBytes(t *testing.T, program []byte, ep *EvalParams, problems ...stri
aid := ep.TxnGroup[0].Txn.ApplicationID
if aid == 0 {
aid = basics.AppIndex(888)
+ // we're testing an app call without the caller specifying details about
+ // the app, so conjure up boring app params to make the `global
+ // AppCreator` work.
+ addr, err := basics.UnmarshalChecksumAddress(testAppCreator)
+ require.NoError(t, err)
+ ep.Ledger.(*Ledger).NewApp(addr, 888, basics.AppParams{})
}
return testAppFull(t, program, 0, aid, ep, problems...)
}
@@ -1598,6 +1609,49 @@ func TestAcctParams(t *testing.T) {
ledger.NewAsset(tx.Sender, 3000, basics.AssetParams{})
test("txn Sender; acct_params_get AcctTotalAssetsCreated; assert; int 1; ==")
test("txn Sender; acct_params_get AcctTotalAssets; assert; int 1; ==")
+
+ if ep.Proto.LogicSigVersion < 11 {
+ return // the rest uses fields that came at 11
+ }
+ test("txn Sender; acct_params_get AcctIncentiveEligible; assert; !")
+ test("txn Sender; acct_params_get AcctLastHeartbeat; assert; !")
+ test("txn Sender; acct_params_get AcctLastProposed; assert; !")
+ })
+}
+
+func TestVoterParams(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ // start at 11 for acct_params_get
+ testLogicRange(t, 11, 0, func(t *testing.T, ep *EvalParams, tx *transactions.Transaction, ledger *Ledger) {
+ test := func(source string) {
+ t.Helper()
+ testApp(t, source, ep)
+ }
+
+ test("txn Sender; voter_params_get VoterBalance; !; assert; int 0; ==")
+ test("txn Sender; voter_params_get VoterIncentiveEligible; !; assert; int 0; ==")
+
+ // The logic package test ledger just returns current values
+ ledger.NewAccount(tx.Sender, 42)
+ test("txn Sender; voter_params_get VoterBalance; assert; int 42; ==")
+ test("txn Sender; voter_params_get VoterIncentiveEligible; assert; !")
+ })
+}
+
+func TestOnlineStake(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ // start at 11 for online_stake
+ testLogicRange(t, 11, 0, func(t *testing.T, ep *EvalParams, tx *transactions.Transaction, ledger *Ledger) {
+ test := func(source string) {
+ t.Helper()
+ testApp(t, source, ep)
+ }
+
+ test("online_stake; int 3333000000; ==") // test ledger hard codes 3333 algos
})
}
diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go
index 3ede2c134b..3a81a9cbef 100644
--- a/data/transactions/logic/eval_test.go
+++ b/data/transactions/logic/eval_test.go
@@ -1160,8 +1160,6 @@ int 1
&&
`
-const testAddr = "47YPQTIGQEO7T4Y4RWDYWEKV6RTR2UNBQXBABEEGM72ESWDQNCQ52OPASU"
-
const globalV2TestProgram = globalV1TestProgram + `
global LogicSigVersion
int 1
@@ -1182,7 +1180,7 @@ int 888
`
const globalV3TestProgram = globalV2TestProgram + `
global CreatorAddress
-addr ` + testAddr + `
+addr ` + testAppCreator + `
==
&&
`
@@ -1239,10 +1237,10 @@ const globalV11TestProgram = globalV10TestProgram + `
// No new globals in v11
`
-func TestGlobal(t *testing.T) {
+func TestAllGlobals(t *testing.T) {
partitiontest.PartitionTest(t)
-
t.Parallel()
+
type desc struct {
lastField GlobalField
program string
@@ -1270,10 +1268,6 @@ func TestGlobal(t *testing.T) {
require.Equal(t, tests[AssemblerMaxVersion].lastField, invalidGlobalField-1,
"did you add a new global field?")
- ledger := NewLedger(nil)
- addr, err := basics.UnmarshalChecksumAddress(testAddr)
- require.NoError(t, err)
- ledger.NewApp(addr, 888, basics.AppParams{})
for v := uint64(1); v <= AssemblerMaxVersion; v++ {
_, ok := tests[v]
require.True(t, ok)
@@ -1294,7 +1288,6 @@ func TestGlobal(t *testing.T) {
appcall.Txn.Group = crypto.Digest{0x07, 0x06}
ep := defaultAppParams(appcall)
- ep.Ledger = ledger
testApp(t, tests[v].program, ep)
})
}
diff --git a/data/transactions/logic/fields.go b/data/transactions/logic/fields.go
index d0603d0ffc..367967089b 100644
--- a/data/transactions/logic/fields.go
+++ b/data/transactions/logic/fields.go
@@ -23,7 +23,7 @@ import (
"github.com/algorand/go-algorand/protocol"
)
-//go:generate stringer -type=TxnField,GlobalField,AssetParamsField,AppParamsField,AcctParamsField,AssetHoldingField,OnCompletionConstType,EcdsaCurve,EcGroup,Base64Encoding,JSONRefType,VrfStandard,BlockField -output=fields_string.go
+//go:generate stringer -type=TxnField,GlobalField,AssetParamsField,AppParamsField,AcctParamsField,AssetHoldingField,OnCompletionConstType,EcdsaCurve,EcGroup,Base64Encoding,JSONRefType,VoterParamsField,VrfStandard,BlockField -output=fields_string.go
// FieldSpec unifies the various specs for assembly, disassembly, and doc generation.
type FieldSpec interface {
@@ -1319,6 +1319,14 @@ const (
// AcctTotalBoxBytes is the number of bytes in all boxes of this app account
AcctTotalBoxBytes
+ // AcctIncentiveEligible is whether this account opted into block payouts by
+ // paying extra in `keyreg`. Does not reflect eligibility based on balance.
+ AcctIncentiveEligible
+ // AcctLastProposed is the last time this account proposed. Does not include _this_ round.
+ AcctLastProposed
+ // AcctLastHeartbeat is the last heartbeat from this account.
+ AcctLastHeartbeat
+
// AcctTotalAppSchema - consider how to expose
invalidAcctParamsField // compile-time constant for number of fields
@@ -1363,6 +1371,10 @@ var acctParamsFieldSpecs = [...]acctParamsFieldSpec{
{AcctTotalAssets, StackUint64, 8, "The numbers of ASAs held by this account (including ASAs this account created)."},
{AcctTotalBoxes, StackUint64, boxVersion, "The number of existing boxes created by this account's app."},
{AcctTotalBoxBytes, StackUint64, boxVersion, "The total number of bytes used by this account's app's box keys and values."},
+
+ {AcctIncentiveEligible, StackBoolean, incentiveVersion, "Has this account opted into block payouts"},
+ {AcctLastProposed, StackUint64, incentiveVersion, "The round number of the last block this account proposed."},
+ {AcctLastHeartbeat, StackUint64, incentiveVersion, "The round number of the last block this account sent a heartbeat."},
}
func acctParamsFieldSpecByField(f AcctParamsField) (acctParamsFieldSpec, bool) {
@@ -1388,6 +1400,78 @@ var AcctParamsFields = FieldGroup{
acctParamsFieldSpecByName,
}
+// VoterParamsField is an enum for `voter_params_get` opcode
+type VoterParamsField int
+
+const (
+ // VoterBalance is the balance, with pending rewards, from the balance
+ // round. It is 0 if the account was offline then.
+ VoterBalance VoterParamsField = iota
+
+ // expose voter keys?
+
+ // VoterIncentiveEligible is whether this account opted into block payouts
+ // by paying extra in `keyreg`. Does not reflect eligibility based on
+ // balance. The value is returned for the balance round and is _false_ if
+ // the account was offline then.
+ VoterIncentiveEligible
+
+ invalidVoterParamsField // compile-time constant for number of fields
+)
+
+var voterParamsFieldNames [invalidVoterParamsField]string
+
+type voterParamsFieldSpec struct {
+ field VoterParamsField
+ ftype StackType
+ version uint64
+ doc string
+}
+
+func (fs voterParamsFieldSpec) Field() byte {
+ return byte(fs.field)
+}
+func (fs voterParamsFieldSpec) Type() StackType {
+ return fs.ftype
+}
+func (fs voterParamsFieldSpec) OpVersion() uint64 {
+ return incentiveVersion
+}
+func (fs voterParamsFieldSpec) Version() uint64 {
+ return fs.version
+}
+func (fs voterParamsFieldSpec) Note() string {
+ return fs.doc
+}
+
+var voterParamsFieldSpecs = [...]voterParamsFieldSpec{
+ {VoterBalance, StackUint64, 6, "Online stake in microalgos"},
+ {VoterIncentiveEligible, StackBoolean, incentiveVersion, "Had this account opted into block payouts"},
+}
+
+func voterParamsFieldSpecByField(f VoterParamsField) (voterParamsFieldSpec, bool) {
+ if int(f) >= len(voterParamsFieldSpecs) {
+ return voterParamsFieldSpec{}, false
+ }
+ return voterParamsFieldSpecs[f], true
+}
+
+var voterParamsFieldSpecByName = make(voterNameSpecMap, len(voterParamsFieldNames))
+
+type voterNameSpecMap map[string]voterParamsFieldSpec
+
+func (s voterNameSpecMap) get(name string) (FieldSpec, bool) {
+ fs, ok := s[name]
+ return fs, ok
+}
+
+// VoterParamsFields describes voter_params_get's immediates
+var VoterParamsFields = FieldGroup{
+ "voter_params", "Fields",
+ voterParamsFieldNames[:],
+ voterParamsFieldSpecByName,
+}
+
func init() {
equal := func(x int, y int) {
if x != y {
@@ -1479,6 +1563,13 @@ func init() {
acctParamsFieldSpecByName[s.field.String()] = s
}
+ equal(len(voterParamsFieldSpecs), len(voterParamsFieldNames))
+ for i, s := range voterParamsFieldSpecs {
+ equal(int(s.field), i)
+ voterParamsFieldNames[i] = s.field.String()
+ voterParamsFieldSpecByName[s.field.String()] = s
+ }
+
txnTypeMap = make(map[string]uint64)
for i, tt := range TxnTypeNames {
txnTypeMap[tt] = uint64(i)
diff --git a/data/transactions/logic/fields_string.go b/data/transactions/logic/fields_string.go
index 5b92357909..d925e69ee1 100644
--- a/data/transactions/logic/fields_string.go
+++ b/data/transactions/logic/fields_string.go
@@ -1,4 +1,4 @@
-// Code generated by "stringer -type=TxnField,GlobalField,AssetParamsField,AppParamsField,AcctParamsField,AssetHoldingField,OnCompletionConstType,EcdsaCurve,EcGroup,Base64Encoding,JSONRefType,VrfStandard,BlockField -output=fields_string.go"; DO NOT EDIT.
+// Code generated by "stringer -type=TxnField,GlobalField,AssetParamsField,AppParamsField,AcctParamsField,AssetHoldingField,OnCompletionConstType,EcdsaCurve,EcGroup,Base64Encoding,JSONRefType,VoterParamsField,VrfStandard,BlockField -output=fields_string.go"; DO NOT EDIT.
package logic
@@ -195,12 +195,15 @@ func _() {
_ = x[AcctTotalAssets-9]
_ = x[AcctTotalBoxes-10]
_ = x[AcctTotalBoxBytes-11]
- _ = x[invalidAcctParamsField-12]
+ _ = x[AcctIncentiveEligible-12]
+ _ = x[AcctLastProposed-13]
+ _ = x[AcctLastHeartbeat-14]
+ _ = x[invalidAcctParamsField-15]
}
-const _AcctParamsField_name = "AcctBalanceAcctMinBalanceAcctAuthAddrAcctTotalNumUintAcctTotalNumByteSliceAcctTotalExtraAppPagesAcctTotalAppsCreatedAcctTotalAppsOptedInAcctTotalAssetsCreatedAcctTotalAssetsAcctTotalBoxesAcctTotalBoxBytesinvalidAcctParamsField"
+const _AcctParamsField_name = "AcctBalanceAcctMinBalanceAcctAuthAddrAcctTotalNumUintAcctTotalNumByteSliceAcctTotalExtraAppPagesAcctTotalAppsCreatedAcctTotalAppsOptedInAcctTotalAssetsCreatedAcctTotalAssetsAcctTotalBoxesAcctTotalBoxBytesAcctIncentiveEligibleAcctLastProposedAcctLastHeartbeatinvalidAcctParamsField"
-var _AcctParamsField_index = [...]uint8{0, 11, 25, 37, 53, 74, 96, 116, 136, 158, 173, 187, 204, 226}
+var _AcctParamsField_index = [...]uint16{0, 11, 25, 37, 53, 74, 96, 116, 136, 158, 173, 187, 204, 225, 241, 258, 280}
func (i AcctParamsField) String() string {
if i < 0 || i >= AcctParamsField(len(_AcctParamsField_index)-1) {
@@ -328,6 +331,25 @@ func (i JSONRefType) String() string {
}
return _JSONRefType_name[_JSONRefType_index[i]:_JSONRefType_index[i+1]]
}
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[VoterBalance-0]
+ _ = x[VoterIncentiveEligible-1]
+ _ = x[invalidVoterParamsField-2]
+}
+
+const _VoterParamsField_name = "VoterBalanceVoterIncentiveEligibleinvalidVoterParamsField"
+
+var _VoterParamsField_index = [...]uint8{0, 12, 34, 57}
+
+func (i VoterParamsField) String() string {
+ if i < 0 || i >= VoterParamsField(len(_VoterParamsField_index)-1) {
+ return "VoterParamsField(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _VoterParamsField_name[_VoterParamsField_index[i]:_VoterParamsField_index[i+1]]
+}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
diff --git a/data/transactions/logic/fields_test.go b/data/transactions/logic/fields_test.go
index 7cec0b936f..ab2548c306 100644
--- a/data/transactions/logic/fields_test.go
+++ b/data/transactions/logic/fields_test.go
@@ -29,7 +29,8 @@ import (
// ensure v2+ fields fail in TEAL assembler and evaluator on a version before they introduced
// ensure v2+ fields error in v1 program
-func TestGlobalFieldsVersions(t *testing.T) {
+// ensure the types of the returned values are correct
+func TestGlobalVersionsAndTypes(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
@@ -42,7 +43,7 @@ func TestGlobalFieldsVersions(t *testing.T) {
require.Greater(t, len(fields), 1)
for _, field := range fields {
- text := fmt.Sprintf("global %s", field.field.String())
+ text := "global " + field.field.String()
// check assembler fails if version before introduction
testLine(t, text, assemblerNoVersion, "...was introduced in...")
for v := uint64(0); v < field.version; v++ {
@@ -50,6 +51,32 @@ func TestGlobalFieldsVersions(t *testing.T) {
}
testLine(t, text, field.version, "")
+ // tack on a type check, and return a value (`int` gets compiled
+ // differently in different versions, so use intc_0 explicitly
+ switch field.ftype.AVMType {
+ case avmUint64: // ensure the return type is uint64 by using !
+ text = "intcblock 1;" + text + "; !; pop; intc_0"
+ case avmBytes: // ensure the return type is bytes by using len
+ text = "intcblock 1;" + text + "; len; pop; intc_0"
+ case avmAny:
+ text = "intcblock 1;" + text + "; pop; intc_0"
+ }
+
+ // check success in AssemblerMaxVersion and fs.version
+ for _, ver := range []uint64{AssemblerMaxVersion, field.version} {
+ ops := testProg(t, text, ver)
+ switch field.mode {
+ case ModeSig:
+ testLogicBytes(t, ops.Program, defaultSigParamsWithVersion(ver))
+ case ModeApp:
+ testAppBytes(t, ops.Program, defaultAppParamsWithVersion(ver))
+ case modeAny:
+ testLogicBytes(t, ops.Program, defaultSigParamsWithVersion(ver))
+ testAppBytes(t, ops.Program, defaultAppParamsWithVersion(ver))
+ default:
+ t.Fail()
+ }
+ }
ops := testProg(t, text, AssemblerMaxVersion)
// check on a version before the field version
diff --git a/data/transactions/logic/ledger_test.go b/data/transactions/logic/ledger_test.go
index 0254a44678..3dcead5e51 100644
--- a/data/transactions/logic/ledger_test.go
+++ b/data/transactions/logic/ledger_test.go
@@ -216,6 +216,12 @@ func (l *Ledger) PrevTimestamp() int64 {
return int64(rand.Uint32() + 1)
}
+// OnlineStake returns the online stake that applies to the latest round (so
+// it's actually the online stake from 320 rounds ago)
+func (l *Ledger) OnlineStake() (basics.MicroAlgos, error) {
+ return basics.Algos(3333), nil
+}
+
// 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{}
@@ -310,6 +316,31 @@ func (l *Ledger) AccountData(addr basics.Address) (ledgercore.AccountData, error
}, nil
}
+// AgreementData is not a very high-fidelity fake. There's no time delay, it
+// just returns the data that's in AccountData, reshaped into an
+// OnlineAccountData.
+func (l *Ledger) AgreementData(addr basics.Address) (basics.OnlineAccountData, error) {
+ ad, err := l.AccountData(addr)
+ if err != nil {
+ return basics.OnlineAccountData{}, err
+ }
+ // You might imagine this conversion function exists. It does, but requires
+ // rewards handling because OnlineAccountData should have rewards
+ // paid. Here, we ignore that for simple tests.
+ return basics.OnlineAccountData{
+ MicroAlgosWithRewards: ad.MicroAlgos,
+ VotingData: basics.VotingData{
+ VoteID: ad.VoteID,
+ SelectionID: ad.SelectionID,
+ StateProofID: ad.StateProofID,
+ VoteFirstValid: ad.VoteFirstValid,
+ VoteLastValid: ad.VoteLastValid,
+ VoteKeyDilution: ad.VoteKeyDilution,
+ },
+ IncentiveEligible: ad.IncentiveEligible,
+ }, nil
+}
+
// Authorizer returns the address that must authorize txns from a
// given address. It's either the address itself, or the value it has
// been rekeyed to.
diff --git a/data/transactions/logic/opcodes.go b/data/transactions/logic/opcodes.go
index bb5992ae44..f3f8bfe37d 100644
--- a/data/transactions/logic/opcodes.go
+++ b/data/transactions/logic/opcodes.go
@@ -641,6 +641,8 @@ var OpSpecs = []OpSpec{
{0x71, "asset_params_get", opAssetParamsGet, proto("i:aT"), 2, field("f", &AssetParamsFields).only(ModeApp)},
{0x72, "app_params_get", opAppParamsGet, proto("i:aT"), 5, field("f", &AppParamsFields).only(ModeApp)},
{0x73, "acct_params_get", opAcctParamsGet, proto("a:aT"), 6, field("f", &AcctParamsFields).only(ModeApp)},
+ {0x74, "voter_params_get", opVoterParamsGet, proto("a:aT"), incentiveVersion, field("f", &VoterParamsFields).only(ModeApp)},
+ {0x75, "online_stake", opOnlineStake, proto(":i"), incentiveVersion, only(ModeApp)},
{0x78, "min_balance", opMinBalance, proto("i:i"), 3, only(ModeApp)},
{0x78, "min_balance", opMinBalance, proto("a:i"), directRefEnabledVersion, only(ModeApp)},
diff --git a/data/transactions/logic/teal.tmLanguage.json b/data/transactions/logic/teal.tmLanguage.json
index 915957f7f0..53984e8dd2 100644
--- a/data/transactions/logic/teal.tmLanguage.json
+++ b/data/transactions/logic/teal.tmLanguage.json
@@ -72,7 +72,7 @@
},
{
"name": "keyword.other.unit.teal",
- "match": "^(box_create|box_del|box_extract|box_get|box_len|box_put|box_replace|box_resize|box_splice|acct_params_get|app_global_del|app_global_get|app_global_get_ex|app_global_put|app_local_del|app_local_get|app_local_get_ex|app_local_put|app_opted_in|app_params_get|asset_holding_get|asset_params_get|balance|block|log|min_balance)\\b"
+ "match": "^(box_create|box_del|box_extract|box_get|box_len|box_put|box_replace|box_resize|box_splice|acct_params_get|app_global_del|app_global_get|app_global_get_ex|app_global_put|app_local_del|app_local_get|app_local_get_ex|app_local_put|app_opted_in|app_params_get|asset_holding_get|asset_params_get|balance|block|log|min_balance|online_stake|voter_params_get)\\b"
},
{
"name": "keyword.operator.teal",
diff --git a/data/txHandler.go b/data/txHandler.go
index 3d20e95acd..7851889378 100644
--- a/data/txHandler.go
+++ b/data/txHandler.go
@@ -599,6 +599,18 @@ func (handler *TxHandler) processIncomingTxn(rawmsg network.IncomingMessage) net
var err error
var capguard *util.ErlCapacityGuard
+ accepted := false
+ defer func() {
+ // if we failed to put the item onto the backlog, we should release the capacity if any
+ if !accepted {
+ if capguard != nil {
+ if capErr := capguard.Release(); capErr != nil {
+ logging.Base().Warnf("Failed to release capacity to ElasticRateLimiter: %v", capErr)
+ }
+ }
+ }
+ }()
+
if handler.erl != nil {
congestedERL := float64(cap(handler.backlogQueue))*handler.backlogCongestionThreshold < float64(len(handler.backlogQueue))
// consume a capacity unit
@@ -679,6 +691,7 @@ func (handler *TxHandler) processIncomingTxn(rawmsg network.IncomingMessage) net
unverifiedTxGroupHash: canonicalKey,
capguard: capguard,
}:
+ accepted = true
default:
// if we failed here we want to increase the corresponding metric. It might suggest that we
// want to increase the queue size.
diff --git a/data/txHandler_test.go b/data/txHandler_test.go
index 5eb40741ee..896fbb161d 100644
--- a/data/txHandler_test.go
+++ b/data/txHandler_test.go
@@ -28,6 +28,7 @@ import (
"runtime/pprof"
"strings"
"sync"
+ "sync/atomic"
"testing"
"time"
@@ -794,7 +795,7 @@ func TestTxHandlerProcessIncomingCensoring(t *testing.T) {
// makeTestTxHandlerOrphaned creates a tx handler without any backlog consumer.
// It is caller responsibility to run a consumer thread.
func makeTestTxHandlerOrphaned(backlogSize int) *TxHandler {
- return makeTestTxHandlerOrphanedWithContext(context.Background(), txBacklogSize, txBacklogSize, txHandlerConfig{true, false}, 0)
+ return makeTestTxHandlerOrphanedWithContext(context.Background(), backlogSize, backlogSize, txHandlerConfig{true, false}, 0)
}
func makeTestTxHandlerOrphanedWithContext(ctx context.Context, backlogSize int, cacheSize int, txHandlerConfig txHandlerConfig, refreshInterval time.Duration) *TxHandler {
@@ -2681,3 +2682,65 @@ func TestTxHandlerAppRateLimiter(t *testing.T) {
msg := <-handler.backlogQueue
require.Equal(t, msg.rawmsg.Data, blob, blob)
}
+
+// TestTxHandlerCapGuard checks there is no cap guard leak in case of invalid input.
+func TestTxHandlerCapGuard(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ const numUsers = 10
+ addresses, secrets, genesis := makeTestGenesisAccounts(t, numUsers)
+ genBal := bookkeeping.MakeGenesisBalances(genesis, sinkAddr, poolAddr)
+ ledgerName := fmt.Sprintf("%s-mem", t.Name())
+ const inMem = true
+ log := logging.TestingLog(t)
+ log.SetLevel(logging.Error)
+
+ cfg := config.GetDefaultLocal()
+ cfg.EnableTxBacklogRateLimiting = true
+ cfg.EnableTxBacklogAppRateLimiting = false
+ cfg.TxIncomingFilteringFlags = 0
+ cfg.TxBacklogServiceRateWindowSeconds = 1
+ cfg.TxBacklogReservedCapacityPerPeer = 1
+ cfg.IncomingConnectionsLimit = 1
+ cfg.TxBacklogSize = 3
+
+ ledger, err := LoadLedger(log, ledgerName, inMem, protocol.ConsensusCurrentVersion, genBal, genesisID, genesisHash, nil, cfg)
+ require.NoError(t, err)
+ defer ledger.Close()
+
+ handler, err := makeTestTxHandler(ledger, cfg)
+ require.NoError(t, err)
+ defer handler.txVerificationPool.Shutdown()
+ defer close(handler.streamVerifierDropped)
+
+ tx := transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: addresses[0],
+ Fee: basics.MicroAlgos{Raw: proto.MinTxnFee * 2},
+ FirstValid: 0,
+ LastValid: basics.Round(proto.MaxTxnLife),
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: addresses[1],
+ Amount: basics.MicroAlgos{Raw: 1000},
+ },
+ }
+
+ signedTx := tx.Sign(secrets[0])
+ blob := protocol.Encode(&signedTx)
+ blob[0]++ // make it invalid
+
+ var completed atomic.Bool
+ go func() {
+ for i := 0; i < 10; i++ {
+ outgoing := handler.processIncomingTxn(network.IncomingMessage{Data: blob, Sender: mockSender{}})
+ require.Equal(t, network.OutgoingMessage{Action: network.Disconnect}, outgoing)
+ require.Equal(t, 0, len(handler.backlogQueue))
+ }
+ completed.Store(true)
+ }()
+
+ require.Eventually(t, func() bool { return completed.Load() }, 1*time.Second, 10*time.Millisecond)
+}
diff --git a/go.mod b/go.mod
index c15195b54b..a32da9da8c 100644
--- a/go.mod
+++ b/go.mod
@@ -42,10 +42,10 @@ require (
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.5.0
github.com/stretchr/testify v1.8.4
- golang.org/x/crypto v0.19.0
+ golang.org/x/crypto v0.21.0
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
golang.org/x/sync v0.6.0
- golang.org/x/sys v0.17.0
+ golang.org/x/sys v0.18.0
golang.org/x/text v0.14.0
gopkg.in/sohlich/elogrus.v3 v3.0.0-20180410122755-1fa29e2f2009
pgregory.net/rapid v0.6.2
@@ -151,8 +151,8 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/mod v0.15.0 // indirect
- golang.org/x/net v0.21.0 // indirect
- golang.org/x/term v0.17.0 // indirect
+ golang.org/x/net v0.23.0 // indirect
+ golang.org/x/term v0.18.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.18.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
diff --git a/go.sum b/go.sum
index badf55816d..cdae303d5b 100644
--- a/go.sum
+++ b/go.sum
@@ -591,8 +591,8 @@ golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
-golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
+golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
+golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
@@ -632,8 +632,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
-golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
+golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -683,11 +683,11 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
-golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
+golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
-golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
+golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
+golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
diff --git a/ledger/acctonline.go b/ledger/acctonline.go
index 667255fb51..0db04e92ad 100644
--- a/ledger/acctonline.go
+++ b/ledger/acctonline.go
@@ -118,6 +118,9 @@ type onlineAccounts struct {
// disableCache (de)activates the LRU cache use in onlineAccounts
disableCache bool
+
+ // cache for expired online circulation stake since the underlying query is quite heavy
+ expiredCirculationCache *expiredCirculationCache
}
// initialize initializes the accountUpdates structure
@@ -125,6 +128,9 @@ func (ao *onlineAccounts) initialize(cfg config.Local) {
ao.accountsReadCond = sync.NewCond(ao.accountsMu.RLocker())
ao.acctLookback = cfg.MaxAcctLookback
ao.disableCache = cfg.DisableLedgerLRUCache
+ // 2 pages * 256 entries look large enough to handle
+ // both early and late votes, and well as a current and previous stateproof periods
+ ao.expiredCirculationCache = makeExpiredCirculationCache(256)
}
// loadFromDisk is the 2nd level initialization, and is required before the onlineAccounts becomes functional
@@ -549,7 +555,7 @@ func (ao *onlineAccounts) onlineCirculation(rnd basics.Round, voteRnd basics.Rou
if rnd == 0 {
return totalStake, nil
}
- expiredStake, err := ao.ExpiredOnlineCirculation(rnd, voteRnd)
+ expiredStake, err := ao.expiredOnlineCirculation(rnd, voteRnd)
if err != nil {
return basics.MicroAlgos{}, err
}
@@ -874,7 +880,7 @@ func (ao *onlineAccounts) TopOnlineAccounts(rnd basics.Round, voteRnd basics.Rou
for uint64(len(candidates)) < n+uint64(len(modifiedAccounts)) {
var accts map[basics.Address]*ledgercore.OnlineAccount
start := time.Now()
- ledgerAccountsonlinetopCount.Inc(nil)
+ ledgerAccountsOnlineTopCount.Inc(nil)
err = ao.dbs.Snapshot(func(ctx context.Context, tx trackerdb.SnapshotScope) (err error) {
ar, err := tx.MakeAccountsReader()
if err != nil {
@@ -888,7 +894,7 @@ func (ao *onlineAccounts) TopOnlineAccounts(rnd basics.Round, voteRnd basics.Rou
dbRound, err = ar.AccountsRound()
return
})
- ledgerAccountsonlinetopMicros.AddMicrosecondsSince(start, nil)
+ ledgerAccountsOnlineTopMicros.AddMicrosecondsSince(start, nil)
if err != nil {
return nil, basics.MicroAlgos{}, err
}
@@ -965,7 +971,7 @@ func (ao *onlineAccounts) TopOnlineAccounts(rnd basics.Round, voteRnd basics.Rou
// If set, return total online stake minus all future expired stake by voteRnd
if params.ExcludeExpiredCirculation {
- expiredStake, err := ao.ExpiredOnlineCirculation(rnd, voteRnd)
+ expiredStake, err := ao.expiredOnlineCirculation(rnd, voteRnd)
if err != nil {
return nil, basics.MicroAlgos{}, err
}
@@ -1027,6 +1033,9 @@ func (ao *onlineAccounts) onlineAcctsExpiredByRound(rnd, voteRnd basics.Round) (
rewardsParams := config.Consensus[roundParams.CurrentProtocol]
rewardsLevel := roundParams.RewardsLevel
+ start := time.Now()
+ ledgerAccountExpiredByRoundCount.Inc(nil)
+
// Step 1: get all online accounts from DB for rnd
// Not unlocking ao.accountsMu yet, to stay consistent with Step 2
var dbRound basics.Round
@@ -1042,6 +1051,7 @@ func (ao *onlineAccounts) onlineAcctsExpiredByRound(rnd, voteRnd basics.Round) (
dbRound, err = ar.AccountsRound()
return err
})
+ ledgerAccountsExpiredByRoundMicros.AddMicrosecondsSince(start, nil)
if err != nil {
return nil, err
}
@@ -1086,9 +1096,13 @@ func (ao *onlineAccounts) onlineAcctsExpiredByRound(rnd, voteRnd basics.Round) (
return expiredAccounts, nil
}
-// ExpiredOnlineCirculation returns the total online stake for accounts with participation keys registered
+// expiredOnlineCirculation returns the total online stake for accounts with participation keys registered
// at round `rnd` that are expired by round `voteRnd`.
-func (ao *onlineAccounts) ExpiredOnlineCirculation(rnd, voteRnd basics.Round) (basics.MicroAlgos, error) {
+func (ao *onlineAccounts) expiredOnlineCirculation(rnd, voteRnd basics.Round) (basics.MicroAlgos, error) {
+ if expiredStake, ok := ao.expiredCirculationCache.get(rnd, voteRnd); ok {
+ return expiredStake, nil
+ }
+
expiredAccounts, err := ao.onlineAcctsExpiredByRound(rnd, voteRnd)
if err != nil {
return basics.MicroAlgos{}, err
@@ -1101,8 +1115,11 @@ func (ao *onlineAccounts) ExpiredOnlineCirculation(rnd, voteRnd basics.Round) (b
return basics.MicroAlgos{}, fmt.Errorf("ExpiredOnlineCirculation: overflow totaling expired stake")
}
}
+ ao.expiredCirculationCache.put(rnd, voteRnd, expiredStake)
return expiredStake, nil
}
-var ledgerAccountsonlinetopCount = metrics.NewCounter("ledger_accountsonlinetop_count", "calls")
-var ledgerAccountsonlinetopMicros = metrics.NewCounter("ledger_accountsonlinetop_micros", "µs spent")
+var ledgerAccountsOnlineTopCount = metrics.NewCounter("ledger_accountsonlinetop_count", "calls")
+var ledgerAccountsOnlineTopMicros = metrics.NewCounter("ledger_accountsonlinetop_micros", "µs spent")
+var ledgerAccountExpiredByRoundCount = metrics.NewCounter("ledger_accountsexpired_count", "calls")
+var ledgerAccountsExpiredByRoundMicros = metrics.NewCounter("ledger_accountsexpired_micros", "µs spent")
diff --git a/ledger/acctonline_expired_test.go b/ledger/acctonline_expired_test.go
index e51494d184..25bfe3b11b 100644
--- a/ledger/acctonline_expired_test.go
+++ b/ledger/acctonline_expired_test.go
@@ -49,7 +49,7 @@ type onlineAcctModel interface {
LookupAgreement(rnd basics.Round, addr basics.Address) onlineAcctModelAcct
OnlineCirculation(rnd basics.Round, voteRnd basics.Round) basics.MicroAlgos
- ExpiredOnlineCirculation(rnd, voteRnd basics.Round) basics.MicroAlgos
+ expiredOnlineCirculation(rnd, voteRnd basics.Round) basics.MicroAlgos
}
// mapOnlineAcctModel provides a reference implementation for tracking online accounts used
@@ -133,7 +133,7 @@ func (m *mapOnlineAcctModel) OnlineCirculation(rnd basics.Round, voteRnd basics.
return m.sumAcctStake(accts)
}
-func (m *mapOnlineAcctModel) ExpiredOnlineCirculation(rnd, voteRnd basics.Round) basics.MicroAlgos {
+func (m *mapOnlineAcctModel) expiredOnlineCirculation(rnd, voteRnd basics.Round) basics.MicroAlgos {
accts := m.onlineAcctsExpiredByRound(rnd, voteRnd)
return m.sumAcctStake(accts)
}
@@ -385,7 +385,7 @@ func (m *doubleLedgerAcctModel) OnlineCirculation(rnd basics.Round, voteRnd basi
// has already subtracted the expired stake. So to get the total, add
// it back in by querying ExpiredOnlineCirculation.
if m.params.ExcludeExpiredCirculation {
- expiredStake := m.ExpiredOnlineCirculation(rnd, rnd+320)
+ expiredStake := m.expiredOnlineCirculation(rnd, rnd+320)
valStake = m.ops.Add(valStake, expiredStake)
}
@@ -404,20 +404,26 @@ func (l *Ledger) OnlineTotalStake(rnd basics.Round) (basics.MicroAlgos, error) {
return totalStake, err
}
-// ExpiredOnlineCirculation is a wrapper to call onlineAccounts.ExpiredOnlineCirculation safely.
-func (l *Ledger) ExpiredOnlineCirculation(rnd, voteRnd basics.Round) (basics.MicroAlgos, error) {
+// expiredOnlineCirculation is a wrapper to call onlineAccounts.expiredOnlineCirculation safely.
+func (l *Ledger) expiredOnlineCirculation(rnd, voteRnd basics.Round) (basics.MicroAlgos, error) {
l.trackerMu.RLock()
defer l.trackerMu.RUnlock()
- return l.acctsOnline.ExpiredOnlineCirculation(rnd, voteRnd)
+ return l.acctsOnline.expiredOnlineCirculation(rnd, voteRnd)
}
-// ExpiredOnlineCirculation returns the total expired stake at rnd this model produced, while
+// expiredOnlineCirculation returns the total expired stake at rnd this model produced, while
// also asserting that the validator and generator Ledgers both agree.
-func (m *doubleLedgerAcctModel) ExpiredOnlineCirculation(rnd, voteRnd basics.Round) basics.MicroAlgos {
- valStake, err := m.dl.validator.ExpiredOnlineCirculation(rnd, voteRnd)
+func (m *doubleLedgerAcctModel) expiredOnlineCirculation(rnd, voteRnd basics.Round) basics.MicroAlgos {
+ valStake, err := m.dl.validator.expiredOnlineCirculation(rnd, voteRnd)
require.NoError(m.t, err)
- genStake, err := m.dl.generator.ExpiredOnlineCirculation(rnd, voteRnd)
+ valCachedStake, has := m.dl.validator.acctsOnline.expiredCirculationCache.get(rnd, voteRnd)
+ require.True(m.t, has)
+ require.Equal(m.t, valStake, valCachedStake)
+ genStake, err := m.dl.generator.expiredOnlineCirculation(rnd, voteRnd)
require.NoError(m.t, err)
+ genCachedStake, has := m.dl.generator.acctsOnline.expiredCirculationCache.get(rnd, voteRnd)
+ require.True(m.t, has)
+ require.Equal(m.t, genStake, genCachedStake)
require.Equal(m.t, valStake, genStake)
return valStake
}
@@ -483,7 +489,7 @@ func testOnlineAcctModelSimple(t *testing.T, m onlineAcctModel) {
a.Equal(basics.MicroAlgos{Raw: 43_210_000}, onlineStake)
// expired stake is acct 2 + acct 4
- expiredStake := m.ExpiredOnlineCirculation(680, 1000)
+ expiredStake := m.expiredOnlineCirculation(680, 1000)
a.Equal(basics.MicroAlgos{Raw: 22_110_000}, expiredStake)
}
@@ -519,15 +525,6 @@ type goOfflineAction struct{ addr basics.Address }
func (a goOfflineAction) apply(t *testing.T, m onlineAcctModel) { m.goOffline(a.addr) }
-type updateStakeAction struct {
- addr basics.Address
- stake uint64
-}
-
-func (a updateStakeAction) apply(t *testing.T, m onlineAcctModel) {
- m.updateStake(a.addr, basics.MicroAlgos{Raw: a.stake})
-}
-
type checkOnlineStakeAction struct {
rnd, voteRnd basics.Round
online, expired uint64
@@ -535,7 +532,7 @@ type checkOnlineStakeAction struct {
func (a checkOnlineStakeAction) apply(t *testing.T, m onlineAcctModel) {
onlineStake := m.OnlineCirculation(a.rnd, a.voteRnd)
- expiredStake := m.ExpiredOnlineCirculation(a.rnd, a.voteRnd)
+ expiredStake := m.expiredOnlineCirculation(a.rnd, a.voteRnd)
require.Equal(t, basics.MicroAlgos{Raw: a.online}, onlineStake, "round %d, cur %d", a.rnd, m.currentRound())
require.Equal(t, basics.MicroAlgos{Raw: a.expired}, expiredStake, "rnd %d voteRnd %d, cur %d", a.rnd, a.voteRnd, m.currentRound())
}
@@ -681,7 +678,7 @@ func BenchmarkExpiredOnlineCirculation(b *testing.B) {
// query expired circulation across the available range (last 320 rounds, from ~680 to ~1000)
startRnd := m.currentRound() - 320
offset := basics.Round(i % 320)
- _, err := m.dl.validator.ExpiredOnlineCirculation(startRnd+offset, startRnd+offset+320)
+ _, err := m.dl.validator.expiredOnlineCirculation(startRnd+offset, startRnd+offset+320)
require.NoError(b, err)
//total, err := m.dl.validator.OnlineTotalStake(startRnd + offset)
//b.Log("expired circulation", startRnd+offset, startRnd+offset+320, "returned", expiredStake, "total", total)
diff --git a/ledger/acctonline_test.go b/ledger/acctonline_test.go
index d60353e2ae..afc7244082 100644
--- a/ledger/acctonline_test.go
+++ b/ledger/acctonline_test.go
@@ -1939,7 +1939,7 @@ func TestAcctOnline_ExpiredOnlineCirculation(t *testing.T) {
initialOnlineStake, err := oa.onlineCirculation(0, basics.Round(oa.maxBalLookback()))
a.NoError(err)
a.Equal(totalStake, initialOnlineStake)
- initialExpired, err := oa.ExpiredOnlineCirculation(0, 1000)
+ initialExpired, err := oa.expiredOnlineCirculation(0, 1000)
a.NoError(err)
a.Equal(basics.MicroAlgos{Raw: 0}, initialExpired)
@@ -2146,10 +2146,10 @@ func TestAcctOnline_ExpiredOnlineCirculation(t *testing.T) {
a.Fail("unknown db seed")
}
a.Equal(targetVoteRnd, rnd+basics.Round(params.MaxBalLookback))
- _, err := oa.ExpiredOnlineCirculation(rnd, targetVoteRnd)
+ _, err := oa.expiredOnlineCirculation(rnd, targetVoteRnd)
a.Error(err)
a.Contains(err.Error(), fmt.Sprintf("round %d too high", rnd))
- expiredStake, err := oa.ExpiredOnlineCirculation(rnd-1, targetVoteRnd)
+ expiredStake, err := oa.expiredOnlineCirculation(rnd-1, targetVoteRnd)
a.NoError(err)
a.Equal(expectedExpiredStake, expiredStake)
diff --git a/ledger/acctonlineexp.go b/ledger/acctonlineexp.go
new file mode 100644
index 0000000000..83cdaea456
--- /dev/null
+++ b/ledger/acctonlineexp.go
@@ -0,0 +1,66 @@
+// Copyright (C) 2019-2024 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-deadlock"
+)
+
+type expiredCirculationCache struct {
+ cur map[expiredCirculationKey]basics.MicroAlgos
+ prev map[expiredCirculationKey]basics.MicroAlgos
+
+ maxSize int
+ mu deadlock.RWMutex
+}
+
+type expiredCirculationKey struct {
+ rnd basics.Round
+ voteRnd basics.Round
+}
+
+func makeExpiredCirculationCache(maxSize int) *expiredCirculationCache {
+ return &expiredCirculationCache{
+ cur: make(map[expiredCirculationKey]basics.MicroAlgos),
+ maxSize: maxSize,
+ }
+}
+
+func (c *expiredCirculationCache) get(rnd basics.Round, voteRnd basics.Round) (basics.MicroAlgos, bool) {
+ c.mu.RLock()
+ defer c.mu.RUnlock()
+ if stake, ok := c.cur[expiredCirculationKey{rnd: rnd, voteRnd: voteRnd}]; ok {
+ return stake, true
+ }
+ if stake, ok := c.prev[expiredCirculationKey{rnd: rnd, voteRnd: voteRnd}]; ok {
+ return stake, true
+ }
+
+ return basics.MicroAlgos{}, false
+}
+
+func (c *expiredCirculationCache) put(rnd basics.Round, voteRnd basics.Round, expiredStake basics.MicroAlgos) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ if len(c.cur) >= c.maxSize {
+ c.prev = c.cur
+ c.cur = make(map[expiredCirculationKey]basics.MicroAlgos)
+
+ }
+ c.cur[expiredCirculationKey{rnd: rnd, voteRnd: voteRnd}] = expiredStake
+}
diff --git a/ledger/acctonlineexp_test.go b/ledger/acctonlineexp_test.go
new file mode 100644
index 0000000000..024a8c539c
--- /dev/null
+++ b/ledger/acctonlineexp_test.go
@@ -0,0 +1,69 @@
+// Copyright (C) 2019-2024 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/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/stretchr/testify/require"
+)
+
+func TestAcctOnline_ExpiredCirculationCacheBasic(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ cache := makeExpiredCirculationCache(1)
+
+ expStake1 := basics.MicroAlgos{Raw: 123}
+ cache.put(1, 2, expStake1)
+ stake, ok := cache.get(1, 2)
+ require.True(t, ok)
+ require.Equal(t, expStake1, stake)
+
+ stake, ok = cache.get(3, 4)
+ require.False(t, ok)
+ require.Equal(t, basics.MicroAlgos{}, stake)
+
+ expStake2 := basics.MicroAlgos{Raw: 345}
+ cache.put(3, 4, expStake2)
+
+ stake, ok = cache.get(3, 4)
+ require.True(t, ok)
+ require.Equal(t, expStake2, stake)
+
+ // ensure the old entry is still there
+ stake, ok = cache.get(1, 2)
+ require.True(t, ok)
+ require.Equal(t, expStake1, stake)
+
+ // add one more, should evict the first and keep the second
+ expStake3 := basics.MicroAlgos{Raw: 567}
+ cache.put(5, 6, expStake3)
+ stake, ok = cache.get(5, 6)
+ require.True(t, ok)
+ require.Equal(t, expStake3, stake)
+
+ stake, ok = cache.get(3, 4)
+ require.True(t, ok)
+ require.Equal(t, expStake2, stake)
+
+ stake, ok = cache.get(1, 2)
+ require.False(t, ok)
+ require.Equal(t, basics.MicroAlgos{}, stake)
+}
diff --git a/ledger/apptxn_test.go b/ledger/apptxn_test.go
index 8e40d327e9..a7b3b15214 100644
--- a/ledger/apptxn_test.go
+++ b/ledger/apptxn_test.go
@@ -1104,13 +1104,16 @@ func TestKeyreg(t *testing.T) {
t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis()
- l := newTestLedger(t, genBalances)
- defer l.Close()
- app := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ // 31 allowed inner keyreg
+ ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
+
+ app := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
txn ApplicationArgs 0
byte "pay"
==
@@ -1133,71 +1136,59 @@ nonpart:
itxn_field Nonparticipation
itxn_submit
`),
- }
+ }
- // Create the app
- eval := nextBlock(t, l)
- txns(t, l, eval, &app)
- vb := endBlock(t, l, eval)
- appID := vb.Block().Payset[0].ApplicationID
- require.NotZero(t, appID)
-
- // Give the app a lot of money
- fund := txntest.Txn{
- Type: "pay",
- Sender: addrs[0],
- Receiver: appID.Address(),
- Amount: 1_000_000_000,
- }
- eval = nextBlock(t, l)
- txn(t, l, eval, &fund)
- endBlock(t, l, eval)
+ // Create the app
+ vb := dl.fullBlock(&app)
+ appID := vb.Block().Payset[0].ApplicationID
+ require.NotZero(t, appID)
- require.Equal(t, 1_000_000_000, int(micros(t, l, appID.Address())))
+ // Give the app a lot of money
+ fund := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: appID.Address(),
+ Amount: 1_000_000_000,
+ }
+ dl.fullBlock(&fund)
- // Build up Residue in RewardsState so it's ready to pay
- for i := 1; i < 10; i++ {
- eval := nextBlock(t, l)
- endBlock(t, l, eval)
- }
+ require.Equal(t, 1_000_000_000, int(micros(t, dl.generator, appID.Address())))
- // pay a little
- pay := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApplicationID: appID,
- ApplicationArgs: [][]byte{[]byte("pay")},
- }
- eval = nextBlock(t, l)
- txn(t, l, eval, &pay)
- endBlock(t, l, eval)
- // 2000 was earned in rewards (- 1000 fee, -1 pay)
- require.Equal(t, 1_000_000_999, int(micros(t, l, appID.Address())))
-
- // Go nonpart
- nonpart := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApplicationID: appID,
- ApplicationArgs: [][]byte{[]byte("nonpart")},
- }
- eval = nextBlock(t, l)
- txn(t, l, eval, &nonpart)
- endBlock(t, l, eval)
- require.Equal(t, 999_999_999, int(micros(t, l, appID.Address())))
-
- // Build up Residue in RewardsState so it's ready to pay AGAIN
- // But expect no rewards
- for i := 1; i < 100; i++ {
- eval := nextBlock(t, l)
- endBlock(t, l, eval)
- }
- eval = nextBlock(t, l)
- txn(t, l, eval, pay.Noted("again"))
- txn(t, l, eval, nonpart.Noted("again"), "cannot change online/offline")
- endBlock(t, l, eval)
- // Paid fee + 1. Did not get rewards
- require.Equal(t, 999_998_998, int(micros(t, l, appID.Address())))
+ // Build up Residue in RewardsState so it's ready to pay
+ for i := 1; i < 10; i++ {
+ dl.fullBlock()
+ }
+
+ // pay a little
+ pay := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{[]byte("pay")},
+ }
+ dl.fullBlock(&pay)
+ // 2000 was earned in rewards (- 1000 fee, -1 pay)
+ require.Equal(t, 1_000_000_999, int(micros(t, dl.generator, appID.Address())))
+
+ // Go nonpart
+ nonpart := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{[]byte("nonpart")},
+ }
+ dl.fullBlock(&nonpart)
+ require.Equal(t, 999_999_999, int(micros(t, dl.generator, appID.Address())))
+
+ // Build up Residue in RewardsState so it's ready to pay AGAIN
+ // But expect no rewards
+ for i := 1; i < 100; i++ {
+ dl.fullBlock()
+ }
+ dl.txn(pay.Noted("again"))
+ dl.txn(nonpart.Noted("again"), "cannot change online/offline")
+ require.Equal(t, 999_998_998, int(micros(t, dl.generator, appID.Address())))
+ })
}
func TestInnerAppCall(t *testing.T) {
@@ -1205,13 +1196,16 @@ func TestInnerAppCall(t *testing.T) {
t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis()
- l := newTestLedger(t, genBalances)
- defer l.Close()
- app0 := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ // 31 allowed inner appl.
+ ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
+
+ app0 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
itxn_begin
int pay
itxn_field TypeEnum
@@ -1221,16 +1215,14 @@ func TestInnerAppCall(t *testing.T) {
itxn_field Receiver
itxn_submit
`),
- }
- eval := nextBlock(t, l)
- txn(t, l, eval, &app0)
- vb := endBlock(t, l, eval)
- id0 := vb.Block().Payset[0].ApplicationID
+ }
+ vb := dl.fullBlock(&app0)
+ id0 := vb.Block().Payset[0].ApplicationID
- app1 := txntest.Txn{
- Type: "appl",
- Sender: addrs[1],
- ApprovalProgram: main(`
+ app1 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[1],
+ ApprovalProgram: main(`
itxn_begin
int appl
itxn_field TypeEnum
@@ -1238,32 +1230,28 @@ func TestInnerAppCall(t *testing.T) {
itxn_field ApplicationID
itxn_submit
`),
- }
+ }
- eval = nextBlock(t, l)
- txns(t, l, eval, &app1)
- vb = endBlock(t, l, eval)
- id1 := vb.Block().Payset[0].ApplicationID
+ vb = dl.fullBlock(&app1)
+ id1 := vb.Block().Payset[0].ApplicationID
- fund0 := txntest.Txn{
- Type: "pay",
- Sender: addrs[0],
- Receiver: id0.Address(),
- Amount: 1_000_000_000,
- }
- fund1 := fund0
- fund1.Receiver = id1.Address()
-
- call1 := txntest.Txn{
- Type: "appl",
- Sender: addrs[2],
- ApplicationID: id1,
- ForeignApps: []basics.AppIndex{id0},
- }
- eval = nextBlock(t, l)
- txns(t, l, eval, &fund0, &fund1, &call1)
- endBlock(t, l, eval)
+ fund0 := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: id0.Address(),
+ Amount: 1_000_000_000,
+ }
+ fund1 := fund0
+ fund1.Receiver = id1.Address()
+ call1 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[2],
+ ApplicationID: id1,
+ ForeignApps: []basics.AppIndex{id0},
+ }
+ dl.fullBlock(&fund0, &fund1, &call1)
+ })
}
// TestInnerAppManipulate ensures that apps called from inner transactions make
@@ -1496,13 +1484,16 @@ func TestIndirectReentry(t *testing.T) {
t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis()
- l := newTestLedger(t, genBalances)
- defer l.Close()
- app0 := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ // 31 allowed inner appl.
+ ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
+
+ app0 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
itxn_begin
int appl
itxn_field TypeEnum
@@ -1512,23 +1503,21 @@ func TestIndirectReentry(t *testing.T) {
itxn_field Applications
itxn_submit
`),
- }
- eval := nextBlock(t, l)
- txn(t, l, eval, &app0)
- vb := endBlock(t, l, eval)
- id0 := vb.Block().Payset[0].ApplicationID
-
- fund := txntest.Txn{
- Type: "pay",
- Sender: addrs[0],
- Receiver: id0.Address(),
- Amount: 1_000_000,
- }
+ }
+ vb := dl.fullBlock(&app0)
+ id0 := vb.Block().Payset[0].ApplicationID
- app1 := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ fund := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: id0.Address(),
+ Amount: 1_000_000,
+ }
+
+ app1 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
itxn_begin
int appl
itxn_field TypeEnum
@@ -1536,21 +1525,18 @@ func TestIndirectReentry(t *testing.T) {
itxn_field ApplicationID
itxn_submit
`),
- }
- eval = nextBlock(t, l)
- txns(t, l, eval, &app1, &fund)
- vb = endBlock(t, l, eval)
- id1 := vb.Block().Payset[0].ApplicationID
-
- call1 := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApplicationID: id0,
- ForeignApps: []basics.AppIndex{id1, id0},
- }
- eval = nextBlock(t, l)
- txn(t, l, eval, &call1, "attempt to re-enter")
- endBlock(t, l, eval)
+ }
+ vb = dl.fullBlock(&app1, &fund)
+ id1 := vb.Block().Payset[0].ApplicationID
+
+ call1 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApplicationID: id0,
+ ForeignApps: []basics.AppIndex{id1, id0},
+ }
+ dl.txn(&call1, "attempt to re-enter")
+ })
}
// TestValidAppReentry tests a valid form of reentry (which may not be the correct word here).
@@ -1561,13 +1547,16 @@ func TestValidAppReentry(t *testing.T) {
t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis()
- l := newTestLedger(t, genBalances)
- defer l.Close()
- app0 := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ // 31 allowed inner appl.
+ ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
+
+ app0 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
itxn_begin
int appl
itxn_field TypeEnum
@@ -1584,38 +1573,34 @@ func TestValidAppReentry(t *testing.T) {
itxn_field Applications
itxn_submit
`),
- }
- eval := nextBlock(t, l)
- txn(t, l, eval, &app0)
- vb := endBlock(t, l, eval)
- id0 := vb.Block().Payset[0].ApplicationID
-
- fund0 := txntest.Txn{
- Type: "pay",
- Sender: addrs[0],
- Receiver: id0.Address(),
- Amount: 1_000_000,
- }
+ }
+ vb := dl.fullBlock(&app0)
+ id0 := vb.Block().Payset[0].ApplicationID
- app1 := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ fund0 := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: id0.Address(),
+ Amount: 1_000_000,
+ }
+
+ app1 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
int 3
int 3
==
assert
`),
- }
- eval = nextBlock(t, l)
- txns(t, l, eval, &app1, &fund0)
- vb = endBlock(t, l, eval)
- id1 := vb.Block().Payset[0].ApplicationID
+ }
+ vb = dl.fullBlock(&app1, &fund0)
+ id1 := vb.Block().Payset[0].ApplicationID
- app2 := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ app2 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
itxn_begin
int appl
itxn_field TypeEnum
@@ -1623,32 +1608,27 @@ func TestValidAppReentry(t *testing.T) {
itxn_field ApplicationID
itxn_submit
`),
- }
- eval = nextBlock(t, l)
- txn(t, l, eval, &app2)
- vb = endBlock(t, l, eval)
- id2 := vb.Block().Payset[0].ApplicationID
-
- fund2 := txntest.Txn{
- Type: "pay",
- Sender: addrs[0],
- Receiver: id2.Address(),
- Amount: 1_000_000,
- }
+ }
+ vb = dl.fullBlock(&app2)
+ id2 := vb.Block().Payset[0].ApplicationID
+
+ fund2 := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: id2.Address(),
+ Amount: 1_000_000,
+ }
- eval = nextBlock(t, l)
- txn(t, l, eval, &fund2)
- _ = endBlock(t, l, eval)
+ dl.txn(&fund2)
- call1 := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApplicationID: id0,
- ForeignApps: []basics.AppIndex{id2, id1, id0},
- }
- eval = nextBlock(t, l)
- txn(t, l, eval, &call1)
- endBlock(t, l, eval)
+ call1 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApplicationID: id0,
+ ForeignApps: []basics.AppIndex{id2, id1, id0},
+ }
+ dl.txn(&call1)
+ })
}
func TestMaxInnerTxForSingleAppCall(t *testing.T) {
@@ -1750,13 +1730,15 @@ func TestAbortWhenInnerAppCallFails(t *testing.T) {
t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis()
- l := newTestLedger(t, genBalances)
- defer l.Close()
+ // 31 allowed inner appl.
+ ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
- app0 := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ app0 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
itxn_begin
int appl
itxn_field TypeEnum
@@ -1768,44 +1750,39 @@ int 1
==
assert
`),
- }
- eval := nextBlock(t, l)
- txn(t, l, eval, &app0)
- vb := endBlock(t, l, eval)
- id0 := vb.Block().Payset[0].ApplicationID
-
- fund0 := txntest.Txn{
- Type: "pay",
- Sender: addrs[0],
- Receiver: id0.Address(),
- Amount: 1_000_000,
- }
+ }
+ vb := dl.fullBlock(&app0)
+ id0 := vb.Block().Payset[0].ApplicationID
- app1 := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ fund0 := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: id0.Address(),
+ Amount: 1_000_000,
+ }
+
+ app1 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
int 3
int 2
==
assert
`),
- }
- eval = nextBlock(t, l)
- txns(t, l, eval, &app1, &fund0)
- vb = endBlock(t, l, eval)
- id1 := vb.Block().Payset[0].ApplicationID
-
- callTx := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApplicationID: id0,
- ForeignApps: []basics.AppIndex{id1},
- }
+ }
+ vb = dl.fullBlock(&app1, &fund0)
+ id1 := vb.Block().Payset[0].ApplicationID
+
+ callTx := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApplicationID: id0,
+ ForeignApps: []basics.AppIndex{id1},
+ }
- eval = nextBlock(t, l)
- txn(t, l, eval, &callTx, "logic eval error")
- endBlock(t, l, eval)
+ dl.txn(&callTx, "logic eval error")
+ })
}
// TestSelfCheckHoldingNewApp checks whether a newly created app can check its
@@ -2043,51 +2020,40 @@ func TestAppVersionMatching(t *testing.T) {
t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis()
- l := newTestLedger(t, genBalances)
- defer l.Close()
-
- four, err := logic.AssembleStringWithVersion("int 1", 4)
- require.NoError(t, err)
- five, err := logic.AssembleStringWithVersion("int 1", 5)
- require.NoError(t, err)
- six, err := logic.AssembleStringWithVersion("int 1", 6)
- require.NoError(t, err)
- create := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: five.Program,
- ClearStateProgram: five.Program,
- }
-
- eval := nextBlock(t, l)
- txn(t, l, eval, &create)
- endBlock(t, l, eval)
-
- create.ClearStateProgram = six.Program
-
- eval = nextBlock(t, l)
- txn(t, l, eval, &create, "version mismatch")
- endBlock(t, l, eval)
+ // matching required in v6 which is v31
+ ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
- create.ApprovalProgram = six.Program
+ four, err := logic.AssembleStringWithVersion("int 1", 4)
+ require.NoError(t, err)
+ five, err := logic.AssembleStringWithVersion("int 1", 5)
+ require.NoError(t, err)
+ six, err := logic.AssembleStringWithVersion("int 1", 6)
+ require.NoError(t, err)
- eval = nextBlock(t, l)
- txn(t, l, eval, &create)
- endBlock(t, l, eval)
+ create := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: five.Program,
+ ClearStateProgram: five.Program,
+ }
+ dl.txn(&create)
- create.ClearStateProgram = four.Program
+ create.ClearStateProgram = six.Program
+ dl.txn(&create, "version mismatch")
- eval = nextBlock(t, l)
- txn(t, l, eval, &create, "version mismatch")
- endBlock(t, l, eval)
+ create.ApprovalProgram = six.Program
+ dl.txn(&create)
- // four doesn't match five, but it doesn't have to
- create.ApprovalProgram = five.Program
+ create.ClearStateProgram = four.Program
+ dl.txn(&create, "version mismatch")
- eval = nextBlock(t, l)
- txn(t, l, eval, &create)
- endBlock(t, l, eval)
+ // four doesn't match five, but it doesn't have to
+ create.ApprovalProgram = five.Program
+ dl.txn(&create)
+ })
}
func TestAppDowngrade(t *testing.T) {
@@ -2453,34 +2419,34 @@ func TestInnerClearState(t *testing.T) {
t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis()
- l := newTestLedger(t, genBalances)
- defer l.Close()
+ // Inner apps start in v31
+ ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
- // inner will be an app that we opt into, then clearstate
- // note that clearstate rejects
- inner := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: "int 1",
- ClearStateProgram: "int 0",
- LocalStateSchema: basics.StateSchema{
- NumUint: 2,
- NumByteSlice: 2,
- },
- }
+ // inner will be an app that we opt into, then clearstate
+ // note that clearstate rejects
+ inner := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: "int 1",
+ ClearStateProgram: "int 0",
+ LocalStateSchema: basics.StateSchema{
+ NumUint: 2,
+ NumByteSlice: 2,
+ },
+ }
- eval := nextBlock(t, l)
- txn(t, l, eval, &inner)
- vb := endBlock(t, l, eval)
- innerID := vb.Block().Payset[0].ApplicationID
+ vb := dl.fullBlock(&inner)
+ innerID := vb.Block().Payset[0].ApplicationID
- // Outer is a simple app that will invoke the given app (in ForeignApps[0])
- // with the given OnCompletion (in ApplicationArgs[0]). Goal is to use it
- // to opt into, and the clear state, on the inner app.
- outer := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ // Outer is a simple app that will invoke the given app (in ForeignApps[0])
+ // with the given OnCompletion (in ApplicationArgs[0]). Goal is to use it
+ // to opt into, and the clear state, on the inner app.
+ outer := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
itxn_begin
int appl
itxn_field TypeEnum
@@ -2491,48 +2457,42 @@ itxn_begin
itxn_field OnCompletion
itxn_submit
`),
- ForeignApps: []basics.AppIndex{innerID},
- }
+ ForeignApps: []basics.AppIndex{innerID},
+ }
- eval = nextBlock(t, l)
- txn(t, l, eval, &outer)
- vb = endBlock(t, l, eval)
- outerID := vb.Block().Payset[0].ApplicationID
+ vb = dl.fullBlock(&outer)
+ outerID := vb.Block().Payset[0].ApplicationID
- fund := txntest.Txn{
- Type: "pay",
- Sender: addrs[0],
- Receiver: outerID.Address(),
- Amount: 1_000_000,
- }
+ fund := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: outerID.Address(),
+ Amount: 1_000_000,
+ }
- call := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApplicationID: outerID,
- ApplicationArgs: [][]byte{{byte(transactions.OptInOC)}},
- ForeignApps: []basics.AppIndex{innerID},
- }
- eval = nextBlock(t, l)
- txns(t, l, eval, &fund, &call)
- endBlock(t, l, eval)
-
- outerAcct := lookup(t, l, outerID.Address())
- require.Len(t, outerAcct.AppLocalStates, 1)
- require.Equal(t, outerAcct.TotalAppSchema, basics.StateSchema{
- NumUint: 2,
- NumByteSlice: 2,
- })
+ call := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApplicationID: outerID,
+ ApplicationArgs: [][]byte{{byte(transactions.OptInOC)}},
+ ForeignApps: []basics.AppIndex{innerID},
+ }
+ dl.txns(&fund, &call)
- call.ApplicationArgs = [][]byte{{byte(transactions.ClearStateOC)}}
- eval = nextBlock(t, l)
- txn(t, l, eval, &call)
- endBlock(t, l, eval)
+ outerAcct := lookup(t, dl.generator, outerID.Address())
+ require.Len(t, outerAcct.AppLocalStates, 1)
+ require.Equal(t, outerAcct.TotalAppSchema, basics.StateSchema{
+ NumUint: 2,
+ NumByteSlice: 2,
+ })
- outerAcct = lookup(t, l, outerID.Address())
- require.Empty(t, outerAcct.AppLocalStates)
- require.Empty(t, outerAcct.TotalAppSchema)
+ call.ApplicationArgs = [][]byte{{byte(transactions.ClearStateOC)}}
+ dl.txn(&call)
+ outerAcct = lookup(t, dl.generator, outerID.Address())
+ require.Empty(t, outerAcct.AppLocalStates)
+ require.Empty(t, outerAcct.TotalAppSchema)
+ })
}
// TestInnerClearStateBadCallee ensures that inner clear state programs are not
@@ -2542,34 +2502,34 @@ func TestInnerClearStateBadCallee(t *testing.T) {
t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis()
- l := newTestLedger(t, genBalances)
- defer l.Close()
+ // Inner appls start in v31
+ ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
- // badCallee tries to run down your budget, so an inner clear must be
- // protected from exhaustion
- badCallee := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: "int 1",
- ClearStateProgram: `top:
+ // badCallee tries to run down your budget, so an inner clear must be
+ // protected from exhaustion
+ badCallee := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: "int 1",
+ ClearStateProgram: `top:
int 1
pop
b top
`,
- }
+ }
- eval := nextBlock(t, l)
- txn(t, l, eval, &badCallee)
- vb := endBlock(t, l, eval)
- badID := vb.Block().Payset[0].ApplicationID
+ vb := dl.fullBlock(&badCallee)
+ badID := vb.Block().Payset[0].ApplicationID
- // Outer is a simple app that will invoke the given app (in ForeignApps[0])
- // with the given OnCompletion (in ApplicationArgs[0]). Goal is to use it
- // to opt into, and then clear state, the bad app
- outer := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ // Outer is a simple app that will invoke the given app (in ForeignApps[0])
+ // with the given OnCompletion (in ApplicationArgs[0]). Goal is to use it
+ // to opt into, and then clear state, the bad app
+ outer := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
itxn_begin
int appl
itxn_field TypeEnum
@@ -2597,44 +2557,39 @@ bnz skip // Don't do budget checking during optin
assert
skip:
`),
- ForeignApps: []basics.AppIndex{badID},
- }
+ ForeignApps: []basics.AppIndex{badID},
+ }
- eval = nextBlock(t, l)
- txn(t, l, eval, &outer)
- vb = endBlock(t, l, eval)
- outerID := vb.Block().Payset[0].ApplicationID
+ vb = dl.fullBlock(&outer)
+ outerID := vb.Block().Payset[0].ApplicationID
- fund := txntest.Txn{
- Type: "pay",
- Sender: addrs[0],
- Receiver: outerID.Address(),
- Amount: 1_000_000,
- }
+ fund := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: outerID.Address(),
+ Amount: 1_000_000,
+ }
- call := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApplicationID: outerID,
- ApplicationArgs: [][]byte{{byte(transactions.OptInOC)}},
- ForeignApps: []basics.AppIndex{badID},
- }
- eval = nextBlock(t, l)
- txns(t, l, eval, &fund, &call)
- endBlock(t, l, eval)
-
- outerAcct := lookup(t, l, outerID.Address())
- require.Len(t, outerAcct.AppLocalStates, 1)
-
- // When doing a clear state, `call` checks that budget wasn't stolen
- call.ApplicationArgs = [][]byte{{byte(transactions.ClearStateOC)}}
- eval = nextBlock(t, l)
- txn(t, l, eval, &call)
- endBlock(t, l, eval)
-
- // Clearstate took effect, despite failure from infinite loop
- outerAcct = lookup(t, l, outerID.Address())
- require.Empty(t, outerAcct.AppLocalStates)
+ call := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApplicationID: outerID,
+ ApplicationArgs: [][]byte{{byte(transactions.OptInOC)}},
+ ForeignApps: []basics.AppIndex{badID},
+ }
+ dl.fullBlock(&fund, &call)
+
+ outerAcct := lookup(t, dl.generator, outerID.Address())
+ require.Len(t, outerAcct.AppLocalStates, 1)
+
+ // When doing a clear state, `call` checks that budget wasn't stolen
+ call.ApplicationArgs = [][]byte{{byte(transactions.ClearStateOC)}}
+ dl.fullBlock(&call)
+
+ // Clearstate took effect, despite failure from infinite loop
+ outerAcct = lookup(t, dl.generator, outerID.Address())
+ require.Empty(t, outerAcct.AppLocalStates)
+ })
}
// TestInnerClearStateBadCaller ensures that inner clear state programs cannot
@@ -2644,28 +2599,30 @@ func TestInnerClearStateBadCaller(t *testing.T) {
t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis()
- l := newTestLedger(t, genBalances)
- defer l.Close()
+ // Inner appls start in v31
+ ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
- inner := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: "int 1",
- ClearStateProgram: `global OpcodeBudget
+ inner := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: "int 1",
+ ClearStateProgram: `global OpcodeBudget
itob
log
int 1`,
- LocalStateSchema: basics.StateSchema{
- NumUint: 1,
- NumByteSlice: 2,
- },
- }
+ LocalStateSchema: basics.StateSchema{
+ NumUint: 1,
+ NumByteSlice: 2,
+ },
+ }
- // waster allows tries to get the budget down below 100 before returning
- waster := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ // waster allows tries to get the budget down below 100 before returning
+ waster := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
global OpcodeBudget
itob
log
@@ -2683,25 +2640,23 @@ global OpcodeBudget
itob
log
`),
- LocalStateSchema: basics.StateSchema{
- NumUint: 3,
- NumByteSlice: 4,
- },
- }
+ LocalStateSchema: basics.StateSchema{
+ NumUint: 3,
+ NumByteSlice: 4,
+ },
+ }
- eval := nextBlock(t, l)
- txns(t, l, eval, &inner, &waster)
- vb := endBlock(t, l, eval)
- innerID := vb.Block().Payset[0].ApplicationID
- wasterID := vb.Block().Payset[1].ApplicationID
+ vb := dl.fullBlock(&inner, &waster)
+ innerID := vb.Block().Payset[0].ApplicationID
+ wasterID := vb.Block().Payset[1].ApplicationID
- // Grouper is a simple app that will invoke the given apps (in
- // ForeignApps[0,1]) as a group, with the given OnCompletion (in
- // ApplicationArgs[0]).
- grouper := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ // Grouper is a simple app that will invoke the given apps (in
+ // ForeignApps[0,1]) as a group, with the given OnCompletion (in
+ // ApplicationArgs[0]).
+ grouper := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
itxn_begin
int appl
itxn_field TypeEnum
@@ -2720,43 +2675,37 @@ itxn_next
itxn_field OnCompletion
itxn_submit
`),
- }
+ }
- eval = nextBlock(t, l)
- txn(t, l, eval, &grouper)
- vb = endBlock(t, l, eval)
- grouperID := vb.Block().Payset[0].ApplicationID
+ vb = dl.fullBlock(&grouper)
+ grouperID := vb.Block().Payset[0].ApplicationID
- fund := txntest.Txn{
- Type: "pay",
- Sender: addrs[0],
- Receiver: grouperID.Address(),
- Amount: 1_000_000,
- }
+ fund := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: grouperID.Address(),
+ Amount: 1_000_000,
+ }
- call := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApplicationID: grouperID,
- ApplicationArgs: [][]byte{{byte(transactions.OptInOC)}, {byte(transactions.OptInOC)}},
- ForeignApps: []basics.AppIndex{wasterID, innerID},
- }
- eval = nextBlock(t, l)
- txns(t, l, eval, &fund, &call)
- endBlock(t, l, eval)
-
- gAcct := lookup(t, l, grouperID.Address())
- require.Len(t, gAcct.AppLocalStates, 2)
-
- call.ApplicationArgs = [][]byte{{byte(transactions.CloseOutOC)}, {byte(transactions.ClearStateOC)}}
- eval = nextBlock(t, l)
- txn(t, l, eval, &call, "ClearState execution with low OpcodeBudget")
- vb = endBlock(t, l, eval)
- require.Len(t, vb.Block().Payset, 0)
-
- // Clearstate did not take effect, since the caller tried to shortchange the CSP
- gAcct = lookup(t, l, grouperID.Address())
- require.Len(t, gAcct.AppLocalStates, 2)
+ call := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApplicationID: grouperID,
+ ApplicationArgs: [][]byte{{byte(transactions.OptInOC)}, {byte(transactions.OptInOC)}},
+ ForeignApps: []basics.AppIndex{wasterID, innerID},
+ }
+ dl.fullBlock(&fund, &call)
+
+ gAcct := lookup(t, dl.generator, grouperID.Address())
+ require.Len(t, gAcct.AppLocalStates, 2)
+
+ call.ApplicationArgs = [][]byte{{byte(transactions.CloseOutOC)}, {byte(transactions.ClearStateOC)}}
+ dl.txn(&call, "ClearState execution with low OpcodeBudget")
+
+ // Clearstate did not take effect, since the caller tried to shortchange the CSP
+ gAcct = lookup(t, dl.generator, grouperID.Address())
+ require.Len(t, gAcct.AppLocalStates, 2)
+ })
}
// TestClearStateInnerPay ensures that ClearState programs can run inner txns in
@@ -2880,13 +2829,15 @@ func TestGlobalChangesAcrossApps(t *testing.T) {
t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis()
- l := newTestLedger(t, genBalances)
- defer l.Close()
+ // Inner appls start in v31
+ ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
- appA := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ appA := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
// Call B : No arguments means: set your global "X" to "ABC"
itxn_begin
int appl; itxn_field TypeEnum
@@ -2916,12 +2867,12 @@ func TestGlobalChangesAcrossApps(t *testing.T) {
==
assert
`),
- }
+ }
- appB := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ appB := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
txn NumAppArgs
bnz check // 1 arg means check
// set
@@ -2937,15 +2888,15 @@ check:
assert
b end
`),
- GlobalStateSchema: basics.StateSchema{
- NumByteSlice: 1,
- },
- }
+ GlobalStateSchema: basics.StateSchema{
+ NumByteSlice: 1,
+ },
+ }
- appC := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ appC := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
txn Applications 1
byte "X"
app_global_get_ex
@@ -2954,32 +2905,29 @@ check:
==
assert
`),
- }
+ }
- eval := nextBlock(t, l)
- txns(t, l, eval, &appA, &appB, &appC)
- vb := endBlock(t, l, eval)
- idA := vb.Block().Payset[0].ApplicationID
- idB := vb.Block().Payset[1].ApplicationID
- idC := vb.Block().Payset[2].ApplicationID
-
- fundA := txntest.Txn{
- Type: "pay",
- Sender: addrs[0],
- Receiver: idA.Address(),
- Amount: 1_000_000,
- }
+ vb := dl.fullBlock(&appA, &appB, &appC)
+ idA := vb.Block().Payset[0].ApplicationID
+ idB := vb.Block().Payset[1].ApplicationID
+ idC := vb.Block().Payset[2].ApplicationID
- callA := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApplicationID: idA,
- ForeignApps: []basics.AppIndex{idB, idC},
- }
+ fundA := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: idA.Address(),
+ Amount: 1_000_000,
+ }
- eval = nextBlock(t, l)
- txns(t, l, eval, &fundA, &callA)
- endBlock(t, l, eval)
+ callA := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApplicationID: idA,
+ ForeignApps: []basics.AppIndex{idB, idC},
+ }
+
+ dl.fullBlock(&fundA, &callA)
+ })
}
// TestLocalChangesAcrossApps ensures that state changes are seen by other app
@@ -2989,13 +2937,15 @@ func TestLocalChangesAcrossApps(t *testing.T) {
t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis()
- l := newTestLedger(t, genBalances)
- defer l.Close()
+ // Inner appls start in v31
+ ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
- appA := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ appA := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
// Call B : No arguments means: set caller's local "X" to "ABC"
itxn_begin
int appl; itxn_field TypeEnum
@@ -3027,12 +2977,12 @@ func TestLocalChangesAcrossApps(t *testing.T) {
==
assert
`),
- }
+ }
- appB := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ appB := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
txn NumAppArgs
bnz check // 1 arg means check
// set
@@ -3050,15 +3000,15 @@ check:
assert
b end
`),
- LocalStateSchema: basics.StateSchema{
- NumByteSlice: 1,
- },
- }
+ LocalStateSchema: basics.StateSchema{
+ NumByteSlice: 1,
+ },
+ }
- appC := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApprovalProgram: main(`
+ appC := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
txn Sender
txn Applications 1
byte "X"
@@ -3068,32 +3018,29 @@ check:
==
assert
`),
- }
+ }
- eval := nextBlock(t, l)
- txns(t, l, eval, &appA, &appB, &appC)
- vb := endBlock(t, l, eval)
- idA := vb.Block().Payset[0].ApplicationID
- idB := vb.Block().Payset[1].ApplicationID
- idC := vb.Block().Payset[2].ApplicationID
-
- fundA := txntest.Txn{
- Type: "pay",
- Sender: addrs[0],
- Receiver: idA.Address(),
- Amount: 1_000_000,
- }
+ vb := dl.fullBlock(&appA, &appB, &appC)
+ idA := vb.Block().Payset[0].ApplicationID
+ idB := vb.Block().Payset[1].ApplicationID
+ idC := vb.Block().Payset[2].ApplicationID
- callA := txntest.Txn{
- Type: "appl",
- Sender: addrs[0],
- ApplicationID: idA,
- ForeignApps: []basics.AppIndex{idB, idC},
- }
+ fundA := txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: idA.Address(),
+ Amount: 1_000_000,
+ }
- eval = nextBlock(t, l)
- txns(t, l, eval, &fundA, &callA)
- endBlock(t, l, eval)
+ callA := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApplicationID: idA,
+ ForeignApps: []basics.AppIndex{idB, idC},
+ }
+
+ dl.fullBlock(&fundA, &callA)
+ })
}
func TestForeignAppAccountsAccessible(t *testing.T) {
diff --git a/ledger/double_test.go b/ledger/double_test.go
index 0854943636..c1cd09f97c 100644
--- a/ledger/double_test.go
+++ b/ledger/double_test.go
@@ -153,23 +153,24 @@ func (dl *DoubleLedger) endBlock(proposer ...basics.Address) *ledgercore.Validat
return vb
}
-func (dl *DoubleLedger) fundedApp(sender basics.Address, amount uint64, source string) basics.AppIndex {
+func (dl *DoubleLedger) createApp(sender basics.Address, source string) basics.AppIndex {
createapp := txntest.Txn{
Type: "appl",
Sender: sender,
ApprovalProgram: source,
}
vb := dl.fullBlock(&createapp)
- appIndex := vb.Block().Payset[0].ApplyData.ApplicationID
+ return vb.Block().Payset[0].ApplyData.ApplicationID
+}
- fund := txntest.Txn{
+func (dl *DoubleLedger) fundedApp(sender basics.Address, amount uint64, source string) basics.AppIndex {
+ appIndex := dl.createApp(sender, source)
+ dl.fullBlock(&txntest.Txn{
Type: "pay",
Sender: sender,
Receiver: appIndex.Address(),
Amount: amount,
- }
-
- dl.txn(&fund)
+ })
return appIndex
}
diff --git a/ledger/eval/appcow_test.go b/ledger/eval/appcow_test.go
index 60ab1df25e..6f5e39b305 100644
--- a/ledger/eval/appcow_test.go
+++ b/ledger/eval/appcow_test.go
@@ -48,6 +48,14 @@ func (ml *emptyLedger) lookup(addr basics.Address) (ledgercore.AccountData, erro
return ledgercore.AccountData{}, nil
}
+func (ml *emptyLedger) lookupAgreement(addr basics.Address) (basics.OnlineAccountData, error) {
+ return basics.OnlineAccountData{}, nil
+}
+
+func (ml *emptyLedger) onlineStake() (basics.MicroAlgos, error) {
+ return basics.MicroAlgos{}, nil
+}
+
func (ml *emptyLedger) lookupAppParams(addr basics.Address, aidx basics.AppIndex, cacheOnly bool) (ledgercore.AppParamsDelta, bool, error) {
return ledgercore.AppParamsDelta{}, true, nil
}
diff --git a/ledger/eval/applications.go b/ledger/eval/applications.go
index 3aa7bd3905..c1d5d6d619 100644
--- a/ledger/eval/applications.go
+++ b/ledger/eval/applications.go
@@ -38,6 +38,23 @@ func (cs *roundCowState) AccountData(addr basics.Address) (ledgercore.AccountDat
return record, nil
}
+func (cs *roundCowState) AgreementData(addr basics.Address) (basics.OnlineAccountData, error) {
+ record, err := cs.lookupAgreement(addr)
+ if err != nil {
+ return basics.OnlineAccountData{}, err
+ }
+ return record, nil
+}
+
+func (cs *roundCowState) OnlineStake() (basics.MicroAlgos, error) {
+ return cs.lookupParent.onlineStake()
+}
+
+// onlineStake is needed to implement roundCowParent
+func (cs *roundCowState) onlineStake() (basics.MicroAlgos, error) {
+ return cs.lookupParent.onlineStake()
+}
+
func (cs *roundCowState) Authorizer(addr basics.Address) (basics.Address, error) {
record, err := cs.Get(addr, false) // pending rewards unneeded
if err != nil {
diff --git a/ledger/eval/cow.go b/ledger/eval/cow.go
index 23c415bbdf..9511af7ce7 100644
--- a/ledger/eval/cow.go
+++ b/ledger/eval/cow.go
@@ -44,6 +44,10 @@ type roundCowParent interface {
// lookup retrieves data about an address, eventually querying the ledger if the address was not found in cache.
lookup(basics.Address) (ledgercore.AccountData, error)
+ // lookup retrieves agreement data about an address, querying the ledger if necessary.
+ lookupAgreement(basics.Address) (basics.OnlineAccountData, error)
+ onlineStake() (basics.MicroAlgos, error)
+
// lookupAppParams, lookupAssetParams, lookupAppLocalState, and lookupAssetHolding retrieve data for a given address and ID.
// If cacheOnly is set, the ledger DB will not be queried, and only the cache will be consulted.
// This is used when we know a given value is already in cache (from a previous query for that same address and ID),
@@ -182,6 +186,12 @@ func (cb *roundCowState) lookup(addr basics.Address) (data ledgercore.AccountDat
return cb.lookupParent.lookup(addr)
}
+// lookupAgreement differs from other lookup methods because it need not
+// maintain a local value because it cannot be modified by transactions.
+func (cb *roundCowState) lookupAgreement(addr basics.Address) (data basics.OnlineAccountData, err error) {
+ return cb.lookupParent.lookupAgreement(addr)
+}
+
func (cb *roundCowState) lookupAppParams(addr basics.Address, aidx basics.AppIndex, cacheOnly bool) (ledgercore.AppParamsDelta, bool, error) {
params, ok := cb.mods.Accts.GetAppParams(addr, aidx)
if ok {
diff --git a/ledger/eval/cow_test.go b/ledger/eval/cow_test.go
index 81224a8d0b..138e2562ad 100644
--- a/ledger/eval/cow_test.go
+++ b/ledger/eval/cow_test.go
@@ -44,6 +44,35 @@ func (ml *mockLedger) lookup(addr basics.Address) (ledgercore.AccountData, error
return ledgercore.ToAccountData(ml.balanceMap[addr]), nil
}
+// convertToOnline is only suitable for test code because OnlineAccountData
+// should have rewards paid. Here, we ignore that for simple tests.
+func convertToOnline(ad ledgercore.AccountData) basics.OnlineAccountData {
+ return basics.OnlineAccountData{
+ MicroAlgosWithRewards: ad.MicroAlgos,
+ VotingData: basics.VotingData{
+ VoteID: ad.VoteID,
+ SelectionID: ad.SelectionID,
+ StateProofID: ad.StateProofID,
+ VoteFirstValid: ad.VoteFirstValid,
+ VoteLastValid: ad.VoteLastValid,
+ VoteKeyDilution: ad.VoteKeyDilution,
+ },
+ IncentiveEligible: ad.IncentiveEligible,
+ }
+}
+
+func (ml *mockLedger) lookupAgreement(addr basics.Address) (basics.OnlineAccountData, error) {
+ ad, err := ml.lookup(addr)
+ if err != nil { // impossible, see lookup()
+ return basics.OnlineAccountData{}, err
+ }
+ return convertToOnline(ad), nil
+}
+
+func (ml *mockLedger) onlineStake() (basics.MicroAlgos, error) {
+ return basics.Algos(55_555), nil
+}
+
func (ml *mockLedger) lookupAppParams(addr basics.Address, aidx basics.AppIndex, cacheOnly bool) (ledgercore.AppParamsDelta, bool, error) {
params, ok := ml.balanceMap[addr].AppParams[aidx]
return ledgercore.AppParamsDelta{Params: ¶ms}, ok, nil // XXX make a copy?
diff --git a/ledger/eval/eval.go b/ledger/eval/eval.go
index 6599dd5918..859b62922f 100644
--- a/ledger/eval/eval.go
+++ b/ledger/eval/eval.go
@@ -24,6 +24,7 @@ import (
"math/bits"
"sync"
+ "github.com/algorand/go-algorand/agreement"
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/basics"
@@ -46,11 +47,13 @@ type LedgerForCowBase interface {
GenesisHash() crypto.Digest
CheckDup(config.ConsensusParams, basics.Round, basics.Round, basics.Round, transactions.Txid, ledgercore.Txlease) error
LookupWithoutRewards(basics.Round, basics.Address) (ledgercore.AccountData, basics.Round, error)
+ LookupAgreement(basics.Round, basics.Address) (basics.OnlineAccountData, error)
LookupAsset(basics.Round, basics.Address, basics.AssetIndex) (ledgercore.AssetResource, error)
LookupApplication(basics.Round, basics.Address, basics.AppIndex) (ledgercore.AppResource, error)
LookupKv(basics.Round, string) ([]byte, error)
GetCreatorForRound(basics.Round, basics.CreatableIndex, basics.CreatableType) (basics.Address, bool, error)
GetStateProofVerificationContext(stateProofLastAttestedRound basics.Round) (*ledgercore.StateProofVerificationContext, error)
+ OnlineCirculation(basics.Round, basics.Round) (basics.MicroAlgos, error)
}
// ErrRoundZero is self-explanatory
@@ -129,6 +132,15 @@ type roundCowBase struct {
// The account data store here is always the account data without the rewards.
accounts map[basics.Address]ledgercore.AccountData
+ // The online accounts that we've already accessed during this round evaluation. This is a
+ // cache used to avoid looking up the same account data more than once during a single evaluator
+ // execution. The OnlineAccountData is historical and therefore won't be changing.
+ onlineAccounts map[basics.Address]basics.OnlineAccountData
+
+ // totalOnline is the cached amount of online stake for rnd (so it's from
+ // rnd-320). The zero value indicates it is not yet cached.
+ totalOnline basics.MicroAlgos
+
// Similarly to accounts cache that stores base account data, there are caches for params, states, holdings.
appParams map[ledgercore.AccountApp]cachedAppParams
assetParams map[ledgercore.AccountAsset]cachedAssetParams
@@ -150,6 +162,7 @@ func makeRoundCowBase(l LedgerForCowBase, rnd basics.Round, txnCount uint64, sta
stateProofNextRnd: stateProofNextRnd,
proto: proto,
accounts: make(map[basics.Address]ledgercore.AccountData),
+ onlineAccounts: make(map[basics.Address]basics.OnlineAccountData),
appParams: make(map[ledgercore.AccountApp]cachedAppParams),
assetParams: make(map[ledgercore.AccountAsset]cachedAssetParams),
appLocalStates: make(map[ledgercore.AccountApp]cachedAppLocalState),
@@ -193,6 +206,56 @@ func (x *roundCowBase) lookup(addr basics.Address) (ledgercore.AccountData, erro
return ad, err
}
+// balanceRound reproduces the way that the agreement package finds the round to
+// consider for online accounts.
+func (x *roundCowBase) balanceRound() (basics.Round, error) {
+ phdr, err := x.BlockHdr(agreement.ParamsRound(x.rnd))
+ if err != nil {
+ return 0, err
+ }
+ agreementParams := config.Consensus[phdr.CurrentProtocol]
+ return agreement.BalanceRound(x.rnd, agreementParams), nil
+}
+
+// lookupAgreement returns the online accountdata for the provided account address. It uses an internal cache
+// to avoid repeated lookups against the ledger.
+func (x *roundCowBase) lookupAgreement(addr basics.Address) (basics.OnlineAccountData, error) {
+ if accountData, found := x.onlineAccounts[addr]; found {
+ return accountData, nil
+ }
+
+ brnd, err := x.balanceRound()
+ if err != nil {
+ return basics.OnlineAccountData{}, err
+ }
+ ad, err := x.l.LookupAgreement(brnd, addr)
+ if err != nil {
+ return basics.OnlineAccountData{}, err
+ }
+
+ x.onlineAccounts[addr] = ad
+ return ad, err
+}
+
+// onlineStake returns the total online stake as of the start of the round. It
+// caches the result to prevent repeated calls to the ledger.
+func (x *roundCowBase) onlineStake() (basics.MicroAlgos, error) {
+ if !x.totalOnline.IsZero() {
+ return x.totalOnline, nil
+ }
+
+ brnd, err := x.balanceRound()
+ if err != nil {
+ return basics.MicroAlgos{}, err
+ }
+ total, err := x.l.OnlineCirculation(brnd, x.rnd)
+ if err != nil {
+ return basics.MicroAlgos{}, err
+ }
+ x.totalOnline = total
+ return x.totalOnline, err
+}
+
func (x *roundCowBase) updateAssetResourceCache(aa ledgercore.AccountAsset, r ledgercore.AssetResource) {
// cache AssetParams and AssetHolding returned by LookupResource
if r.AssetParams == nil {
diff --git a/ledger/eval/eval_test.go b/ledger/eval/eval_test.go
index 994bedd561..77a477b3c0 100644
--- a/ledger/eval/eval_test.go
+++ b/ledger/eval/eval_test.go
@@ -180,6 +180,7 @@ ok:
// and the usage counts correctly propagated from parent cow to child cow and back
func TestEvalAppStateCountsWithTxnGroup(t *testing.T) {
partitiontest.PartitionTest(t)
+ t.Parallel()
_, _, err := testEvalAppGroup(t, basics.StateSchema{NumByteSlice: 1})
require.ErrorContains(t, err, "store bytes count 2 exceeds schema bytes count 1")
@@ -189,6 +190,7 @@ func TestEvalAppStateCountsWithTxnGroup(t *testing.T) {
// produce correct results when a txn group has storage allocate and storage update actions
func TestEvalAppAllocStateWithTxnGroup(t *testing.T) {
partitiontest.PartitionTest(t)
+ t.Parallel()
eval, addr, err := testEvalAppGroup(t, basics.StateSchema{NumByteSlice: 2})
require.NoError(t, err)
@@ -203,6 +205,7 @@ func TestEvalAppAllocStateWithTxnGroup(t *testing.T) {
// see TestBlockEvaluator for more
func TestTestTransactionGroup(t *testing.T) {
partitiontest.PartitionTest(t)
+ t.Parallel()
var txgroup []transactions.SignedTxn
eval := BlockEvaluator{}
@@ -219,6 +222,7 @@ func TestTestTransactionGroup(t *testing.T) {
// some trivial checks that require no setup
func TestPrivateTransactionGroup(t *testing.T) {
partitiontest.PartitionTest(t)
+ t.Parallel()
var txgroup []transactions.SignedTxnWithAD
eval := BlockEvaluator{}
@@ -675,56 +679,6 @@ func testnetFixupExecution(t *testing.T, headerRound basics.Round, poolBonus uin
require.NoError(t, err)
}
-// newTestGenesis creates a bunch of accounts, splits up 10B algos
-// between them and the rewardspool and feesink, and gives out the
-// addresses and secrets it creates to enable tests. For special
-// scenarios, manipulate these return values before using newTestLedger.
-func newTestGenesis() (bookkeeping.GenesisBalances, []basics.Address, []*crypto.SignatureSecrets) {
- // irrelevant, but deterministic
- sink, err := basics.UnmarshalChecksumAddress("YTPRLJ2KK2JRFSZZNAF57F3K5Y2KCG36FZ5OSYLW776JJGAUW5JXJBBD7Q")
- if err != nil {
- panic(err)
- }
- rewards, err := basics.UnmarshalChecksumAddress("242H5OXHUEBYCGGWB3CQ6AZAMQB5TMCWJGHCGQOZPEIVQJKOO7NZXUXDQA")
- if err != nil {
- panic(err)
- }
-
- const count = 10
- addrs := make([]basics.Address, count)
- secrets := make([]*crypto.SignatureSecrets, count)
- accts := make(map[basics.Address]basics.AccountData)
-
- // 10 billion microalgos, across N accounts and pool and sink
- amount := 10 * 1000000000 * 1000000 / uint64(count+2)
-
- for i := 0; i < count; i++ {
- // Create deterministic addresses, so that output stays the same, run to run.
- var seed crypto.Seed
- seed[0] = byte(i)
- secrets[i] = crypto.GenerateSignatureSecrets(seed)
- addrs[i] = basics.Address(secrets[i].SignatureVerifier)
-
- adata := basics.AccountData{
- MicroAlgos: basics.MicroAlgos{Raw: amount},
- }
- accts[addrs[i]] = adata
- }
-
- accts[sink] = basics.AccountData{
- MicroAlgos: basics.MicroAlgos{Raw: amount},
- Status: basics.NotParticipating,
- }
-
- accts[rewards] = basics.AccountData{
- MicroAlgos: basics.MicroAlgos{Raw: amount},
- }
-
- genBalances := bookkeeping.MakeGenesisBalances(accts, sink, rewards)
-
- return genBalances, addrs, secrets
-}
-
type evalTestLedger struct {
blocks map[basics.Round]bookkeeping.Block
roundBalances map[basics.Round]map[basics.Address]basics.AccountData
@@ -827,11 +781,21 @@ func (ledger *evalTestLedger) LatestTotals() (basics.Round, ledgercore.AccountTo
return basics.Round(len(ledger.blocks)).SubSaturate(1), ledger.latestTotals, nil
}
-// LookupWithoutRewards is like Lookup but does not apply pending rewards up
-// to the requested round rnd.
+// LookupWithoutRewards is like Lookup but is not supposed to apply pending
+// rewards up to the requested round rnd. Here Lookup doesn't do that anyway.
func (ledger *evalTestLedger) LookupWithoutRewards(rnd basics.Round, addr basics.Address) (ledgercore.AccountData, basics.Round, error) {
- ad := ledger.roundBalances[rnd][addr]
- return ledgercore.ToAccountData(ad), rnd, nil
+ ad, err := ledger.Lookup(rnd, addr)
+ return ledgercore.ToAccountData(ad), rnd, err
+}
+
+func (ledger *evalTestLedger) LookupAgreement(rnd basics.Round, addr basics.Address) (basics.OnlineAccountData, error) {
+ ad, _, err := ledger.LookupWithoutRewards(rnd, addr)
+ return convertToOnline(ad), err
+}
+
+// OnlineCirculation just returns a deterministic value for a given round.
+func (ledger *evalTestLedger) OnlineCirculation(rnd, voteRound basics.Round) (basics.MicroAlgos, error) {
+ return basics.MicroAlgos{Raw: uint64(rnd) * 1_000_000}, nil
}
func (ledger *evalTestLedger) LookupApplication(rnd basics.Round, addr basics.Address, aidx basics.AppIndex) (ledgercore.AppResource, error) {
@@ -1057,6 +1021,14 @@ func (l *testCowBaseLedger) LookupWithoutRewards(basics.Round, basics.Address) (
return ledgercore.AccountData{}, basics.Round(0), errors.New("not implemented")
}
+func (l *testCowBaseLedger) LookupAgreement(rnd basics.Round, addr basics.Address) (basics.OnlineAccountData, error) {
+ return basics.OnlineAccountData{}, errors.New("not implemented")
+}
+
+func (l *testCowBaseLedger) OnlineCirculation(rnd, voteRnd basics.Round) (basics.MicroAlgos, error) {
+ return basics.MicroAlgos{}, errors.New("not implemented")
+}
+
func (l *testCowBaseLedger) LookupApplication(rnd basics.Round, addr basics.Address, aidx basics.AppIndex) (ledgercore.AppResource, error) {
return ledgercore.AppResource{}, errors.New("not implemented")
}
diff --git a/ledger/eval/prefetcher/prefetcher_alignment_test.go b/ledger/eval/prefetcher/prefetcher_alignment_test.go
index cb4b165c94..734d84a661 100644
--- a/ledger/eval/prefetcher/prefetcher_alignment_test.go
+++ b/ledger/eval/prefetcher/prefetcher_alignment_test.go
@@ -18,6 +18,7 @@ package prefetcher_test
import (
"context"
+ "errors"
"fmt"
"testing"
@@ -118,6 +119,16 @@ func (l *prefetcherAlignmentTestLedger) LookupWithoutRewards(_ basics.Round, add
}
return ledgercore.AccountData{}, 0, nil
}
+func (l *prefetcherAlignmentTestLedger) LookupAgreement(_ basics.Round, addr basics.Address) (basics.OnlineAccountData, error) {
+ // prefetch alignment tests do not check for prefetching of online account data
+ // because it's quite different and can only occur in AVM opcodes, which
+ // aren't handled anyway (just as we don't know if a holding or app local
+ // will be accessed in AVM.)
+ return basics.OnlineAccountData{}, errors.New("not implemented")
+}
+func (l *prefetcherAlignmentTestLedger) OnlineCirculation(rnd, voteRnd basics.Round) (basics.MicroAlgos, error) {
+ return basics.MicroAlgos{}, errors.New("not implemented")
+}
func (l *prefetcherAlignmentTestLedger) LookupApplication(rnd basics.Round, addr basics.Address, aidx basics.AppIndex) (ledgercore.AppResource, error) {
l.mu.Lock()
if l.requestedApps == nil {
diff --git a/ledger/eval_simple_test.go b/ledger/eval_simple_test.go
index 9ac67d2fb7..972821c26c 100644
--- a/ledger/eval_simple_test.go
+++ b/ledger/eval_simple_test.go
@@ -406,34 +406,84 @@ func TestAbsentTracking(t *testing.T) {
genBalances, addrs, _ := ledgertesting.NewTestGenesis(func(cfg *ledgertesting.GenesisCfg) {
cfg.OnlineCount = 2 // So we know proposer should propose every 2 rounds, on average
- })
+ }, ledgertesting.TurnOffRewards)
+ getOnlineStake := `
+ int 0; voter_params_get VoterBalance; itob; log; itob; log;
+ int 0; voter_params_get VoterIncentiveEligible; itob; log; itob; log;
+ int 1`
+
checkingBegins := 40
- ledgertesting.TestConsensusRange(t, checkingBegins-1, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ ledgertesting.TestConsensusRange(t, checkingBegins, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
dl := NewDoubleLedger(t, genBalances, cv, cfg)
defer dl.Close()
- // have addrs[1] go online, which makes it eligible for suspension
- dl.txn(&txntest.Txn{
+ // we use stakeChecker for testing `voter_params_get` on suspended accounts
+ stib := dl.txn(&txntest.Txn{ // #1
+ Type: "appl",
+ Sender: addrs[3], // use non-online account, Totals unchanged
+ ApprovalProgram: getOnlineStake,
+ })
+ stakeChecker := stib.ApplicationID
+ require.NotZero(t, stakeChecker)
+
+ checkState := func(addr basics.Address, online bool, eligible bool, expected uint64) {
+ t.Helper()
+ if !online {
+ require.Zero(t, expected)
+ }
+ stib = dl.txn(&txntest.Txn{
+ Type: "appl",
+ Sender: addr,
+ ApplicationID: stakeChecker,
+ })
+ logs := stib.ApplyData.EvalDelta.Logs
+ require.Len(t, logs, 4)
+ tBytes := "\x00\x00\x00\x00\x00\x00\x00\x01"
+ fBytes := "\x00\x00\x00\x00\x00\x00\x00\x00"
+ onlBytes := fBytes
+ if online {
+ onlBytes = tBytes
+ }
+ elgBytes := fBytes
+ if eligible {
+ elgBytes = tBytes
+ }
+ require.Equal(t, onlBytes, logs[0], "online")
+ require.Equal(t, int(expected), int(binary.BigEndian.Uint64([]byte(logs[1]))))
+ require.Equal(t, onlBytes, logs[2], "online")
+ require.Equal(t, elgBytes, logs[3], "eligible")
+ }
+
+ // have addrs[1] go online explicitly, which makes it eligible for suspension.
+ // use a large fee, so we can see IncentiveEligible change
+ dl.txn(&txntest.Txn{ // #2
Type: "keyreg",
+ Fee: 10_000_000,
Sender: addrs[1],
VotePK: [32]byte{1},
SelectionPK: [32]byte{1},
})
- totals, err := dl.generator.Totals(1)
- require.NoError(t, err)
- require.NotZero(t, totals.Online.Money.Raw)
-
// as configured above, only the first two accounts should be online
require.True(t, lookup(t, dl.generator, addrs[0]).Status == basics.Online)
require.True(t, lookup(t, dl.generator, addrs[1]).Status == basics.Online)
require.False(t, lookup(t, dl.generator, addrs[2]).Status == basics.Online)
+ checkState(addrs[0], true, false, 833_333_333_333_333) // #3
+ require.Equal(t, int(lookup(t, dl.generator, addrs[0]).MicroAlgos.Raw), 833_333_333_332_333)
+ // although addr[1] just paid to be eligible, it won't be for 320 rounds
+ checkState(addrs[1], true, false, 833_333_333_333_333) // #4
+ checkState(addrs[2], false, false, 0) // #5
+
// genesis accounts don't begin IncentiveEligible, even if online
require.False(t, lookup(t, dl.generator, addrs[0]).IncentiveEligible)
- require.False(t, lookup(t, dl.generator, addrs[1]).IncentiveEligible)
+ // but addr[1] paid extra fee. Note this is _current_ state, not really "online"
+ require.True(t, lookup(t, dl.generator, addrs[1]).IncentiveEligible)
require.False(t, lookup(t, dl.generator, addrs[2]).IncentiveEligible)
- dl.fullBlock()
+ vb := dl.fullBlock() // #6
+ totals, err := dl.generator.Totals(vb.Block().Round())
+ require.NoError(t, err)
+ require.NotZero(t, totals.Online.Money.Raw)
// although it's not even online, we'll use addrs[7] as the proposer
proposer := addrs[7]
@@ -444,18 +494,14 @@ func TestAbsentTracking(t *testing.T) {
Receiver: addrs[2],
Amount: 100_000,
})
- dl.endBlock(proposer)
+ dl.endBlock(proposer) // #7
prp := lookup(t, dl.validator, proposer)
- if ver >= checkingBegins {
- require.Equal(t, prp.LastProposed, dl.validator.Latest())
- } else {
- require.Zero(t, prp.LastProposed)
- }
+ require.Equal(t, prp.LastProposed, dl.validator.Latest())
require.Zero(t, prp.LastHeartbeat)
require.False(t, prp.IncentiveEligible)
- // addr[1] is spent to an offline account, so Online totals decrease
+ // addr[1] paid to an offline account, so Online totals decrease
newtotals, err := dl.generator.Totals(dl.generator.Latest())
require.NoError(t, err)
// payment and fee left the online account
@@ -465,15 +511,15 @@ func TestAbsentTracking(t *testing.T) {
dl.fullBlock()
// addrs[2] was already offline
- dl.txns(&txntest.Txn{Type: "keyreg", Sender: addrs[2]}) // OFFLINE keyreg
+ dl.txns(&txntest.Txn{Type: "keyreg", Sender: addrs[2]}) // OFFLINE keyreg #9
regger := lookup(t, dl.validator, addrs[2])
- // total were unchanged by an offline keyreg from an offline account
+ // totals were unchanged by an offline keyreg from an offline account
newtotals, err = dl.generator.Totals(dl.generator.Latest())
require.NoError(t, err)
require.Equal(t, totals.Online.Money.Raw, newtotals.Online.Money.Raw)
- // an an offline keyreg transaction records no activity
+ // an offline keyreg transaction records no activity
require.Zero(t, regger.LastProposed)
require.Zero(t, regger.LastHeartbeat)
@@ -483,8 +529,8 @@ func TestAbsentTracking(t *testing.T) {
Sender: addrs[2],
VotePK: [32]byte{1},
SelectionPK: [32]byte{1},
- })
- // online totals have grown
+ }) // #10
+ // online totals have grown, addr[2] was added
newtotals, err = dl.generator.Totals(dl.generator.Latest())
require.NoError(t, err)
require.Greater(t, newtotals.Online.Money.Raw, totals.Online.Money.Raw)
@@ -493,27 +539,30 @@ func TestAbsentTracking(t *testing.T) {
require.Zero(t, regger.LastProposed)
require.True(t, regger.Status == basics.Online)
- if ver >= checkingBegins {
- require.NotZero(t, regger.LastHeartbeat) // online keyreg caused update
- } else {
- require.Zero(t, regger.LastHeartbeat)
- }
+ // But nothing has changed, since we're not past 320
+ checkState(addrs[0], true, false, 833_333_333_333_333) // #11
+ checkState(addrs[1], true, false, 833_333_333_333_333) // #12
+ checkState(addrs[2], false, false, 0) // #13
+
+ require.NotZero(t, regger.LastHeartbeat) // online keyreg caused update
require.False(t, regger.IncentiveEligible)
// ONLINE keyreg with extra fee
- dl.txns(&txntest.Txn{
+ vb = dl.fullBlock(&txntest.Txn{
Type: "keyreg",
Fee: 2_000_000,
Sender: addrs[2],
VotePK: [32]byte{1},
SelectionPK: [32]byte{1},
- })
+ }) // #14
+ twoEligible := vb.Block().Round()
+ require.EqualValues(t, 14, twoEligible) // sanity check
regger = lookup(t, dl.validator, addrs[2])
- require.Equal(t, ver >= checkingBegins, regger.IncentiveEligible)
+ require.True(t, regger.IncentiveEligible)
for i := 0; i < 5; i++ {
- dl.fullBlock()
+ dl.fullBlock() // #15-19
require.True(t, lookup(t, dl.generator, addrs[0]).Status == basics.Online)
require.True(t, lookup(t, dl.generator, addrs[1]).Status == basics.Online)
require.True(t, lookup(t, dl.generator, addrs[2]).Status == basics.Online)
@@ -525,7 +574,7 @@ func TestAbsentTracking(t *testing.T) {
require.True(t, lookup(t, dl.generator, addrs[2]).Status == basics.Online)
for i := 0; i < 30; i++ {
- dl.fullBlock()
+ dl.fullBlock() // #20-49
}
// addrs 0-2 all have about 1/3 of stake, so seemingly (see next block
@@ -535,39 +584,46 @@ func TestAbsentTracking(t *testing.T) {
require.Equal(t, basics.Online, lookup(t, dl.generator, addrs[0]).Status)
require.Equal(t, basics.Online, lookup(t, dl.generator, addrs[1]).Status)
require.Equal(t, basics.Online, lookup(t, dl.generator, addrs[2]).Status)
- require.Equal(t, ver >= checkingBegins, lookup(t, dl.generator, addrs[2]).IncentiveEligible)
+ require.True(t, lookup(t, dl.generator, addrs[2]).IncentiveEligible)
- // when 2 pays 0, they both get noticed but addr[0] is not considered absent
- vb := dl.fullBlock(&txntest.Txn{
+ // when 2 pays 0, they both get noticed but addr[0] is not considered
+ // absent because it is a genesis account
+ vb = dl.fullBlock(&txntest.Txn{
Type: "pay",
Sender: addrs[2],
Receiver: addrs[0],
Amount: 0,
- })
- if ver >= checkingBegins {
- require.Equal(t, vb.Block().AbsentParticipationAccounts, []basics.Address{addrs[2]})
- }
+ }) // #50
+ require.Equal(t, vb.Block().AbsentParticipationAccounts, []basics.Address{addrs[2]})
+
+ twoPaysZero := vb.Block().Round()
+ require.EqualValues(t, 50, twoPaysZero)
// addr[0] has never proposed or heartbeat so it is not considered absent
require.Equal(t, basics.Online, lookup(t, dl.generator, addrs[0]).Status)
// addr[1] still hasn't been "noticed"
require.Equal(t, basics.Online, lookup(t, dl.generator, addrs[1]).Status)
- require.Equal(t, ver >= checkingBegins, lookup(t, dl.generator, addrs[2]).Status == basics.Offline)
+ require.Equal(t, basics.Offline, lookup(t, dl.generator, addrs[2]).Status)
require.False(t, lookup(t, dl.generator, addrs[2]).IncentiveEligible)
+ // separate the payments by a few blocks so it will be easier to test
+ // when the changes go into effect
+ for i := 0; i < 4; i++ {
+ dl.fullBlock() // #51-54
+ }
// now, when 2 pays 1, 1 gets suspended (unlike 0, we had 1 keyreg early on, so LastHeartbeat>0)
vb = dl.fullBlock(&txntest.Txn{
Type: "pay",
Sender: addrs[2],
Receiver: addrs[1],
Amount: 0,
- })
- if ver >= checkingBegins {
- require.Equal(t, vb.Block().AbsentParticipationAccounts, []basics.Address{addrs[1]})
- }
+ }) // #55
+ twoPaysOne := vb.Block().Round()
+ require.EqualValues(t, 55, twoPaysOne)
+ require.Equal(t, vb.Block().AbsentParticipationAccounts, []basics.Address{addrs[1]})
require.Equal(t, basics.Online, lookup(t, dl.generator, addrs[0]).Status)
- require.Equal(t, ver >= checkingBegins, lookup(t, dl.generator, addrs[1]).Status == basics.Offline)
+ require.Equal(t, basics.Offline, lookup(t, dl.generator, addrs[1]).Status)
require.False(t, lookup(t, dl.generator, addrs[1]).IncentiveEligible)
- require.Equal(t, ver >= checkingBegins, lookup(t, dl.generator, addrs[2]).Status == basics.Offline)
+ require.Equal(t, basics.Offline, lookup(t, dl.generator, addrs[2]).Status)
require.False(t, lookup(t, dl.generator, addrs[2]).IncentiveEligible)
// now, addrs[2] proposes, so it gets back online, but stays ineligible
@@ -575,6 +631,49 @@ func TestAbsentTracking(t *testing.T) {
dl.fullBlock()
require.Equal(t, basics.Online, lookup(t, dl.generator, addrs[2]).Status)
require.False(t, lookup(t, dl.generator, addrs[2]).IncentiveEligible)
+
+ // "synchronize" so the loop below ends on 320
+ for dl.fullBlock().Block().Round()%4 != 3 {
+ }
+ // keep in mind that each call to checkState also advances the round, so
+ // each loop advances by 4.
+ for rnd := dl.fullBlock().Block().Round(); rnd < 320; rnd = dl.fullBlock().Block().Round() {
+ // STILL nothing has changed, as we're under 320
+ checkState(addrs[0], true, false, 833_333_333_333_333)
+ checkState(addrs[1], true, false, 833_333_333_333_333)
+ checkState(addrs[2], false, false, 0)
+ }
+ // rnd was 320 in the last fullBlock
+
+ // We will soon see effects visible to `vote_params_get`
+ // In first block, addr[3] created an app. No effect on 0-2
+ checkState(addrs[1], true, false, 833_333_333_333_333) // 321
+ // in second block, the checkstate app was created
+ checkState(addrs[1], true, false, 833_333_333_333_333) // 322
+ // addr[1] spent 10A on a fee in rnd 3, so online stake and eligibility adjusted in 323
+ checkState(addrs[1], true, true, 833_333_323_333_333) // 323
+
+ for rnd := dl.fullBlock().Block().Round(); rnd < 320+twoEligible-1; rnd = dl.fullBlock().Block().Round() {
+ }
+ checkState(addrs[2], true, false, 833_333_333_429_333)
+ checkState(addrs[2], true, true, 833_333_331_429_333) // after keyreg w/ 2A is effective
+
+ for rnd := dl.fullBlock().Block().Round(); rnd < 320+twoPaysZero-1; rnd = dl.fullBlock().Block().Round() {
+ }
+ // we're at the round before two's suspension kicks in
+ checkState(addrs[2], true, true, 833_333_331_429_333) // still "online"
+ checkState(addrs[0], true, false, 833_333_333_331_333) // paid fee in #5 and #11, we're at ~371
+ // 2 was noticed & suspended after paying 0, eligible and amount go to 0
+ checkState(addrs[2], false, false, 0)
+ checkState(addrs[0], true, false, 833_333_333_331_333) // addr 0 didn't get suspended (genesis)
+
+ // roughly the same check, except for addr 1, which was genesis, but
+ // after doing a keyreg, became susceptible to suspension
+ for rnd := dl.fullBlock().Block().Round(); rnd < 320+twoPaysOne-1; rnd = dl.fullBlock().Block().Round() {
+ }
+ checkState(addrs[1], true, true, 833_333_323_230_333) // still online, balance irrelevant
+ // 1 was noticed & suspended after being paid by 2, so eligible and amount go to 0
+ checkState(addrs[1], false, false, 0)
})
}
@@ -585,7 +684,9 @@ func TestAbsenteeChallenges(t *testing.T) {
t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis(func(cfg *ledgertesting.GenesisCfg) {
- cfg.OnlineCount = 5 // Make online stake big, so these accounts won't be expected to propose
+ // Get some big accounts online, so the accounts we create here will be
+ // a tiny fraction, not expected to propose often.
+ cfg.OnlineCount = 5
})
checkingBegins := 40
@@ -703,6 +804,105 @@ func TestAbsenteeChallenges(t *testing.T) {
})
}
+// TestVoterAccess ensures that the `voter` opcode works properly when hooked up
+// to a real ledger.
+func TestVoterAccess(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ genBalances, addrs, _ := ledgertesting.NewTestGenesis(
+ ledgertesting.TurnOffRewards,
+ func(cfg *ledgertesting.GenesisCfg) {
+ cfg.OnlineCount = 1 // So that one is online from the start
+ })
+ getOnlineStake := `int 0; voter_params_get VoterBalance; itob; log; itob; log; online_stake; itob; log; int 1`
+
+ // `voter_params_get` introduced in 40
+ ledgertesting.TestConsensusRange(t, 40, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
+
+ stib := dl.txn(&txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: getOnlineStake,
+ })
+ stakeChecker := stib.ApplicationID
+ require.NotZero(t, stakeChecker)
+
+ // have addrs[1] go online, though it won't be visible right away
+ dl.txn(&txntest.Txn{
+ Type: "keyreg",
+ Sender: addrs[1],
+ VotePK: [32]byte{0xaa},
+ SelectionPK: [32]byte{0xbb},
+ })
+
+ one := basics.Address{0xaa, 0x11}
+ two := basics.Address{0xaa, 0x22}
+ three := basics.Address{0xaa, 0x33}
+
+ checkState := func(addr basics.Address, online bool, expected uint64, total uint64) {
+ t.Helper()
+ if !online {
+ require.Zero(t, expected)
+ }
+ stib = dl.txn(&txntest.Txn{
+ Type: "appl",
+ Sender: addr,
+ ApplicationID: stakeChecker,
+ })
+ logs := stib.ApplyData.EvalDelta.Logs
+ require.Len(t, logs, 3)
+ if online {
+ require.Equal(t, "\x00\x00\x00\x00\x00\x00\x00\x01", logs[0])
+ require.Equal(t, int(expected), int(binary.BigEndian.Uint64([]byte(logs[1]))))
+ } else {
+ require.Equal(t, "\x00\x00\x00\x00\x00\x00\x00\x00", logs[0])
+ require.Equal(t, int(expected), int(binary.BigEndian.Uint64([]byte(logs[1]))))
+ }
+ require.Equal(t, int(total), int(binary.BigEndian.Uint64([]byte(logs[2]))))
+ }
+
+ checkState(addrs[0], true, 833_333_333_333_333, 833_333_333_333_333)
+ // checking again because addrs[0] just paid a fee, but we show online balance hasn't changed yet
+ checkState(addrs[0], true, 833_333_333_333_333, 833_333_333_333_333)
+ for i := 1; i < 10; i++ {
+ checkState(addrs[i], false, 0, 833_333_333_333_333)
+ }
+
+ // Fund the new accounts and have them go online.
+ for i, addr := range []basics.Address{one, two, three} {
+ dl.txns(&txntest.Txn{
+ Type: "pay",
+ Sender: addrs[0],
+ Receiver: addr,
+ Amount: (uint64(i) + 1) * 1_000_000_000,
+ }, &txntest.Txn{
+ Type: "keyreg",
+ Sender: addr,
+ VotePK: [32]byte{byte(i + 1)},
+ SelectionPK: [32]byte{byte(i + 1)},
+ })
+ }
+ // they don't have online stake yet
+ for _, addr := range []basics.Address{one, two, three} {
+ checkState(addr, false, 0, 833_333_333_333_333)
+ }
+ for i := 0; i < 320; i++ {
+ dl.fullBlock()
+ }
+ // addr[1] is now visibly online. the total is across all five that are now online, minus various fees paid
+ checkState(addrs[1], true, 833_333_333_333_333-2000, 2*833_333_333_333_333-14000)
+ for i := 2; i < 10; i++ { // addrs[2-9] never came online
+ checkState(addrs[i], false, 0, 2*833_333_333_333_333-14000)
+ }
+ for i, addr := range []basics.Address{one, two, three} {
+ checkState(addr, true, (uint64(i)+1)*1_000_000_000-2000, 2*833_333_333_333_333-14000)
+ }
+ })
+}
+
// TestHoldingGet tests some of the corner cases for the asset_holding_get
// opcode: the asset doesn't exist, the account doesn't exist, account not opted
// in, vs it has none of the asset. This is tested here, even though it should
diff --git a/ledger/evalindexer.go b/ledger/evalindexer.go
deleted file mode 100644
index f83dbb9809..0000000000
--- a/ledger/evalindexer.go
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright (C) 2019-2024 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 (
- "errors"
- "fmt"
-
- "github.com/algorand/go-algorand/config"
- "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/ledger/eval"
- "github.com/algorand/go-algorand/ledger/ledgercore"
-)
-
-// A ledger interface that Indexer implements. This is a simplified version of the
-// LedgerForEvaluator interface. Certain functions that the evaluator doesn't use
-// in the trusting mode are excluded, and the present functions only request data
-// at the latest round. However, functions below can be used for batch querying.
-type indexerLedgerForEval interface {
- LatestBlockHdr() (bookkeeping.BlockHeader, error)
- // The value of the returned map is nil iff the account was not found.
- LookupWithoutRewards(map[basics.Address]struct{}) (map[basics.Address]*ledgercore.AccountData, error)
- // The returned map must have the same structure (elements) as the input map.
- // If a resource is not found, it must be nil in `ledgercore.AccountResource`.
- LookupResources(map[basics.Address]map[Creatable]struct{}) (map[basics.Address]map[Creatable]ledgercore.AccountResource, error)
- GetAssetCreator(map[basics.AssetIndex]struct{}) (map[basics.AssetIndex]FoundAddress, error)
- GetAppCreator(map[basics.AppIndex]struct{}) (map[basics.AppIndex]FoundAddress, error)
- LatestTotals() (ledgercore.AccountTotals, error)
- LookupKv(basics.Round, string) ([]byte, error)
-
- BlockHdr(basics.Round) (bookkeeping.BlockHeader, error)
-}
-
-// FoundAddress is a wrapper for an address and a boolean.
-type FoundAddress struct {
- Address basics.Address
- Exists bool
-}
-
-// EvalForIndexerResources contains resources preloaded from the Indexer database.
-// Indexer is able to do the preloading more efficiently than the evaluator loading
-// resources one by one.
-type EvalForIndexerResources struct {
- // The map value is nil iff the account does not exist. The account data is owned here.
- Accounts map[basics.Address]*ledgercore.AccountData
- Resources map[basics.Address]map[Creatable]ledgercore.AccountResource
- Creators map[Creatable]FoundAddress
-}
-
-// Creatable represent a single creatable object.
-type Creatable struct {
- Index basics.CreatableIndex
- Type basics.CreatableType
-}
-
-// Converter between indexerLedgerForEval and ledgerForEvaluator interfaces.
-type indexerLedgerConnector struct {
- il indexerLedgerForEval
- genesisHash crypto.Digest
- genesisProto config.ConsensusParams
- latestRound basics.Round
- roundResources EvalForIndexerResources
-}
-
-func (l indexerLedgerConnector) FlushCaches() {}
-
-// BlockHdr is part of LedgerForEvaluator interface.
-func (l indexerLedgerConnector) BlockHdr(round basics.Round) (bookkeeping.BlockHeader, error) {
- if round != l.latestRound {
- return bookkeeping.BlockHeader{}, fmt.Errorf(
- "BlockHdr() evaluator called this function for the wrong round %d, "+
- "latest round is %d",
- round, l.latestRound)
- }
- return l.il.LatestBlockHdr()
-}
-
-// 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.
- return errors.New("CheckDup() not implemented")
-}
-
-// LookupWithoutRewards is part of LedgerForEvaluator interface.
-func (l indexerLedgerConnector) LookupWithoutRewards(round basics.Round, address basics.Address) (ledgercore.AccountData, basics.Round, error) {
- // check to see if the account data in the cache.
- if pad, has := l.roundResources.Accounts[address]; has {
- if pad == nil {
- return ledgercore.AccountData{}, round, nil
- }
- return *pad, round, nil
- }
-
- accountDataMap, err := l.il.LookupWithoutRewards(map[basics.Address]struct{}{address: {}})
- if err != nil {
- return ledgercore.AccountData{}, basics.Round(0), err
- }
-
- accountData := accountDataMap[address]
- if accountData == nil {
- return ledgercore.AccountData{}, round, nil
- }
- return *accountData, round, nil
-}
-
-func (l indexerLedgerConnector) LookupApplication(rnd basics.Round, addr basics.Address, aidx basics.AppIndex) (ledgercore.AppResource, error) {
- r, err := l.lookupResource(rnd, addr, basics.CreatableIndex(aidx), basics.AppCreatable)
- return ledgercore.AppResource{AppParams: r.AppParams, AppLocalState: r.AppLocalState}, err
-}
-
-func (l indexerLedgerConnector) LookupAsset(rnd basics.Round, addr basics.Address, aidx basics.AssetIndex) (ledgercore.AssetResource, error) {
- r, err := l.lookupResource(rnd, addr, basics.CreatableIndex(aidx), basics.AssetCreatable)
- return ledgercore.AssetResource{AssetParams: r.AssetParams, AssetHolding: r.AssetHolding}, err
-}
-
-func (l indexerLedgerConnector) lookupResource(round basics.Round, address basics.Address, aidx basics.CreatableIndex, ctype basics.CreatableType) (ledgercore.AccountResource, error) {
- // check to see if the account data in the cache.
- if creatableMap, ok := l.roundResources.Resources[address]; ok {
- if resource, ok := creatableMap[Creatable{aidx, ctype}]; ok {
- return resource, nil
- }
- }
-
- accountResourceMap, err :=
- l.il.LookupResources(map[basics.Address]map[Creatable]struct{}{address: {{aidx, ctype}: {}}})
- if err != nil {
- return ledgercore.AccountResource{}, err
- }
-
- return accountResourceMap[address][Creatable{aidx, ctype}], nil
-}
-
-// LookupKv delegates to the Ledger and marks the box key as touched for post-processing
-func (l indexerLedgerConnector) LookupKv(rnd basics.Round, key string) ([]byte, error) {
- value, err := l.il.LookupKv(rnd, key)
- if err != nil {
- return value, fmt.Errorf("LookupKv() in indexerLedgerConnector internal error: %w", err)
- }
- return value, nil
-}
-
-// GetCreatorForRound is part of LedgerForEvaluator interface.
-func (l indexerLedgerConnector) GetCreatorForRound(_ basics.Round, cindex basics.CreatableIndex, ctype basics.CreatableType) (basics.Address, bool, error) {
- var foundAddress FoundAddress
- var has bool
- // check to see if the account data in the cache.
- if foundAddress, has = l.roundResources.Creators[Creatable{Index: cindex, Type: ctype}]; has {
- return foundAddress.Address, foundAddress.Exists, nil
- }
-
- switch ctype {
- case basics.AssetCreatable:
- foundAddresses, err :=
- l.il.GetAssetCreator(map[basics.AssetIndex]struct{}{basics.AssetIndex(cindex): {}})
- if err != nil {
- return basics.Address{}, false, err
- }
- foundAddress = foundAddresses[basics.AssetIndex(cindex)]
- case basics.AppCreatable:
- foundAddresses, err :=
- l.il.GetAppCreator(map[basics.AppIndex]struct{}{basics.AppIndex(cindex): {}})
- if err != nil {
- return basics.Address{}, false, err
- }
- foundAddress = foundAddresses[basics.AppIndex(cindex)]
- default:
- return basics.Address{}, false, fmt.Errorf("unknown creatable type %v", ctype)
- }
-
- return foundAddress.Address, foundAddress.Exists, nil
-}
-
-// GenesisHash is part of LedgerForEvaluator interface.
-func (l indexerLedgerConnector) GenesisHash() crypto.Digest {
- return l.genesisHash
-}
-
-// GenesisProto is part of LedgerForEvaluator interface.
-func (l indexerLedgerConnector) GenesisProto() config.ConsensusParams {
- return l.genesisProto
-}
-
-// Totals is part of LedgerForEvaluator interface.
-func (l indexerLedgerConnector) LatestTotals() (rnd basics.Round, totals ledgercore.AccountTotals, err error) {
- totals, err = l.il.LatestTotals()
- rnd = l.latestRound
- return
-}
-
-// VotersForStateProof is part of LedgerForEvaluator interface.
-func (l indexerLedgerConnector) VotersForStateProof(_ basics.Round) (*ledgercore.VotersForRound, error) {
- // This function is not used by evaluator.
- return nil, errors.New("VotersForStateProof() not implemented")
-}
-
-// GetStateProofVerificationContext is part of LedgerForEvaluator interface.
-func (l indexerLedgerConnector) GetStateProofVerificationContext(_ basics.Round) (*ledgercore.StateProofVerificationContext, error) {
- return nil, errors.New("GetStateProofVerificationContext() not implemented")
-}
-
-func makeIndexerLedgerConnector(il indexerLedgerForEval, genesisHash crypto.Digest, genesisProto config.ConsensusParams, latestRound basics.Round, roundResources EvalForIndexerResources) indexerLedgerConnector {
- return indexerLedgerConnector{
- il: il,
- genesisHash: genesisHash,
- genesisProto: genesisProto,
- latestRound: latestRound,
- roundResources: roundResources,
- }
-}
-
-// EvalForIndexer evaluates a block without validation using the given `proto`.
-// Return the state delta and transactions with modified apply data according to `proto`.
-// This function is used by Indexer which modifies `proto` to retrieve the asset
-// close amount for each transaction even when the real consensus parameters do not
-// support it.
-func EvalForIndexer(il indexerLedgerForEval, block *bookkeeping.Block, proto config.ConsensusParams, resources EvalForIndexerResources) (ledgercore.StateDelta, []transactions.SignedTxnInBlock, error) {
- ilc := makeIndexerLedgerConnector(il, block.GenesisHash(), proto, block.Round()-1, resources)
-
- eval, err := eval.StartEvaluator(
- ilc, block.BlockHeader,
- eval.EvaluatorOptions{
- PaysetHint: len(block.Payset),
- ProtoParams: &proto,
- Generate: false,
- Validate: false,
- })
- if err != nil {
- return ledgercore.StateDelta{}, []transactions.SignedTxnInBlock{},
- fmt.Errorf("EvalForIndexer() err: %w", err)
- }
-
- return eval.ProcessBlockForIndexer(block)
-}
diff --git a/ledger/evalindexer_test.go b/ledger/evalindexer_test.go
deleted file mode 100644
index c85d5f0275..0000000000
--- a/ledger/evalindexer_test.go
+++ /dev/null
@@ -1,396 +0,0 @@
-// Copyright (C) 2019-2024 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 (
- "errors"
- "fmt"
- "math/rand"
- "testing"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
-
- "github.com/algorand/go-algorand/config"
- "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/txntest"
- "github.com/algorand/go-algorand/ledger/ledgercore"
- ledgertesting "github.com/algorand/go-algorand/ledger/testing"
- "github.com/algorand/go-algorand/logging"
- "github.com/algorand/go-algorand/protocol"
- "github.com/algorand/go-algorand/test/partitiontest"
-)
-
-type indexerLedgerForEvalImpl struct {
- l *Ledger
- latestRound basics.Round
-}
-
-func (il indexerLedgerForEvalImpl) LatestBlockHdr() (bookkeeping.BlockHeader, error) {
- return il.l.BlockHdr(il.latestRound)
-}
-
-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.
-func (il indexerLedgerForEvalImpl) LookupWithoutRewards(addresses map[basics.Address]struct{}) (map[basics.Address]*ledgercore.AccountData, error) {
- res := make(map[basics.Address]*ledgercore.AccountData)
-
- for address := range addresses {
- accountData, _, err := il.l.LookupWithoutRewards(il.latestRound, address)
- if err != nil {
- return nil, err
- }
-
- if accountData.IsZero() {
- res[address] = nil
- } else {
- accountDataCopy := new(ledgercore.AccountData)
- *accountDataCopy = accountData
- res[address] = accountDataCopy
- }
- }
-
- return res, nil
-}
-
-// The value of the returned map is nil iff the account was not found.
-func (il indexerLedgerForEvalImpl) LookupResources(addresses map[basics.Address]map[Creatable]struct{}) (map[basics.Address]map[Creatable]ledgercore.AccountResource, error) {
- res := make(map[basics.Address]map[Creatable]ledgercore.AccountResource)
-
- var err error
- for address, creatables := range addresses {
- for creatable := range creatables {
- c, ok := res[address]
- if !ok {
- c = make(map[Creatable]ledgercore.AccountResource)
- res[address] = c
- }
-
- c[creatable], err =
- il.l.lookupResource(il.latestRound, address, creatable.Index, creatable.Type)
- if err != nil {
- return nil, err
- }
- }
- }
-
- return res, nil
-}
-
-func (il indexerLedgerForEvalImpl) GetAssetCreator(map[basics.AssetIndex]struct{}) (map[basics.AssetIndex]FoundAddress, error) {
- // This function is unused.
- return nil, errors.New("GetAssetCreator() not implemented")
-}
-
-func (il indexerLedgerForEvalImpl) GetAppCreator(map[basics.AppIndex]struct{}) (map[basics.AppIndex]FoundAddress, error) {
- // This function is unused.
- return nil, errors.New("GetAppCreator() not implemented")
-}
-
-func (il indexerLedgerForEvalImpl) LookupKv(basics.Round, string) ([]byte, error) {
- // This function is unused.
- return nil, errors.New("LookupKv() not implemented")
-}
-
-func (il indexerLedgerForEvalImpl) LatestTotals() (totals ledgercore.AccountTotals, err error) {
- _, totals, err = il.l.LatestTotals()
- return
-}
-
-// Test that overriding the consensus parameters effects the generated apply data.
-func TestEvalForIndexerCustomProtocolParams(t *testing.T) {
- partitiontest.PartitionTest(t)
-
- genesisBalances, addrs, _ := ledgertesting.NewTestGenesis()
-
- var genHash crypto.Digest
- crypto.RandBytes(genHash[:])
- block, err := bookkeeping.MakeGenesisBlock(protocol.ConsensusV24,
- genesisBalances, "test", genHash)
- require.NoError(t, err)
-
- dbName := t.Name()
- cfg := config.GetDefaultLocal()
- cfg.Archival = true
- l, err := OpenLedger(logging.Base(), dbName, true, ledgercore.InitState{
- Block: block,
- Accounts: genesisBalances.Balances,
- GenesisHash: genHash,
- }, cfg)
- require.NoError(t, err)
- defer l.Close()
-
- const assetid basics.AssetIndex = 1
- proto := config.Consensus[protocol.ConsensusV24]
-
- block = bookkeeping.MakeBlock(block.BlockHeader)
-
- createTxn := txntest.Txn{
- Type: "acfg",
- Sender: addrs[0],
- GenesisHash: block.GenesisHash(),
- AssetParams: basics.AssetParams{
- Total: 200,
- Decimals: 0,
- Manager: addrs[0],
- Reserve: addrs[0],
- Freeze: addrs[0],
- Clawback: addrs[0],
- },
- }
- createTxn.FillDefaults(proto)
- createStib, err := block.BlockHeader.EncodeSignedTxn(
- createTxn.SignedTxn(), transactions.ApplyData{})
- require.NoError(t, err)
-
- optInTxn := txntest.Txn{
- Type: "axfer",
- Sender: addrs[1],
- GenesisHash: block.GenesisHash(),
- XferAsset: assetid,
- AssetAmount: 0,
- AssetReceiver: addrs[1],
- }
- optInTxn.FillDefaults(proto)
- optInStib, err := block.BlockHeader.EncodeSignedTxn(
- optInTxn.SignedTxn(), transactions.ApplyData{})
- require.NoError(t, err)
-
- fundTxn := txntest.Txn{
- Type: "axfer",
- Sender: addrs[0],
- GenesisHash: block.GenesisHash(),
- XferAsset: assetid,
- AssetAmount: 100,
- AssetReceiver: addrs[1],
- }
- fundTxn.FillDefaults(proto)
- fundStib, err := block.BlockHeader.EncodeSignedTxn(
- fundTxn.SignedTxn(), transactions.ApplyData{})
- require.NoError(t, err)
-
- optOutTxn := txntest.Txn{
- Type: "axfer",
- Sender: addrs[1],
- GenesisHash: block.GenesisHash(),
- XferAsset: assetid,
- AssetAmount: 30,
- AssetReceiver: addrs[0],
- AssetCloseTo: addrs[0],
- }
- optOutTxn.FillDefaults(proto)
- optOutStib, err := block.BlockHeader.EncodeSignedTxn(
- optOutTxn.SignedTxn(), transactions.ApplyData{})
- require.NoError(t, err)
-
- block.Payset = []transactions.SignedTxnInBlock{
- createStib, optInStib, fundStib, optOutStib,
- }
-
- il := indexerLedgerForEvalImpl{
- l: l,
- latestRound: 0,
- }
- proto.EnableAssetCloseAmount = true
- _, modifiedTxns, err := EvalForIndexer(il, &block, proto, EvalForIndexerResources{})
- require.NoError(t, err)
-
- require.Equal(t, 4, len(modifiedTxns))
- assert.Equal(t, uint64(70), modifiedTxns[3].AssetClosingAmount)
-}
-
-// TestEvalForIndexerForExpiredAccounts tests that the EvalForIndexer function will correctly mark accounts offline
-func TestEvalForIndexerForExpiredAccounts(t *testing.T) {
- partitiontest.PartitionTest(t)
-
- genesisBalances, addrs, _ := ledgertesting.NewTestGenesis()
-
- var genHash crypto.Digest
- crypto.RandBytes(genHash[:])
- block, err := bookkeeping.MakeGenesisBlock(protocol.ConsensusFuture,
- genesisBalances, "test", genHash)
- require.NoError(t, err)
-
- dbName := t.Name()
- cfg := config.GetDefaultLocal()
- cfg.Archival = true
- l, err := OpenLedger(logging.Base(), dbName, true, ledgercore.InitState{
- Block: block,
- Accounts: genesisBalances.Balances,
- GenesisHash: genHash,
- }, cfg)
- require.NoError(t, err)
- defer l.Close()
-
- proto := config.Consensus[protocol.ConsensusFuture]
-
- block = bookkeeping.MakeBlock(block.BlockHeader)
-
- il := indexerLedgerForEvalImpl{
- l: l,
- latestRound: 0,
- }
-
- _, _, err = EvalForIndexer(il, &block, proto, EvalForIndexerResources{})
- require.NoError(t, err)
-
- badBlock := block
- // First validate that bad block is fine if we dont touch it...
- _, _, err = EvalForIndexer(il, &badBlock, proto, EvalForIndexerResources{})
- require.NoError(t, err)
-
- // Introduce an unknown address, but this time the Eval function is called with parameters that
- // don't necessarily mean that this will cause an error. Just that an empty address will be added
- badBlock.ExpiredParticipationAccounts = append(badBlock.ExpiredParticipationAccounts, basics.Address{123})
-
- _, _, err = EvalForIndexer(il, &badBlock, proto, EvalForIndexerResources{})
- require.NoError(t, err)
-
- badBlock = block
-
- // Now we add way too many accounts which will cause resetExpiredOnlineAccountsParticipationKeys() to fail
- addressToCopy := addrs[0]
-
- for i := 0; i < proto.MaxProposedExpiredOnlineAccounts+1; i++ {
- badBlock.ExpiredParticipationAccounts = append(badBlock.ExpiredParticipationAccounts, addressToCopy)
- }
-
- _, _, err = EvalForIndexer(il, &badBlock, proto, EvalForIndexerResources{})
- require.Error(t, err)
-
- // Sanity Check
-
- badBlock = block
-
- _, _, err = EvalForIndexer(il, &badBlock, proto, EvalForIndexerResources{})
- require.NoError(t, err)
-}
-
-func newTestLedger(t testing.TB, balances bookkeeping.GenesisBalances) *Ledger {
- var genHash crypto.Digest
- crypto.RandBytes(genHash[:])
- genBlock, err := bookkeeping.MakeGenesisBlock(protocol.ConsensusFuture, balances, "test", genHash)
- require.NoError(t, err)
- require.False(t, genBlock.FeeSink.IsZero())
- require.False(t, genBlock.RewardsPool.IsZero())
- dbName := fmt.Sprintf("%s.%d", t.Name(), crypto.RandUint64())
- cfg := config.GetDefaultLocal()
- cfg.Archival = true
- l, err := OpenLedger(logging.Base(), dbName, true, ledgercore.InitState{
- Block: genBlock,
- Accounts: balances.Balances,
- GenesisHash: genHash,
- }, cfg)
- require.NoError(t, err)
- return l
-}
-
-// Test that preloading data in cow base works as expected.
-func TestResourceCaching(t *testing.T) {
- partitiontest.PartitionTest(t)
-
- var address basics.Address
- _, err := rand.Read(address[:])
- require.NoError(t, err)
-
- creatable := Creatable{
- Index: basics.CreatableIndex(7),
- Type: basics.AssetCreatable,
- }
-
- genesisInitState, _, _ := ledgertesting.GenesisWithProto(10, protocol.ConsensusFuture)
-
- genesisBalances := bookkeeping.GenesisBalances{
- Balances: genesisInitState.Accounts,
- FeeSink: testSinkAddr,
- RewardsPool: testPoolAddr,
- Timestamp: 0,
- }
- l := newTestLedger(t, genesisBalances)
- defer l.Close()
-
- genesisBlockHeader, err := l.BlockHdr(basics.Round(0))
- require.NoError(t, err)
- block := bookkeeping.MakeBlock(genesisBlockHeader)
-
- resources := EvalForIndexerResources{
- Accounts: map[basics.Address]*ledgercore.AccountData{
- address: {
- AccountBaseData: ledgercore.AccountBaseData{
- MicroAlgos: basics.MicroAlgos{Raw: 5},
- },
- },
- },
- Resources: map[basics.Address]map[Creatable]ledgercore.AccountResource{
- address: {
- creatable: {
- AssetParams: &basics.AssetParams{
- Total: 8,
- },
- AssetHolding: &basics.AssetHolding{
- Amount: 9,
- },
- },
- },
- },
- Creators: map[Creatable]FoundAddress{
- {Index: basics.CreatableIndex(6), Type: basics.AssetCreatable}: {Address: address, Exists: true},
- {Index: basics.CreatableIndex(6), Type: basics.AppCreatable}: {Address: address, Exists: false},
- },
- }
-
- proto := config.Consensus[protocol.ConsensusFuture]
- ilc := makeIndexerLedgerConnector(indexerLedgerForEvalImpl{l: l, latestRound: basics.Round(0)}, block.GenesisHash(), proto, block.Round()-1, resources)
-
- {
- accountData, rnd, err := ilc.LookupWithoutRewards(basics.Round(0), address)
- require.NoError(t, err)
- assert.Equal(t, ledgercore.AccountData{AccountBaseData: ledgercore.AccountBaseData{MicroAlgos: basics.MicroAlgos{Raw: 5}}}, accountData)
- assert.Equal(t, basics.Round(0), rnd)
- }
- {
- accountResource, err := ilc.LookupAsset(
- basics.Round(0), address, basics.AssetIndex(7))
- require.NoError(t, err)
- expected := ledgercore.AssetResource{
- AssetParams: &basics.AssetParams{
- Total: 8,
- },
- AssetHolding: &basics.AssetHolding{
- Amount: 9,
- },
- }
- assert.Equal(t, expected, accountResource)
- }
- {
- address, found, err := ilc.GetCreatorForRound(basics.Round(0), basics.CreatableIndex(6), basics.AssetCreatable)
- require.NoError(t, err)
- require.True(t, found)
- assert.Equal(t, address, address)
- }
- {
- _, found, err := ilc.GetCreatorForRound(basics.Round(0), basics.CreatableIndex(6), basics.AppCreatable)
- require.NoError(t, err)
- require.False(t, found)
- }
-}
diff --git a/ledger/tracker.go b/ledger/tracker.go
index 6d976a9763..d99f997ebe 100644
--- a/ledger/tracker.go
+++ b/ledger/tracker.go
@@ -908,6 +908,14 @@ func (aul *accountUpdatesLedgerEvaluator) LookupWithoutRewards(rnd basics.Round,
return data, validThrough, err
}
+func (aul *accountUpdatesLedgerEvaluator) LookupAgreement(rnd basics.Round, addr basics.Address) (basics.OnlineAccountData, error) {
+ return aul.ao.LookupOnlineAccountData(rnd, addr)
+}
+
+func (aul *accountUpdatesLedgerEvaluator) OnlineCirculation(rnd basics.Round, voteRnd basics.Round) (basics.MicroAlgos, error) {
+ return aul.ao.onlineCirculation(rnd, voteRnd)
+}
+
func (aul *accountUpdatesLedgerEvaluator) LookupApplication(rnd basics.Round, addr basics.Address, aidx basics.AppIndex) (ledgercore.AppResource, error) {
r, _, err := aul.au.lookupResource(rnd, addr, basics.CreatableIndex(aidx), basics.AppCreatable, false /* don't sync */)
return ledgercore.AppResource{AppParams: r.AppParams, AppLocalState: r.AppLocalState}, err
diff --git a/logging/log.go b/logging/log.go
index d9b79eb9aa..48f83c1b9e 100644
--- a/logging/log.go
+++ b/logging/log.go
@@ -308,7 +308,7 @@ func (l logger) SetOutput(w io.Writer) {
}
func (l logger) setOutput(w io.Writer) {
- l.entry.Logger.Out = w
+ l.entry.Logger.SetOutput(w)
}
func (l logger) getOutput() io.Writer {
diff --git a/netdeploy/remote/deployedNetwork.go b/netdeploy/remote/deployedNetwork.go
index 729409fe94..25de422026 100644
--- a/netdeploy/remote/deployedNetwork.go
+++ b/netdeploy/remote/deployedNetwork.go
@@ -75,12 +75,12 @@ type DeployedNetworkConfig struct {
// DeployedNetwork represents the complete configuration specification for a deployed network
type DeployedNetwork struct {
- useExistingGenesis bool
- createBoostrappedNetwork bool
- GenesisData gen.GenesisData
- Topology topology
- Hosts []HostConfig
- BootstrappedNet BootstrappedNetwork
+ useExistingGenesis bool
+ createBootstrappedNetwork bool
+ GenesisData gen.GenesisData
+ Topology topology
+ Hosts []HostConfig
+ BootstrappedNet BootstrappedNetwork
}
type netState struct {
@@ -253,12 +253,12 @@ func (cfg *DeployedNetwork) SetUseExistingGenesisFiles(useExisting bool) bool {
return old
}
-// SetUseBoostrappedFiles sets the override flag indicating we should use existing genesis
+// SetUseBootstrappedFiles sets the override flag indicating we should use existing genesis
// files instead of generating new ones. This is useful for permanent networks like devnet and testnet.
// Returns the previous value.
-func (cfg *DeployedNetwork) SetUseBoostrappedFiles(boostrappedFile bool) bool {
- old := cfg.createBoostrappedNetwork
- cfg.createBoostrappedNetwork = boostrappedFile
+func (cfg *DeployedNetwork) SetUseBootstrappedFiles(bootstrappedFile bool) bool {
+ old := cfg.createBootstrappedNetwork
+ cfg.createBootstrappedNetwork = bootstrappedFile
return old
}
@@ -346,7 +346,7 @@ func (cfg DeployedNetwork) BuildNetworkFromTemplate(buildCfg BuildConfig, rootDi
return
}
- if cfg.createBoostrappedNetwork {
+ if cfg.createBootstrappedNetwork {
fmt.Println("Generating db files ")
cfg.GenerateDatabaseFiles(cfg.BootstrappedNet, genesisFolder)
diff --git a/network/wsNetwork.go b/network/wsNetwork.go
index 295bd71155..9c203d8839 100644
--- a/network/wsNetwork.go
+++ b/network/wsNetwork.go
@@ -1147,6 +1147,8 @@ func (wn *msgHandler) messageHandlerThread(wg *sync.WaitGroup, peersConnectivity
networkIncomingBufferMicros.AddUint64(uint64(bufferNanos/1000), nil)
handleTime := handled.Sub(start)
networkHandleMicros.AddUint64(uint64(handleTime.Nanoseconds()/1000), nil)
+ networkHandleMicrosByTag.Add(string(msg.Tag), uint64(handleTime.Nanoseconds()/1000))
+ networkHandleCountByTag.Add(string(msg.Tag), 1)
switch outmsg.Action {
case Disconnect:
wg.Add(1)
diff --git a/network/wsPeer.go b/network/wsPeer.go
index adf211f592..c4b64bdec4 100644
--- a/network/wsPeer.go
+++ b/network/wsPeer.go
@@ -63,6 +63,8 @@ func init() {
networkReceivedBytesByTag = metrics.NewTagCounterFiltered("algod_network_received_bytes_{TAG}", "Number of bytes that were received from the network for {TAG} messages", tagStringList, "UNK")
networkMessageReceivedByTag = metrics.NewTagCounterFiltered("algod_network_message_received_{TAG}", "Number of complete messages that were received from the network for {TAG} messages", tagStringList, "UNK")
networkMessageSentByTag = metrics.NewTagCounterFiltered("algod_network_message_sent_{TAG}", "Number of complete messages that were sent to the network for {TAG} messages", tagStringList, "UNK")
+ networkHandleCountByTag = metrics.NewTagCounterFiltered("algod_network_rx_handle_countbytag_{TAG}", "count of handler calls in the receive thread for {TAG} messages", tagStringList, "UNK")
+ networkHandleMicrosByTag = metrics.NewTagCounterFiltered("algod_network_rx_handle_microsbytag_{TAG}", "microseconds spent by protocol handlers in the receive thread for {TAG} messages", tagStringList, "UNK")
matched := false
for _, version := range SupportedProtocolVersions {
@@ -91,6 +93,9 @@ var networkMessageReceivedByTag *metrics.TagCounter
var networkMessageSentTotal = metrics.MakeCounter(metrics.NetworkMessageSentTotal)
var networkMessageSentByTag *metrics.TagCounter
+var networkHandleMicrosByTag *metrics.TagCounter
+var networkHandleCountByTag *metrics.TagCounter
+
var networkConnectionsDroppedTotal = metrics.MakeCounter(metrics.NetworkConnectionsDroppedTotal)
var networkMessageQueueMicrosTotal = metrics.MakeCounter(metrics.MetricName{Name: "algod_network_message_sent_queue_micros_total", Description: "Total microseconds message spent waiting in queue to be sent"})
diff --git a/test/heapwatch/requirements.txt b/test/heapwatch/requirements.txt
index 9743ce85c1..d4d68874dd 100644
--- a/test/heapwatch/requirements.txt
+++ b/test/heapwatch/requirements.txt
@@ -1,6 +1,6 @@
dash==2.15.0
dash-table==5.0.0
-Jinja2==3.1.3
+Jinja2==3.1.4
matplotlib==3.7.2
plotly==5.16.0
py-algorand-sdk==2.3.0
diff --git a/test/packages/test_release.sh b/test/packages/test_release.sh
index 1a66184eb2..e92f52e459 100755
--- a/test/packages/test_release.sh
+++ b/test/packages/test_release.sh
@@ -15,11 +15,12 @@ then
fi
OS_LIST=(
- centos:7
- quay.io/centos/centos:stream8
- fedora:38
+ quay.io/centos/centos:stream9
+ fedora:39
+ fedora:40
ubuntu:20.04
ubuntu:22.04
+ ubuntu:24.04
)
BUCKET=algorand-builds
@@ -68,7 +69,8 @@ EOF
then
WITH_PACMAN=$(echo -e "${TOKENIZED//\{\{PACMAN\}\}/RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y curl}")
else
- WITH_PACMAN=$(echo -e "${TOKENIZED//\{\{PACMAN\}\}/RUN yum install -y curl}")
+ # fedora and centos already have curl installed.
+ WITH_PACMAN=$(echo -e "${TOKENIZED//\{\{PACMAN\}\}/}")
fi
echo -e "$BLUE_FG[$0]$END_FG_COLOR Testing $item..."
diff --git a/test/scripts/e2e_client_runner.py b/test/scripts/e2e_client_runner.py
index 3d5888696f..2ff7f876cc 100755
--- a/test/scripts/e2e_client_runner.py
+++ b/test/scripts/e2e_client_runner.py
@@ -106,7 +106,7 @@ def _script_thread_inner(runset, scriptname, timeout):
# create a wallet for the test
walletname = base64.b16encode(os.urandom(16)).decode()
- winfo = kmd.create_wallet(walletname, '')
+ winfo = kmd.create_wallet(walletname, '', timeout=120) # 2 minute timeout
handle = kmd.init_wallet_handle(winfo['id'], '')
addr = kmd.generate_key(handle)
diff --git a/test/scripts/e2e_subs/goal/goal.py b/test/scripts/e2e_subs/goal/goal.py
index 57d8b0acb5..c68c8cdc79 100755
--- a/test/scripts/e2e_subs/goal/goal.py
+++ b/test/scripts/e2e_subs/goal/goal.py
@@ -121,8 +121,8 @@ def open_wallet(self, name):
wallet = w
assert wallet, f"No wallet named '{name}'"
- self.handle = self.kmd.init_wallet_handle(wallet["id"], "")
- keys = self.kmd.list_keys(self.handle)
+ self.handle = self.kmd.init_wallet_handle(wallet["id"], "", timeout=120)
+ keys = self.kmd.list_keys(self.handle, timeout=120)
assert len(keys) == 1
self.account = keys[0]
diff --git a/test/scripts/e2e_subs/htlc-teal-test.sh b/test/scripts/e2e_subs/htlc-teal-test.sh
index d2b70c533d..617e51d5cc 100755
--- a/test/scripts/e2e_subs/htlc-teal-test.sh
+++ b/test/scripts/e2e_subs/htlc-teal-test.sh
@@ -46,8 +46,9 @@ ${gcmd} clerk send --fee=1000 --from-program ${TEMPDIR}/atomic.teal -a=0 -t=${ZE
# Check balance
BALANCEB=$(${gcmd} account balance -a ${ACCOUNTB} | awk '{ print $1 }')
-if [ $BALANCEB -ne 9999000 ]; then
- date "+htlc-teal-test FAIL wanted balance=9999000 but got ${BALANCEB} %Y%m%d_%H%M%S"
+# Use >= 9999000 to account for rewards which may have accumulated
+if [ $BALANCEB -lt 9999000 ]; then
+ date "+htlc-teal-test FAIL wanted balance>=9999000 but got ${BALANCEB} %Y%m%d_%H%M%S"
false
fi
diff --git a/test/testdata/deployednettemplates/recipes/bootstrappedScenario/Makefile b/test/testdata/deployednettemplates/recipes/bootstrappedScenario/Makefile
index f5db1ebbc1..4611e30ed2 100644
--- a/test/testdata/deployednettemplates/recipes/bootstrappedScenario/Makefile
+++ b/test/testdata/deployednettemplates/recipes/bootstrappedScenario/Makefile
@@ -2,7 +2,7 @@
PARAMS=-w 20 -R 8 -N 20 -n 20 --npn-algod-nodes 10 --node-template node.json --relay-template relay.json --non-participating-node-template nonPartNode.json --last-part-key-round 50000
FILEPARAMS=--rounds 1600 --ntxns 20000 --naccounts 30000000 --nassets 20000 --napps 20000 --wallet-name "wallet1" --bal 50000000 --bal 50000001 --deterministic
-all: net.json genesis.json topology.json boostrappedFile.json
+all: net.json genesis.json topology.json bootstrappedFile.json
net.json: node.json nonPartNode.json ${GOPATH}/bin/netgoal Makefile
netgoal generate -t net -r /tmp/wat -o net.json ${PARAMS}
@@ -15,8 +15,8 @@ genesis.json: ${GOPATH}/bin/netgoal Makefile
topology.json: gen_topology.py
python3 gen_topology.py
-boostrappedFile.json: ${GOPATH}/bin/netgoal Makefile
- netgoal generate -t loadingFile -r /tmp/wat -o boostrappedFile.json ${FILEPARAMS}
+bootstrappedFile.json: ${GOPATH}/bin/netgoal Makefile
+ netgoal generate -t loadingFile -r /tmp/wat -o bootstrappedFile.json ${FILEPARAMS}
clean:
rm -f net.json genesis.json
diff --git a/test/testdata/deployednettemplates/recipes/bootstrappedScenario/recipe.json b/test/testdata/deployednettemplates/recipes/bootstrappedScenario/recipe.json
index 766328dbb3..55805a6eb9 100644
--- a/test/testdata/deployednettemplates/recipes/bootstrappedScenario/recipe.json
+++ b/test/testdata/deployednettemplates/recipes/bootstrappedScenario/recipe.json
@@ -1,8 +1,8 @@
{
- "GenesisFile":"genesis.json",
- "NetworkFile":"net.json",
- "ConfigFile": "../../configs/reference.json",
- "HostTemplatesFile": "../../hosttemplates/hosttemplates.json",
- "TopologyFile": "topology.json",
- "BootstrappedFile": "boostrappedFile.json"
+ "GenesisFile": "genesis.json",
+ "NetworkFile": "net.json",
+ "ConfigFile": "../../configs/reference.json",
+ "HostTemplatesFile": "../../hosttemplates/hosttemplates.json",
+ "TopologyFile": "topology.json",
+ "BootstrappedFile": "bootstrappedFile.json"
}
diff --git a/test/testdata/deployednettemplates/recipes/scenario1s/Makefile b/test/testdata/deployednettemplates/recipes/scenario1s/Makefile
index f4b1910906..ed8a70132e 100644
--- a/test/testdata/deployednettemplates/recipes/scenario1s/Makefile
+++ b/test/testdata/deployednettemplates/recipes/scenario1s/Makefile
@@ -1,7 +1,7 @@
# scenario1s is scenario1 but smaller, (100 nodes, 100 wallets) -> (20 nodes, 20 wallets), each algod gets single tenancy on a smaller ec2 instance
PARAMS=-w 20 -R 8 -N 20 -n 20 --npn-algod-nodes 10 --node-template node.json --relay-template relay.json --non-participating-node-template nonPartNode.json
-all: net.json genesis.json topology.json boostrappedFile.json
+all: net.json genesis.json topology.json bootstrappedFile.json
net.json: node.json nonPartNode.json ${GOPATH}/bin/netgoal Makefile
netgoal generate -t net -r /tmp/wat -o net.json ${PARAMS}
diff --git a/tools/block-generator/go.mod b/tools/block-generator/go.mod
index 29bdbdb4e8..cfeb442668 100644
--- a/tools/block-generator/go.mod
+++ b/tools/block-generator/go.mod
@@ -125,12 +125,12 @@ require (
go.uber.org/mock v0.4.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
- golang.org/x/crypto v0.19.0 // indirect
+ golang.org/x/crypto v0.21.0 // indirect
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect
golang.org/x/mod v0.15.0 // indirect
- golang.org/x/net v0.21.0 // indirect
+ golang.org/x/net v0.23.0 // indirect
golang.org/x/sync v0.6.0 // indirect
- golang.org/x/sys v0.17.0 // indirect
+ golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.18.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
diff --git a/tools/block-generator/go.sum b/tools/block-generator/go.sum
index e34dae4485..dbd7cdeb72 100644
--- a/tools/block-generator/go.sum
+++ b/tools/block-generator/go.sum
@@ -541,8 +541,8 @@ golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
-golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
+golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
+golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
@@ -582,8 +582,8 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
-golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
+golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -629,8 +629,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
-golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
+golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/tools/network/cloudflare/createRecord.go b/tools/network/cloudflare/createRecord.go
index efaa840575..d115e8b059 100644
--- a/tools/network/cloudflare/createRecord.go
+++ b/tools/network/cloudflare/createRecord.go
@@ -38,11 +38,9 @@ type createDNSRecord struct {
// https://community.cloudflare.com/t/cloudflare-api-v4-srv-dns-creation-failure-in-php/25677/7
type createSRVRecord struct {
Type string `json:"type"`
+ Name string `json:"name"`
Data struct {
- Name string `json:"name"`
TTL uint `json:"ttl"`
- Service string `json:"service"`
- Proto string `json:"proto"`
Weight uint `json:"weight"`
Port uint `json:"port"`
Priority uint `json:"priority"`
@@ -90,10 +88,8 @@ func createSRVRecordRequest(zoneID string, authToken string, name string, servic
requestJSON := createSRVRecord{
Type: "SRV",
}
- requestJSON.Data.Name = name
+ requestJSON.Name = service + "." + protocol + "." + name
requestJSON.Data.TTL = ttl
- requestJSON.Data.Service = service
- requestJSON.Data.Proto = protocol
requestJSON.Data.Weight = weight
requestJSON.Data.Port = port
requestJSON.Data.Priority = priority
diff --git a/tools/network/cloudflare/updateRecord.go b/tools/network/cloudflare/updateRecord.go
index 269c48f11a..7ad2b188f1 100644
--- a/tools/network/cloudflare/updateRecord.go
+++ b/tools/network/cloudflare/updateRecord.go
@@ -63,11 +63,9 @@ func updateSRVRecordRequest(zoneID string, authToken string, recordID string, na
requestJSON := createSRVRecord{
Type: "SRV",
+ Name: fmt.Sprintf("%s.%s.%s", service, protocol, name),
}
- requestJSON.Data.Name = name
requestJSON.Data.TTL = ttl
- requestJSON.Data.Service = service
- requestJSON.Data.Proto = protocol
requestJSON.Data.Weight = weight
requestJSON.Data.Port = port
requestJSON.Data.Priority = priority