diff --git a/.codecov.yml b/.codecov.yml
index def78dc007..691bb6d2f4 100644
--- a/.codecov.yml
+++ b/.codecov.yml
@@ -1,10 +1,15 @@
codecov:
require_ci_to_pass: yes
+flags:
+ full_coverage:
+ joined: false
+
ignore:
- "**/*_gen.go"
- "**/*_gen_test.go"
- "**/generated"
+ - "**/*_string.go" # ignore stringer-generated code
coverage:
status:
diff --git a/.custom-gcl.yml b/.custom-gcl.yml
index 0d2860a229..e1d7f3ccc8 100644
--- a/.custom-gcl.yml
+++ b/.custom-gcl.yml
@@ -8,3 +8,6 @@ plugins:
- module: fillmore-labs.com/errortype
import: fillmore-labs.com/errortype/gclplugin
version: v0.0.7
+ - module: github.com/cce/docnametypo
+ import: github.com/cce/docnametypo/gclplugin
+ version: v0.2.0
diff --git a/.github/actions/setup-test/action.yml b/.github/actions/setup-test/action.yml
index 142fe8cc0a..950bc1f303 100644
--- a/.github/actions/setup-test/action.yml
+++ b/.github/actions/setup-test/action.yml
@@ -28,13 +28,3 @@ runs:
sudo dpkg-reconfigure -f noninteractive man-db
sudo apt-get install -y --no-upgrade expect
shell: bash
- - name: Cache gotestsum
- id: cache-gotestsum
- uses: actions/cache@v4
- with:
- path: ~/go/bin/gotestsum
- key: gotestsum-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('scripts/buildtools/versions') }}
- - name: Install gotestsum
- if: steps.cache-gotestsum.outputs.cache-hit != 'true'
- run: ./scripts/buildtools/install_buildtools.sh -o "gotest.tools/gotestsum"
- shell: bash
diff --git a/.github/workflows/ci-nightly.yml b/.github/workflows/ci-nightly.yml
index c1a821cfbb..577953ef5d 100644
--- a/.github/workflows/ci-nightly.yml
+++ b/.github/workflows/ci-nightly.yml
@@ -102,15 +102,16 @@ jobs:
- name: Run tests
run: |
./scripts/configure_dev.sh
- ./scripts/buildtools/install_buildtools.sh -o "gotest.tools/gotestsum"
PACKAGES="$(go list ./... | grep -v /go-algorand/test/)"
- export PACKAGE_NAMES=$(echo $PACKAGES | tr -d '\n')
+ export PACKAGE_NAMES=$(echo $PACKAGES | tr -d '\n')
+ COVERPACKAGES="$(go list ./... | grep -E -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | grep -E -v '(test|testing|mock|mocks)$' | paste -sd ',' -)"
mkdir -p test_results/${{ matrix.platform }}_test_nightly/${PARTITION_ID}
- gotestsum --format standard-quiet \
+ go tool -modfile=tool.mod gotestsum --format standard-quiet \
--junitfile ~/test_results/${{ matrix.platform }}_test_nightly/${PARTITION_ID}/results.xml \
--jsonfile ~/test_results/${{ matrix.platform }}_test_nightly/${PARTITION_ID}/testresults.json \
-- --tags "sqlite_unlock_notify sqlite_omit_load_extension" \
-race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 1 \
+ -coverpkg=$COVERPACKAGES \
$PACKAGE_NAMES
- name: Notify Slack on failure
if: failure()
@@ -143,6 +144,7 @@ jobs:
with:
token: ${{ env.CODECOV_TOKEN }}
file: ./coverage.txt
+ flags: full_coverage
fail_ci_if_error: false
- name: Upload test results to Codecov
if: ${{ !cancelled() }}
@@ -184,7 +186,6 @@ jobs:
- name: Run integration tests
run: |
./scripts/configure_dev.sh
- ./scripts/buildtools/install_buildtools.sh -o "gotest.tools/gotestsum"
mkdir -p ~/test_results/${{ matrix.platform }}_integration_nightly/${PARTITION_ID}
TEST_RESULTS=~/test_results/${{ matrix.platform }}_integration_nightly/${PARTITION_ID} \
test/scripts/run_integration_tests.sh
@@ -241,7 +242,6 @@ jobs:
- name: Run E2E expect tests
run: |
scripts/configure_dev.sh
- scripts/buildtools/install_buildtools.sh -o "gotest.tools/gotestsum"
mkdir -p ~/test_results/${{ matrix.platform }}_e2e_expect_nightly/${PARTITION_ID}
TEST_RESULTS=~/test_results/${{ matrix.platform }}_e2e_expect_nightly/${PARTITION_ID} \
test/scripts/run_integration_tests.sh
@@ -308,7 +308,6 @@ jobs:
- name: Run E2E subs tests
run: |
scripts/configure_dev.sh
- scripts/buildtools/install_buildtools.sh -o "gotest.tools/gotestsum"
mkdir -p ~/test_results/${{ matrix.platform }}_e2e_subs_nightly
TEST_RESULTS=~/test_results/${{ matrix.platform }}_e2e_subs_nightly \
test/scripts/run_integration_tests.sh
diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml
index 18bccfb797..876215417a 100644
--- a/.github/workflows/ci-pr.yml
+++ b/.github/workflows/ci-pr.yml
@@ -4,6 +4,13 @@ on:
branches:
- master
- 'rel/**'
+ workflow_dispatch:
+ inputs:
+ full_coverage:
+ description: 'Run with -coverpkg to measure cross-package coverage (slower)'
+ required: false
+ type: boolean
+ default: false
env:
CODECOV_TOKEN: "8b4a1f91-f154-4c26-b84c-c9aaa90159c6" # Same public token from CircleCI config
@@ -49,13 +56,19 @@ jobs:
- name: Run tests
run: |
PACKAGES="$(go list ./... | grep -v /go-algorand/test/)"
- export PACKAGE_NAMES=$(echo $PACKAGES | tr -d '\n')
+ export PACKAGE_NAMES=$(echo $PACKAGES | tr -d '\n')
+ COVERPKG_FLAG=""
+ if [[ "${{ inputs.full_coverage }}" == "true" ]]; then
+ COVERPACKAGES="$(go list ./... | grep -E -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | grep -E -v '(test|testing|mock|mocks)$' | paste -sd ',' -)"
+ COVERPKG_FLAG="-coverpkg=$COVERPACKAGES"
+ fi
mkdir -p test_results/${{ matrix.platform }}_test/${PARTITION_ID}
- gotestsum --format standard-quiet \
+ go tool -modfile=tool.mod gotestsum --format standard-quiet \
--junitfile ~/test_results/${{ matrix.platform }}_test/${PARTITION_ID}/results.xml \
--jsonfile ~/test_results/${{ matrix.platform }}_test/${PARTITION_ID}/testresults.json \
-- --tags "sqlite_unlock_notify sqlite_omit_load_extension" $SHORTTEST \
-race -timeout 1h -coverprofile=coverage.txt -covermode=atomic -p 4 \
+ $COVERPKG_FLAG \
$PACKAGE_NAMES
- name: Notify Slack on failure
if: failure()
@@ -89,6 +102,7 @@ jobs:
with:
token: ${{ env.CODECOV_TOKEN }}
file: ./coverage.txt
+ flags: ${{ inputs.full_coverage && 'full_coverage' || '' }}
fail_ci_if_error: false
- name: Upload test results to Codecov
if: ${{ !cancelled() }}
diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml
index bab80f0363..5d605ea934 100644
--- a/.github/workflows/reviewdog.yml
+++ b/.github/workflows/reviewdog.yml
@@ -1,6 +1,6 @@
name: "ReviewDog workflow"
env:
- GOLANGCI_LINT_VERSION: "v2.6.0"
+ GOLANGCI_LINT_VERSION: "v2.7.1"
on:
push:
branches:
diff --git a/.golangci-warnings.yml b/.golangci-warnings.yml
index 2bc88696f2..e6954c6e6b 100644
--- a/.golangci-warnings.yml
+++ b/.golangci-warnings.yml
@@ -4,16 +4,23 @@ run:
linters:
default: none
enable:
+ - docnametypo
+ - errortype
- gosec
- partitiontest
- - errortype
settings:
gosec:
excludes: [G101, G103, G104, G107, G112, G114, G115, G202, G204, G301, G302, G303, G304, G306, G307, G404]
custom:
- partitiontest:
- type: "module"
- description: This custom linter ensures test functions call 'partitiontest.PartitionTest(t)'
+ docnametypo:
+ type: module
+ description: "docnametypo catches doc comments with mismatched function names"
+ original-url: "https://github.com/cce/docnametypo"
+ settings:
+ include-exported: true
+ include-types: true
+ include-generated: false
+ allowed-prefixes: asm,op
errortype:
type: module
description: "errortype helps prevent subtle bugs in error handling."
@@ -24,6 +31,9 @@ linters:
check-is: true
unchecked-assert: false
check-unused: true
+ partitiontest:
+ type: "module"
+ description: This custom linter ensures test functions call 'partitiontest.PartitionTest(t)'
exclusions:
generated: lax
rules:
diff --git a/.golangci.yml b/.golangci.yml
index 50996eed33..551341b0f9 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -126,8 +126,9 @@ linters:
path: _test\.go
text: 'dot-imports: should not use dot imports' # dot imports OK for tests
- linters: revive
- path: util/
text: 'var-naming: avoid meaningless package names' # util package is OK
+ - linters: revive
+ text: 'var-naming: avoid package names that conflict with Go standard library package names' # e.g. crypto package
- linters: unused
text: 'field _struct is unused' # we use _struct field tags for msgp/json encoding settings
- linters: revive
diff --git a/AGENTS.md b/AGENTS.md
index 1496e4276b..88625609f6 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -50,8 +50,6 @@ To verify that this wasn't missed, we run verification steps, which can be found
### Development Setup
```bash
./scripts/configure_dev.sh # Initial environment setup
-./scripts/buildtools/install_buildtools.sh # Install build tools
-make deps # Check/install dependencies
```
### Single Test Execution
diff --git a/Makefile b/Makefile
index cd8f077027..e9552dcafc 100644
--- a/Makefile
+++ b/Makefile
@@ -43,12 +43,7 @@ GOTAGSLIST := sqlite_unlock_notify sqlite_omit_load_extension
# e.g. make GOTAGSCUSTOM=msgtrace
GOTAGSLIST += ${GOTAGSCUSTOM}
-# If available, use gotestsum instead of 'go test'.
-ifeq (, $(shell which gotestsum))
-export GOTESTCOMMAND=go test
-else
-export GOTESTCOMMAND=gotestsum --format pkgname --jsonfile testresults.json --
-endif
+GOTESTCOMMAND := go tool -modfile=tool.mod gotestsum --format pkgname --jsonfile testresults.json --
ifeq ($(OS_TYPE), darwin)
# M1 Mac--homebrew install location in /opt/homebrew
@@ -89,6 +84,7 @@ GOLDFLAGS := $(GOLDFLAGS_BASE) \
-X github.com/algorand/go-algorand/config.Channel=$(CHANNEL)
UNIT_TEST_SOURCES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && go list ./... | grep -v /go-algorand/test/ ))
+COVERPKG_PACKAGES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && go list ./... | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing|mocks|mock)$$' ))
ALGOD_API_PACKAGES := $(sort $(shell GOPATH=$(GOPATH) && GO111MODULE=off && cd daemon/algod/api; go list ./... ))
GOMOD_DIRS := ./tools/block-generator ./tools/x-repo-types
@@ -107,10 +103,13 @@ fix: build
$(GOBIN)/algofix */
modernize:
- GOTOOLCHAIN=auto go run golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest -any=false -bloop=false -rangeint=false -fmtappendf=false -waitgroup=false -stringsbuilder=false -omitzero=false -fix ./...
+ GOTOOLCHAIN=auto go run golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@v0.39.0 -any=false -bloop=false -rangeint=false -fmtappendf=false -waitgroup=false -stringsbuilder=false -omitzero=false -fix ./...
-lint: deps
- $(GOBIN)/golangci-lint run -c .golangci.yml
+lint:
+ go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.7.1 run -c .golangci.yml
+
+warninglint: custom-golangci-lint
+ ./custom-golangci-lint run -c .golangci-warnings.yml
expectlint:
cd test/e2e-go/cli/goal/expect && python3 expect_linter.py *.exp
@@ -134,13 +133,24 @@ check_shell:
sanity: fix lint fmt tidy modernize
+# "make cover" runs all tests, and collects full coverage across all go-algorand packages by setting -coverpkg.
+# Without setting -coverpkg, coverage reports only measure lines of code exercised within the same package as the tests.
+#
+# "make cover PACKAGE=X" runs all tests in package github.com/algorand/go-algorand/X/... and collects full coverage
+# across all packages that are dependencies of that package.
cover:
- go test $(GOTAGS) -coverprofile=cover.out $(UNIT_TEST_SOURCES)
+ifeq ($(PACKAGE),)
+ $(GOTESTCOMMAND) $(GOTAGS) -coverprofile=cover.out $(UNIT_TEST_SOURCES) -covermode=atomic -coverpkg=$(shell echo $(COVERPKG_PACKAGES) | sed 's/ /,/g')
+else
+ cd $(PACKAGE); \
+ $(GOTESTCOMMAND) $(GOTAGS) -coverprofile=cover.out ./... -covermode=atomic -coverpkg=$$( (go list -f '{{ join .Deps "\n" }}' ./...; go list -f '{{ join .TestImports "\n" }}' ./...) | grep 'github.com/algorand/go-algorand' | egrep -v '/go-algorand/(test|debug|cmd|config/defaultsGenerator|tools)' | egrep -v '(test|testing|mocks|mock)$$' | sort | uniq | paste -sd ',' -); \
+ go tool cover -html cover.out
+endif
prof:
cd node && go test $(GOTAGS) -cpuprofile=cpu.out -memprofile=mem.out -mutexprofile=mutex.out
-generate: deps
+generate:
PATH=$(GOBIN):$$PATH go generate ./...
msgp: $(patsubst %,%/msgp_gen.go,$(MSGP_GENERATE))
@@ -151,13 +161,13 @@ api:
logic:
make -C data/transactions/logic
-
-%/msgp_gen.go: deps ALWAYS
+MSGP := go run github.com/algorand/msgp@v1.1.62
+%/msgp_gen.go: ALWAYS
@set +e; \
- printf "msgp: $(@D)..."; \
- $(GOBIN)/msgp -file ./$(@D) -o $@ -warnmask github.com/algorand/go-algorand > ./$@.out 2>&1; \
+ printf "$(MSGP) $(@D)..."; \
+ $(MSGP) -file ./$(@D) -o $@ -warnmask github.com/algorand/go-algorand > ./$@.out 2>&1; \
if [ "$$?" != "0" ]; then \
- printf "failed:\n$(GOBIN)/msgp -file ./$(@D) -o $@ -warnmask github.com/algorand/go-algorand\n"; \
+ printf "failed:\n$(MSGP) -file ./$(@D) -o $@ -warnmask github.com/algorand/go-algorand\n"; \
cat ./$@.out; \
rm ./$@.out; \
exit 1; \
@@ -231,9 +241,6 @@ else
echo "OS_TYPE must be darwin for universal builds, skipping"
endif
-deps:
- ./scripts/check_deps.sh
-
# artifacts
# Regenerate kmd swagger spec files
@@ -260,7 +267,7 @@ $(KMD_API_SWAGGER_SPEC): $(KMD_API_FILES) crypto/libs/$(OS_TYPE)/$(ARCH)/lib/lib
touch $@; \
fi
-$(KMD_API_SWAGGER_INJECT): deps $(KMD_API_SWAGGER_SPEC) $(KMD_API_SWAGGER_SPEC).validated
+$(KMD_API_SWAGGER_INJECT): $(KMD_API_SWAGGER_SPEC) $(KMD_API_SWAGGER_SPEC).validated
./daemon/kmd/lib/kmdapi/bundle_swagger_json.sh
# generated files we should make sure we clean
@@ -268,7 +275,7 @@ GENERATED_FILES := \
$(KMD_API_SWAGGER_INJECT) \
$(KMD_API_SWAGGER_SPEC) $(KMD_API_SWAGGER_SPEC).validated
-rebuild_kmd_swagger: deps
+rebuild_kmd_swagger:
rm -f $(GENERATED_FILES)
# we need to invoke the make here since we want to ensure that the deletion and re-creating are sequential
make $(KMD_API_SWAGGER_INJECT)
@@ -306,7 +313,7 @@ build-e2e: check-go-version crypto/libs/$(OS_TYPE)/$(ARCH)/lib/libsodium.a
wait
cp $(GOBIN)/kmd $(GOBIN)-race
-NONGO_BIN_FILES=$(GOBIN)/find-nodes.sh $(GOBIN)/update.sh $(GOBIN)/COPYING $(GOBIN)/ddconfig.sh
+NONGO_BIN_FILES=$(GOBIN)/find-nodes.sh $(GOBIN)/update.sh $(GOBIN)/COPYING
NONGO_BIN: $(NONGO_BIN_FILES)
@@ -316,8 +323,6 @@ $(GOBIN)/update.sh: cmd/updater/update.sh
$(GOBIN)/COPYING: COPYING
-$(GOBIN)/ddconfig.sh: scripts/ddconfig.sh
-
$(GOBIN)/%:
cp -f $< $@
@@ -415,7 +420,7 @@ dump: $(addprefix gen/,$(addsuffix /genesis.dump, $(NETWORKS)))
install: build
scripts/dev_install.sh -p $(GOBIN)
-.PHONY: default fmt lint check_shell sanity cover prof deps build build-race build-e2e test fulltest shorttest clean cleango deploy node_exporter install %gen gen NONGO_BIN check-go-version rebuild_kmd_swagger universal libsodium modernize
+.PHONY: default fmt lint check_shell sanity cover prof build build-race build-e2e test fulltest shorttest clean cleango deploy node_exporter install %gen gen NONGO_BIN check-go-version rebuild_kmd_swagger universal libsodium modernize
###### TARGETS FOR CICD PROCESS ######
include ./scripts/release/mule/Makefile.mule
@@ -423,6 +428,5 @@ include ./scripts/release/mule/Makefile.mule
archive:
aws s3 cp tmp/node_pkgs s3://algorand-internal/channel/$(CHANNEL)/$(FULLBUILDNUMBER) --recursive --exclude "*" --include "*$(FULLBUILDNUMBER)*"
-build_custom_linters:
+custom-golangci-lint: .custom-gcl.yml
golangci-lint custom -v
- ./custom-golangci-lint --version
diff --git a/README.md b/README.md
index 31a4299094..6551290601 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,6 @@ We currently strive to support Debian-based distributions, with Ubuntu 24.04 as
git clone https://github.com/algorand/go-algorand
cd go-algorand
./scripts/configure_dev.sh
-./scripts/buildtools/install_buildtools.sh
```
At this point, you are ready to build go-algorand. We use `make` and have several targets to automate common tasks.
@@ -136,7 +135,6 @@ Contains the two daemons that provide Algorand clients with services:
Enables developers to interface with the Algorand system:
- **cmd**: Contains the primary commands defining entry points into the system.
- - **cmd/catchupsrv** ([README](cmd/catchupsrv/README.md)): A tool to assist with processing historic blocks on a new node.
- **libgoal**: Exports a Go interface useful for developers of Algorand clients.
- **tools** ([README](tools/README.md)): Various tools and utilities that don’t have a better place to go.
- **tools/debug**: Holds secondary commands that assist developers during debugging.
@@ -148,8 +146,6 @@ Helps Algorand developers deploy networks of their own:
- **nodecontrol**
- **docker**
-- **commandandcontrol** ([README](test/commandandcontrol/README.md)): A tool to automate a network of `algod` instances.
-- **components**
- **netdeploy**
### Utilities
@@ -169,5 +165,5 @@ Provides utilities for the various components:
Please see the [COPYING_FAQ](COPYING_FAQ) for details on how to apply our license.
-Copyright (C) 2019-2025, Algorand Inc.
+Copyright (C) 2019-2026, Algorand Inc.
diff --git a/agreement/abstractions.go b/agreement/abstractions.go
index 90d4e1cbfc..c5492fa197 100644
--- a/agreement/abstractions.go
+++ b/agreement/abstractions.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/actions.go b/agreement/actions.go
index 29e37b5c4c..7f1ee27351 100644
--- a/agreement/actions.go
+++ b/agreement/actions.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -26,7 +26,7 @@ import (
"github.com/algorand/go-algorand/protocol"
)
-//go:generate stringer -type=actionType
+//go:generate go tool -modfile=../tool.mod stringer -type=actionType
type actionType uint8
const (
diff --git a/agreement/actiontype_string.go b/agreement/actiontype_string.go
index 9272ec2cf6..e78bb4e299 100644
--- a/agreement/actiontype_string.go
+++ b/agreement/actiontype_string.go
@@ -31,8 +31,9 @@ const _actionType_name = "noopignorebroadcastrelaydisconnectbroadcastVotesverify
var _actionType_index = [...]uint8{0, 4, 10, 19, 24, 34, 48, 58, 71, 83, 89, 100, 106, 112, 120, 129, 139}
func (i actionType) String() string {
- if i >= actionType(len(_actionType_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_actionType_index)-1 {
return "actionType(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _actionType_name[_actionType_index[i]:_actionType_index[i+1]]
+ return _actionType_name[_actionType_index[idx]:_actionType_index[idx+1]]
}
diff --git a/agreement/actor.go b/agreement/actor.go
index 4df7333d11..d262c435bd 100644
--- a/agreement/actor.go
+++ b/agreement/actor.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/agreeInstall.go b/agreement/agreeInstall.go
index 3a9c86ddb1..6c694a8996 100644
--- a/agreement/agreeInstall.go
+++ b/agreement/agreeInstall.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/agreementtest/keyManager.go b/agreement/agreementtest/keyManager.go
index f62d296b81..1e0819bf6e 100644
--- a/agreement/agreementtest/keyManager.go
+++ b/agreement/agreementtest/keyManager.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/agreementtest/simulate.go b/agreement/agreementtest/simulate.go
index b806cdbb40..256b5b9cd5 100644
--- a/agreement/agreementtest/simulate.go
+++ b/agreement/agreementtest/simulate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/agreementtest/simulate_test.go b/agreement/agreementtest/simulate_test.go
index 0bb4d8d109..5c61a91af7 100644
--- a/agreement/agreementtest/simulate_test.go
+++ b/agreement/agreementtest/simulate_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/asyncVoteVerifier.go b/agreement/asyncVoteVerifier.go
index 8678e1104a..83279052e3 100644
--- a/agreement/asyncVoteVerifier.go
+++ b/agreement/asyncVoteVerifier.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/asyncVoteVerifier_test.go b/agreement/asyncVoteVerifier_test.go
index 3e3384fb31..385251f9a5 100644
--- a/agreement/asyncVoteVerifier_test.go
+++ b/agreement/asyncVoteVerifier_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/autopsy.go b/agreement/autopsy.go
index ccefd6f207..5aeeeeaae0 100644
--- a/agreement/autopsy.go
+++ b/agreement/autopsy.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/bundle.go b/agreement/bundle.go
index 0494162caf..6742174642 100644
--- a/agreement/bundle.go
+++ b/agreement/bundle.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -52,7 +52,7 @@ type bundle struct {
EquivocationVotes []equivocationVote `codec:"eqv,allocbound=bounds.MaxVoteThreshold"`
}
-// voteAuthenticators omit the Round, Period, Step, and Proposal for compression
+// voteAuthenticator omits the Round, Period, Step, and Proposal for compression
// and to simplify checking logic.
type voteAuthenticator struct {
_struct struct{} `codec:""` // not omitempty
diff --git a/agreement/bundle_test.go b/agreement/bundle_test.go
index 2eac91fb41..9f9ae675de 100644
--- a/agreement/bundle_test.go
+++ b/agreement/bundle_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/cadaver.go b/agreement/cadaver.go
index 6dea25fdff..45d8fb73f0 100644
--- a/agreement/cadaver.go
+++ b/agreement/cadaver.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/certificate.go b/agreement/certificate.go
index 86fde01e01..545d403e7e 100644
--- a/agreement/certificate.go
+++ b/agreement/certificate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/certificate_test.go b/agreement/certificate_test.go
index 99f40cb35c..56d37aec51 100644
--- a/agreement/certificate_test.go
+++ b/agreement/certificate_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/common_test.go b/agreement/common_test.go
index 9fa2a2829e..6081b2dde8 100644
--- a/agreement/common_test.go
+++ b/agreement/common_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/coservice.go b/agreement/coservice.go
index 053144fb14..3e5f06bc3f 100644
--- a/agreement/coservice.go
+++ b/agreement/coservice.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -22,7 +22,7 @@ import (
"github.com/algorand/go-algorand/logging"
)
-//go:generate stringer -type=coserviceType
+//go:generate go tool -modfile=../tool.mod stringer -type=coserviceType
const (
demuxCoserviceType coserviceType = iota
tokenizerCoserviceType
diff --git a/agreement/coservicetype_string.go b/agreement/coservicetype_string.go
index c01199de01..efb858de7f 100644
--- a/agreement/coservicetype_string.go
+++ b/agreement/coservicetype_string.go
@@ -21,8 +21,9 @@ const _coserviceType_name = "demuxCoserviceTypetokenizerCoserviceTypecryptoVerif
var _coserviceType_index = [...]uint8{0, 18, 40, 67, 90, 108, 128}
func (i coserviceType) String() string {
- if i < 0 || i >= coserviceType(len(_coserviceType_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_coserviceType_index)-1 {
return "coserviceType(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _coserviceType_name[_coserviceType_index[i]:_coserviceType_index[i+1]]
+ return _coserviceType_name[_coserviceType_index[idx]:_coserviceType_index[idx+1]]
}
diff --git a/agreement/credentialArrivalHistory.go b/agreement/credentialArrivalHistory.go
index b79237b547..6308b6a0b9 100644
--- a/agreement/credentialArrivalHistory.go
+++ b/agreement/credentialArrivalHistory.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/credentialArrivalHistory_test.go b/agreement/credentialArrivalHistory_test.go
index 44bb2a20fd..915b7f1079 100644
--- a/agreement/credentialArrivalHistory_test.go
+++ b/agreement/credentialArrivalHistory_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/cryptoRequestContext.go b/agreement/cryptoRequestContext.go
index 05d784ab87..2db4e6c82e 100644
--- a/agreement/cryptoRequestContext.go
+++ b/agreement/cryptoRequestContext.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -46,7 +46,7 @@ type roundRequestsContext struct {
periods map[cryptoRequestCtxKey]periodRequestsContext
}
-// pendingRequests keeps the context for all pending requests
+// pendingRequestsContext keeps the context for all pending requests
//
//msgp:ignore pendingRequestsContext
type pendingRequestsContext map[round]roundRequestsContext
diff --git a/agreement/cryptoRequestContext_test.go b/agreement/cryptoRequestContext_test.go
index d67b67edf2..7fa900a951 100644
--- a/agreement/cryptoRequestContext_test.go
+++ b/agreement/cryptoRequestContext_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/cryptoVerifier.go b/agreement/cryptoVerifier.go
index 1d7752eac5..4555218ecb 100644
--- a/agreement/cryptoVerifier.go
+++ b/agreement/cryptoVerifier.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/cryptoVerifier_test.go b/agreement/cryptoVerifier_test.go
index 48ea73afa2..8880adcf55 100644
--- a/agreement/cryptoVerifier_test.go
+++ b/agreement/cryptoVerifier_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/demux.go b/agreement/demux.go
index 01429be30f..a71001df1f 100644
--- a/agreement/demux.go
+++ b/agreement/demux.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/demux_test.go b/agreement/demux_test.go
index 2af7403465..832c189944 100644
--- a/agreement/demux_test.go
+++ b/agreement/demux_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/doc.go b/agreement/doc.go
index c8f1d6557f..18fa3bd0e0 100644
--- a/agreement/doc.go
+++ b/agreement/doc.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/dynamicFilterTimeoutParams.go b/agreement/dynamicFilterTimeoutParams.go
index cf4bfd226b..164d641d21 100644
--- a/agreement/dynamicFilterTimeoutParams.go
+++ b/agreement/dynamicFilterTimeoutParams.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/dynamicFilterTimeoutParams_test.go b/agreement/dynamicFilterTimeoutParams_test.go
index 3854974715..0a5af5e8dd 100644
--- a/agreement/dynamicFilterTimeoutParams_test.go
+++ b/agreement/dynamicFilterTimeoutParams_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/encoding_test.go b/agreement/encoding_test.go
index 563f5e7f92..6f06bf98a4 100644
--- a/agreement/encoding_test.go
+++ b/agreement/encoding_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/errors.go b/agreement/errors.go
index 59382a4023..476dcb79f5 100644
--- a/agreement/errors.go
+++ b/agreement/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/events.go b/agreement/events.go
index 6b302243a7..c0d4f9fb8d 100644
--- a/agreement/events.go
+++ b/agreement/events.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -70,7 +70,7 @@ type externalEvent interface {
// interface. The semantics of an event depends on the eventType and not on the
// type of the implementing struct.
//
-//go:generate stringer -type=eventType
+//go:generate go tool -modfile=../tool.mod stringer -type=eventType
type eventType uint8
const (
diff --git a/agreement/events_test.go b/agreement/events_test.go
index db8d30a109..8bdaf93004 100644
--- a/agreement/events_test.go
+++ b/agreement/events_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -25,7 +25,7 @@ import (
"github.com/stretchr/testify/require"
)
-// TestSerializableErrorBackwardCompatible ensures Err field of type serializableError can be
+// TestSerializableErrorBackwardCompatibility ensures Err field of type serializableError can be
// properly decoded from ConsensusVersionView.
// This test is only needed for agreement state serialization switch from reflection to msgp.
func TestSerializableErrorBackwardCompatibility(t *testing.T) {
diff --git a/agreement/eventtype_string.go b/agreement/eventtype_string.go
index 9973215b12..01ca7a390d 100644
--- a/agreement/eventtype_string.go
+++ b/agreement/eventtype_string.go
@@ -55,8 +55,9 @@ const _eventType_name = "nonevotePresentpayloadPresentbundlePresentvoteVerifiedp
var _eventType_index = [...]uint16{0, 4, 15, 29, 42, 54, 69, 83, 100, 107, 118, 131, 144, 157, 176, 192, 204, 217, 231, 246, 261, 277, 293, 308, 322, 334, 342, 351, 362, 372, 386, 403, 419, 445, 464, 485, 499, 515, 524, 537, 554}
func (i eventType) String() string {
- if i >= eventType(len(_eventType_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_eventType_index)-1 {
return "eventType(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _eventType_name[_eventType_index[i]:_eventType_index[i+1]]
+ return _eventType_name[_eventType_index[idx]:_eventType_index[idx+1]]
}
diff --git a/agreement/fuzzer/bandwidthFilter_test.go b/agreement/fuzzer/bandwidthFilter_test.go
index 430d69103c..dee116056a 100644
--- a/agreement/fuzzer/bandwidthFilter_test.go
+++ b/agreement/fuzzer/bandwidthFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/catchupFilter_test.go b/agreement/fuzzer/catchupFilter_test.go
index 130715506f..b1ce43893f 100644
--- a/agreement/fuzzer/catchupFilter_test.go
+++ b/agreement/fuzzer/catchupFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -104,7 +104,7 @@ func MakeCatchupFilterFactory(config *CatchupFilterConfig) *CatchupFilter {
}
}
-// Unmarshall CatchupFilter
+// Unmarshal CatchupFilter
func (n *CatchupFilter) Unmarshal(b []byte) NetworkFilterFactory {
type catchupFilterJSON struct {
Name string
diff --git a/agreement/fuzzer/clockedFilter_test.go b/agreement/fuzzer/clockedFilter_test.go
index 82a81eba44..c0b5f1e901 100644
--- a/agreement/fuzzer/clockedFilter_test.go
+++ b/agreement/fuzzer/clockedFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -86,7 +86,7 @@ func (n *ClockedFilter) Tick(newClockTime int) bool {
return n.upstream.Tick(int(n.localClock))
}
-// Unmarshall ClockedFilter
+// Unmarshal ClockedFilter
func (n *ClockedFilter) Unmarshal(b []byte) NetworkFilterFactory {
type clockedFilterJSON struct {
Name string
diff --git a/agreement/fuzzer/dropMessageFilter_test.go b/agreement/fuzzer/dropMessageFilter_test.go
index 46e341f22c..832d54dc8e 100644
--- a/agreement/fuzzer/dropMessageFilter_test.go
+++ b/agreement/fuzzer/dropMessageFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -96,7 +96,7 @@ func (n *DropMessageFilter) Marshal() (bytes []byte, err error) {
}
-// Unmarshall DropMessageFilter
+// Unmarshal DropMessageFilter
func (n *DropMessageFilter) Unmarshal(b []byte) NetworkFilterFactory {
type dropMessageFilterJSON struct {
Name string
diff --git a/agreement/fuzzer/duplicateMessageFilter_test.go b/agreement/fuzzer/duplicateMessageFilter_test.go
index eac5832de0..835d591959 100644
--- a/agreement/fuzzer/duplicateMessageFilter_test.go
+++ b/agreement/fuzzer/duplicateMessageFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/filter_test.go b/agreement/fuzzer/filter_test.go
index d0a0736b01..9fe00d5b2c 100644
--- a/agreement/fuzzer/filter_test.go
+++ b/agreement/fuzzer/filter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/fuzzer.go b/agreement/fuzzer/fuzzer.go
index 7b1c9558b2..c58c1e0976 100644
--- a/agreement/fuzzer/fuzzer.go
+++ b/agreement/fuzzer/fuzzer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/fuzzer_test.go b/agreement/fuzzer/fuzzer_test.go
index 7f0214e2be..caef311d7f 100644
--- a/agreement/fuzzer/fuzzer_test.go
+++ b/agreement/fuzzer/fuzzer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/ledger_test.go b/agreement/fuzzer/ledger_test.go
index 6fb752a565..45a3ae743e 100644
--- a/agreement/fuzzer/ledger_test.go
+++ b/agreement/fuzzer/ledger_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/messageDecoderFilter_test.go b/agreement/fuzzer/messageDecoderFilter_test.go
index 6fd6d7a5bd..ea3361c872 100644
--- a/agreement/fuzzer/messageDecoderFilter_test.go
+++ b/agreement/fuzzer/messageDecoderFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -19,6 +19,7 @@ package fuzzer
import (
"bytes"
"encoding/json"
+
"github.com/algorand/go-deadlock"
//"github.com/algorand/go-algorand/agreement"
@@ -107,7 +108,7 @@ type (
EquivocationVotes []equivocationVote `codec:"eqv"`
}
- // voteAuthenticators omit the Round, Period, Step, and Proposal for compression
+ // voteAuthenticator omits the Round, Period, Step, and Proposal for compression
// and to simplify checking logic.
voteAuthenticator struct {
Sender basics.Address `codec:"snd"`
@@ -324,7 +325,7 @@ func (n *MessageDecoderFilter) getDecodedMessageCounts(tag protocol.Tag) int {
return -1
}
-// Unmarshall MessageDecoderFilter
+// Unmarshal MessageDecoderFilter
func (n *MessageDecoderFilter) Unmarshal(b []byte) NetworkFilterFactory {
type messageDecoderFilterJSON struct {
Name string
diff --git a/agreement/fuzzer/messageDelayFilter_test.go b/agreement/fuzzer/messageDelayFilter_test.go
index d6b970e346..b1c24c1621 100644
--- a/agreement/fuzzer/messageDelayFilter_test.go
+++ b/agreement/fuzzer/messageDelayFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -188,7 +188,7 @@ func (n *MessageDelayFilter) processUpstreamBuffer() bool {
return received
}
-// Unmarshall MessageDelayFilter
+// Unmarshal MessageDelayFilter
func (n *MessageDelayFilter) Unmarshal(b []byte) NetworkFilterFactory {
type messageDelayFilterJSON struct {
Name string
diff --git a/agreement/fuzzer/messageDuplicationFilter_test.go b/agreement/fuzzer/messageDuplicationFilter_test.go
index 6f8fec90ca..00f4a65a14 100644
--- a/agreement/fuzzer/messageDuplicationFilter_test.go
+++ b/agreement/fuzzer/messageDuplicationFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -185,7 +185,7 @@ func (n *MessageDuplicationFilter) processUpstreamBuffer() bool {
return received
}
-// Unmarshall MessageDuplicationFilter
+// Unmarshal MessageDuplicationFilter
func (n *MessageDuplicationFilter) Unmarshal(b []byte) NetworkFilterFactory {
type messageDuplicationFilterJSON struct {
Name string
diff --git a/agreement/fuzzer/messagePriorityQueue_test.go b/agreement/fuzzer/messagePriorityQueue_test.go
index c503398076..a0f65026c1 100644
--- a/agreement/fuzzer/messagePriorityQueue_test.go
+++ b/agreement/fuzzer/messagePriorityQueue_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/messageReflectionFilter_test.go b/agreement/fuzzer/messageReflectionFilter_test.go
index 2e2792b0a8..bf7e0c5428 100644
--- a/agreement/fuzzer/messageReflectionFilter_test.go
+++ b/agreement/fuzzer/messageReflectionFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -192,7 +192,7 @@ func (n *MessageReflectionFilter) processUpstreamBuffer() bool {
return received
}
-// Unmarshall MessageReflectionFilter
+// Unmarshal MessageReflectionFilter
func (n *MessageReflectionFilter) Unmarshal(b []byte) NetworkFilterFactory {
type messageReflectionFilterJSON struct {
Name string
diff --git a/agreement/fuzzer/messageRegossipFilter_test.go b/agreement/fuzzer/messageRegossipFilter_test.go
index 448af42665..e69de625ce 100644
--- a/agreement/fuzzer/messageRegossipFilter_test.go
+++ b/agreement/fuzzer/messageRegossipFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/messageReorderingFilter_test.go b/agreement/fuzzer/messageReorderingFilter_test.go
index fa1f50a907..3f9ce3f02e 100644
--- a/agreement/fuzzer/messageReorderingFilter_test.go
+++ b/agreement/fuzzer/messageReorderingFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -219,7 +219,7 @@ func MakeMessageReorderingFilter(config MessageReorderingFilterConfig) *MessageR
}
}
-// Unmarshall MessageReorderingFilter
+// Unmarshal MessageReorderingFilter
func (n *MessageReorderingFilter) Unmarshal(b []byte) NetworkFilterFactory {
type messageReorderingFilterJSON struct {
Name string
diff --git a/agreement/fuzzer/networkFacade_test.go b/agreement/fuzzer/networkFacade_test.go
index 1d0d7d622a..3688997caa 100644
--- a/agreement/fuzzer/networkFacade_test.go
+++ b/agreement/fuzzer/networkFacade_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/nodeCrashFilter_test.go b/agreement/fuzzer/nodeCrashFilter_test.go
index 5cf4267f1e..bc48a07f05 100644
--- a/agreement/fuzzer/nodeCrashFilter_test.go
+++ b/agreement/fuzzer/nodeCrashFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -100,7 +100,7 @@ func MakeNodeCrashFilterFactory(config *NodeCrashFilterConfig) *NodeCrashFilter
}
}
-// Unmarshall NodeCrashFilter
+// Unmarshal NodeCrashFilter
func (n *NodeCrashFilter) Unmarshal(b []byte) NetworkFilterFactory {
type catchupFilterJSON struct {
Name string
diff --git a/agreement/fuzzer/nullFilter_test.go b/agreement/fuzzer/nullFilter_test.go
index 81b236bd10..81b9d063e9 100644
--- a/agreement/fuzzer/nullFilter_test.go
+++ b/agreement/fuzzer/nullFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/router_test.go b/agreement/fuzzer/router_test.go
index f8449f1d55..37685bec05 100644
--- a/agreement/fuzzer/router_test.go
+++ b/agreement/fuzzer/router_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -78,7 +78,7 @@ func (r *Router) GetDownstreamFilter() DownstreamFilter {
return nil
}
-// SendMessage routes messages sent to message received.
+// sendMessageToNode routes messages sent to message received.
func (r *Router) sendMessageToNode(sourceNode, targetNode int, tag protocol.Tag, data []byte) {
upstreamFilter := r.getUpstreamFilter(targetNode)
if upstreamFilter == nil {
diff --git a/agreement/fuzzer/schedulerFilter_test.go b/agreement/fuzzer/schedulerFilter_test.go
index 97d8254821..b6784a4965 100644
--- a/agreement/fuzzer/schedulerFilter_test.go
+++ b/agreement/fuzzer/schedulerFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -187,7 +187,7 @@ func (n *SchedulerFilterSchedule) Evaluate(timepoint int, nodeID int) bool {
}
}
-// Unmarshall SchedulerFilter
+// Unmarshal SchedulerFilter
func (n *SchedulerFilter) Unmarshal(b []byte) NetworkFilterFactory {
type schedulerFilterConfigJSON struct {
Name string
diff --git a/agreement/fuzzer/tests_test.go b/agreement/fuzzer/tests_test.go
index 408feeeadc..098dfa7df2 100644
--- a/agreement/fuzzer/tests_test.go
+++ b/agreement/fuzzer/tests_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/topologyFilter_test.go b/agreement/fuzzer/topologyFilter_test.go
index 652c9bf7d3..d15904f02c 100644
--- a/agreement/fuzzer/topologyFilter_test.go
+++ b/agreement/fuzzer/topologyFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/trafficStatisticsFilter_test.go b/agreement/fuzzer/trafficStatisticsFilter_test.go
index 74ce51a346..63b24910a7 100644
--- a/agreement/fuzzer/trafficStatisticsFilter_test.go
+++ b/agreement/fuzzer/trafficStatisticsFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/validator_test.go b/agreement/fuzzer/validator_test.go
index 7ba511a1a3..2e1906418f 100644
--- a/agreement/fuzzer/validator_test.go
+++ b/agreement/fuzzer/validator_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/fuzzer/voteFilter_test.go b/agreement/fuzzer/voteFilter_test.go
index c0fcbaf7cf..9e8ee834bf 100644
--- a/agreement/fuzzer/voteFilter_test.go
+++ b/agreement/fuzzer/voteFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -139,7 +139,7 @@ func (n *VoteFilter) Eval(tag protocol.Tag, data []byte, direction string) bool
return true
}
-// Unmarshall VoteFilter
+// Unmarshal VoteFilter
func (n *VoteFilter) Unmarshal(b []byte) NetworkFilterFactory {
type voteFilterJSON struct {
Name string
diff --git a/agreement/gossip/network.go b/agreement/gossip/network.go
index 41294d28cf..16d44f8eb4 100644
--- a/agreement/gossip/network.go
+++ b/agreement/gossip/network.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/gossip/networkFull_test.go b/agreement/gossip/networkFull_test.go
index a48e9ddd55..1c50d112f5 100644
--- a/agreement/gossip/networkFull_test.go
+++ b/agreement/gossip/networkFull_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/gossip/network_test.go b/agreement/gossip/network_test.go
index 0c19ac7bab..584df854da 100644
--- a/agreement/gossip/network_test.go
+++ b/agreement/gossip/network_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/keyManager_test.go b/agreement/keyManager_test.go
index 18f3ffb44e..bde124d652 100644
--- a/agreement/keyManager_test.go
+++ b/agreement/keyManager_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/listener.go b/agreement/listener.go
index 136461396d..2e99f8079c 100644
--- a/agreement/listener.go
+++ b/agreement/listener.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/message.go b/agreement/message.go
index e62dd63b0f..54ceac283d 100644
--- a/agreement/message.go
+++ b/agreement/message.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/message_test.go b/agreement/message_test.go
index 4c7712c591..17a8de7560 100644
--- a/agreement/message_test.go
+++ b/agreement/message_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/msgp_gen.go b/agreement/msgp_gen.go
index f6921ceb92..9e6c1961b3 100644
--- a/agreement/msgp_gen.go
+++ b/agreement/msgp_gen.go
@@ -1,7 +1,7 @@
-package agreement
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package agreement
+
import (
"sort"
@@ -877,7 +877,7 @@ func (z *Certificate) MsgIsZero() bool {
return ((*z).Round.MsgIsZero()) && ((*z).Period == 0) && ((*z).Step == 0) && ((*z).Proposal.MsgIsZero()) && (len((*z).Votes) == 0) && (len((*z).EquivocationVotes) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// CertificateMaxSize returns a maximum valid message size for this message type
func CertificateMaxSize() (s int) {
s = 1 + 4 + basics.RoundMaxSize() + 4 + msgp.Uint64Size + 5 + msgp.Uint64Size + 5 + ProposalValueMaxSize() + 5
// Calculating size of slice: z.Votes
@@ -1047,7 +1047,7 @@ func (z *ConsensusVersionView) MsgIsZero() bool {
return ((*z).Err == nil) && ((*z).Version.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// ConsensusVersionViewMaxSize returns a maximum valid message size for this message type
func ConsensusVersionViewMaxSize() (s int) {
s = 1 + 4
panic("Unable to determine max size: String type string(*z.Err) is unbounded")
@@ -1180,7 +1180,7 @@ func (z *Deadline) MsgIsZero() bool {
return ((*z).Duration == 0) && ((*z).Type == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// DeadlineMaxSize returns a maximum valid message size for this message type
func DeadlineMaxSize() (s int) {
s = 1 + 9 + msgp.DurationSize + 5 + msgp.Int8Size
return
@@ -1240,7 +1240,7 @@ func (z LateCredentialTrackingEffect) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// LateCredentialTrackingEffectMaxSize returns a maximum valid message size for this message type
func LateCredentialTrackingEffectMaxSize() (s int) {
s = msgp.Uint8Size
return
@@ -1300,7 +1300,7 @@ func (z TimeoutType) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// TimeoutTypeMaxSize returns a maximum valid message size for this message type
func TimeoutTypeMaxSize() (s int) {
s = msgp.Int8Size
return
@@ -1360,7 +1360,7 @@ func (z actionType) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// ActionTypeMaxSize returns a maximum valid message size for this message type
func ActionTypeMaxSize() (s int) {
s = msgp.Uint8Size
return
@@ -1578,7 +1578,7 @@ func (z *blockAssembler) MsgIsZero() bool {
return ((*z).Pipeline.MsgIsZero()) && ((*z).Filled == false) && ((*z).Payload.MsgIsZero()) && ((*z).Assembled == false) && (len((*z).Authenticators) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// BlockAssemblerMaxSize returns a maximum valid message size for this message type
func BlockAssemblerMaxSize() (s int) {
s = 1 + 9 + UnauthenticatedProposalMaxSize() + 7 + msgp.BoolSize + 8 + ProposalMaxSize() + 10 + msgp.BoolSize + 15
// Calculating size of slice: z.Authenticators
@@ -1850,7 +1850,7 @@ func (z *bundle) MsgIsZero() bool {
return ((*z).U.MsgIsZero()) && (len((*z).Votes) == 0) && (len((*z).EquivocationVotes) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// BundleMaxSize returns a maximum valid message size for this message type
func BundleMaxSize() (s int) {
s = 1 + 2 + UnauthenticatedBundleMaxSize() + 5
// Calculating size of slice: z.Votes
@@ -1980,7 +1980,7 @@ func (z *compoundMessage) MsgIsZero() bool {
return ((*z).Vote.MsgIsZero()) && ((*z).Proposal.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// CompoundMessageMaxSize returns a maximum valid message size for this message type
func CompoundMessageMaxSize() (s int) {
s = 1 + 5 + UnauthenticatedVoteMaxSize() + 9 + UnauthenticatedProposalMaxSize()
return
@@ -2245,7 +2245,7 @@ func (z *diskState) MsgIsZero() bool {
return (len((*z).Router) == 0) && (len((*z).Player) == 0) && (len((*z).Clock) == 0) && (len((*z).ActionTypes) == 0) && (len((*z).Actions) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// DiskStateMaxSize returns a maximum valid message size for this message type
func DiskStateMaxSize() (s int) {
s = 1 + 7
panic("Unable to determine max size: Byteslice type z.Router is unbounded")
@@ -2580,7 +2580,7 @@ func (z *equivocationVote) MsgIsZero() bool {
return ((*z).Sender.MsgIsZero()) && ((*z).Round.MsgIsZero()) && ((*z).Period == 0) && ((*z).Step == 0) && ((*z).Cred.MsgIsZero()) && (((*z).Proposals[0].MsgIsZero()) && ((*z).Proposals[1].MsgIsZero())) && (((*z).Sigs[0].MsgIsZero()) && ((*z).Sigs[1].MsgIsZero()))
}
-// MaxSize returns a maximum valid message size for this message type
+// EquivocationVoteMaxSize returns a maximum valid message size for this message type
func EquivocationVoteMaxSize() (s int) {
s = 1 + 4 + basics.AddressMaxSize() + 4 + basics.RoundMaxSize() + 4 + msgp.Uint64Size + 5 + msgp.Uint64Size + 5 + committee.CredentialMaxSize() + 6
// Calculating size of array: z.Proposals
@@ -2810,7 +2810,7 @@ func (z *equivocationVoteAuthenticator) MsgIsZero() bool {
return ((*z).Sender.MsgIsZero()) && ((*z).Cred.MsgIsZero()) && (((*z).Sigs[0].MsgIsZero()) && ((*z).Sigs[1].MsgIsZero())) && (((*z).Proposals[0].MsgIsZero()) && ((*z).Proposals[1].MsgIsZero()))
}
-// MaxSize returns a maximum valid message size for this message type
+// EquivocationVoteAuthenticatorMaxSize returns a maximum valid message size for this message type
func EquivocationVoteAuthenticatorMaxSize() (s int) {
s = 1 + 4 + basics.AddressMaxSize() + 5 + committee.UnauthenticatedCredentialMaxSize() + 4
// Calculating size of array: z.Sigs
@@ -2875,7 +2875,7 @@ func (z eventType) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// EventTypeMaxSize returns a maximum valid message size for this message type
func EventTypeMaxSize() (s int) {
s = msgp.Uint8Size
return
@@ -3058,7 +3058,7 @@ func (z *freshnessData) MsgIsZero() bool {
return ((*z).PlayerRound.MsgIsZero()) && ((*z).PlayerPeriod == 0) && ((*z).PlayerStep == 0) && ((*z).PlayerLastConcluding == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// FreshnessDataMaxSize returns a maximum valid message size for this message type
func FreshnessDataMaxSize() (s int) {
s = 1 + 12 + basics.RoundMaxSize() + 13 + msgp.Uint64Size + 11 + msgp.Uint64Size + 21 + msgp.Uint64Size
return
@@ -3419,7 +3419,7 @@ func (z *message) MsgIsZero() bool {
return ((*z).Tag.MsgIsZero()) && ((*z).Vote.MsgIsZero()) && ((*z).Proposal.MsgIsZero()) && ((*z).Bundle.MsgIsZero()) && ((*z).UnauthenticatedVote.MsgIsZero()) && ((*z).UnauthenticatedProposal.MsgIsZero()) && ((*z).UnauthenticatedBundle.MsgIsZero()) && (((*z).CompoundMessage.Vote.MsgIsZero()) && ((*z).CompoundMessage.Proposal.MsgIsZero()))
}
-// MaxSize returns a maximum valid message size for this message type
+// MessageMaxSize returns a maximum valid message size for this message type
func MessageMaxSize() (s int) {
s = 1 + 4 + protocol.TagMaxSize() + 5 + VoteMaxSize() + 9 + ProposalMaxSize() + 7 + BundleMaxSize() + 20 + UnauthenticatedVoteMaxSize() + 24 + UnauthenticatedProposalMaxSize() + 22 + UnauthenticatedBundleMaxSize() + 16 + 1 + 5 + UnauthenticatedVoteMaxSize() + 9 + UnauthenticatedProposalMaxSize()
return
@@ -3709,7 +3709,7 @@ func (z *messageEvent) MsgIsZero() bool {
return ((*z).T == 0) && ((*z).Input.MsgIsZero()) && ((*z).Err == nil) && ((*z).TaskIndex == 0) && ((*z).Tail == nil) && ((*z).Cancelled == false) && ((*z).Proto.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// MessageEventMaxSize returns a maximum valid message size for this message type
func MessageEventMaxSize() (s int) {
s = 1 + 2 + msgp.Uint8Size + 6 + MessageMaxSize() + 4
panic("Unable to determine max size: String type string(*z.Err) is unbounded")
@@ -3834,7 +3834,7 @@ func (z *nextThresholdStatusEvent) MsgIsZero() bool {
return ((*z).Bottom == false) && ((*z).Proposal.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// NextThresholdStatusEventMaxSize returns a maximum valid message size for this message type
func NextThresholdStatusEventMaxSize() (s int) {
s = 1 + 7 + msgp.BoolSize + 9 + ProposalValueMaxSize()
return
@@ -3894,7 +3894,7 @@ func (z period) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// PeriodMaxSize returns a maximum valid message size for this message type
func PeriodMaxSize() (s int) {
s = msgp.Uint64Size
return
@@ -4152,7 +4152,7 @@ func (z *periodRouter) MsgIsZero() bool {
return ((*z).ProposalTracker.MsgIsZero()) && ((*z).VoteTrackerPeriod.MsgIsZero()) && ((*z).ProposalTrackerContract.MsgIsZero()) && (len((*z).Children) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// PeriodRouterMaxSize returns a maximum valid message size for this message type
func PeriodRouterMaxSize() (s int) {
s = 1 + 16 + ProposalTrackerMaxSize() + 18 + VoteTrackerPeriodMaxSize() + 24 + ProposalTrackerContractMaxSize() + 9
s += msgp.MapHeaderSize
@@ -4433,7 +4433,7 @@ func (z *player) MsgIsZero() bool {
return ((*z).Round.MsgIsZero()) && ((*z).Period == 0) && ((*z).Step == 0) && ((*z).LastConcluding == 0) && ((*z).Deadline.MsgIsZero()) && ((*z).OldDeadline == 0) && ((*z).Napping == false) && ((*z).FastRecoveryDeadline == 0) && ((*z).Pending.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// PlayerMaxSize returns a maximum valid message size for this message type
func PlayerMaxSize() (s int) {
s = 1 + 6 + basics.RoundMaxSize() + 7 + msgp.Uint64Size + 5 + msgp.Uint64Size + 15 + msgp.Uint64Size + 15 + DeadlineMaxSize() + 9 + msgp.DurationSize + 8 + msgp.BoolSize + 21 + msgp.DurationSize + 8 + ProposalTableMaxSize()
return
@@ -5571,7 +5571,7 @@ func (z *proposal) MsgIsZero() bool {
return ((*z).unauthenticatedProposal.Block.BlockHeader.Round.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Branch.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Branch512.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Seed.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnCommitments.NativeSha512_256Commitment.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnCommitments.Sha256Commitment.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnCommitments.Sha512Commitment.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TimeStamp == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.GenesisID == "") && ((*z).unauthenticatedProposal.Block.BlockHeader.GenesisHash.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Proposer.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.FeesCollected.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Bonus.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.ProposerPayout.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.FeeSink.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsPool.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsLevel == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRate == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsResidue == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocol.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolApprovals.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeApprove == false) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnCounter == 0) && (len((*z).unauthenticatedProposal.Block.BlockHeader.StateProofTracking) == 0) && (len((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) == 0) && (len((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.AbsentParticipationAccounts) == 0) && ((*z).unauthenticatedProposal.Block.Payset.MsgIsZero()) && ((*z).unauthenticatedProposal.SeedProof.MsgIsZero()) && ((*z).unauthenticatedProposal.OriginalPeriod == 0) && ((*z).unauthenticatedProposal.OriginalProposer.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// ProposalMaxSize returns a maximum valid message size for this message type
func ProposalMaxSize() (s int) {
s = 3 + 4 + basics.RoundMaxSize() + 5 + bookkeeping.BlockHashMaxSize() + 8 + crypto.Sha512DigestMaxSize() + 5 + committee.SeedMaxSize() + 4 + crypto.DigestMaxSize() + 7 + crypto.DigestMaxSize() + 7 + crypto.Sha512DigestMaxSize() + 3 + msgp.Int64Size + 4 + msgp.StringPrefixSize + bounds.MaxGenesisIDLen + 3 + crypto.DigestMaxSize() + 4 + basics.AddressMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 5 + basics.AddressMaxSize() + 4 + basics.AddressMaxSize() + 5 + msgp.Uint64Size + 5 + msgp.Uint64Size + 5 + msgp.Uint64Size + 7 + basics.RoundMaxSize() + 6 + protocol.ConsensusVersionMaxSize() + 10 + protocol.ConsensusVersionMaxSize() + 8 + basics.RoundMaxSize() + 11 + basics.RoundMaxSize() + 11 + basics.RoundMaxSize() + 12 + protocol.ConsensusVersionMaxSize() + 13 + basics.RoundMaxSize() + 11 + msgp.BoolSize + 3 + msgp.Uint64Size + 4
s += msgp.MapHeaderSize
@@ -5678,7 +5678,7 @@ func (z *proposalManager) MsgIsZero() bool {
return true
}
-// MaxSize returns a maximum valid message size for this message type
+// ProposalManagerMaxSize returns a maximum valid message size for this message type
func ProposalManagerMaxSize() (s int) {
s = 1
return
@@ -5820,7 +5820,7 @@ func (z *proposalSeeker) MsgIsZero() bool {
return ((*z).Lowest.MsgIsZero()) && ((*z).Filled == false) && ((*z).Frozen == false)
}
-// MaxSize returns a maximum valid message size for this message type
+// ProposalSeekerMaxSize returns a maximum valid message size for this message type
func ProposalSeekerMaxSize() (s int) {
s = 1 + 7 + VoteMaxSize() + 7 + msgp.BoolSize + 7 + msgp.BoolSize
return
@@ -6099,7 +6099,7 @@ func (z *proposalStore) MsgIsZero() bool {
return (len((*z).Relevant) == 0) && ((*z).Pinned.MsgIsZero()) && (len((*z).Assemblers) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// ProposalStoreMaxSize returns a maximum valid message size for this message type
func ProposalStoreMaxSize() (s int) {
s = 1 + 9
s += msgp.MapHeaderSize
@@ -6343,7 +6343,7 @@ func (z *proposalTable) MsgIsZero() bool {
return (len((*z).Pending) == 0) && ((*z).PendingNext == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// ProposalTableMaxSize returns a maximum valid message size for this message type
func ProposalTableMaxSize() (s int) {
s = 1 + 8
s += msgp.MapHeaderSize
@@ -6555,7 +6555,7 @@ func (z *proposalTracker) MsgIsZero() bool {
return (len((*z).Duplicate) == 0) && ((*z).Freezer.MsgIsZero()) && ((*z).Staging.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// ProposalTrackerMaxSize returns a maximum valid message size for this message type
func ProposalTrackerMaxSize() (s int) {
s = 1 + 10
s += msgp.MapHeaderSize
@@ -6715,7 +6715,7 @@ func (z *proposalTrackerContract) MsgIsZero() bool {
return ((*z).SawOneVote == false) && ((*z).Froze == false) && ((*z).SawSoftThreshold == false) && ((*z).SawCertThreshold == false)
}
-// MaxSize returns a maximum valid message size for this message type
+// ProposalTrackerContractMaxSize returns a maximum valid message size for this message type
func ProposalTrackerContractMaxSize() (s int) {
s = 1 + 11 + msgp.BoolSize + 6 + msgp.BoolSize + 17 + msgp.BoolSize + 17 + msgp.BoolSize
return
@@ -6912,7 +6912,7 @@ func (z *proposalValue) MsgIsZero() bool {
return ((*z).OriginalPeriod == 0) && ((*z).OriginalProposer.MsgIsZero()) && ((*z).BlockDigest.MsgIsZero()) && ((*z).EncodingDigest.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// ProposalValueMaxSize returns a maximum valid message size for this message type
func ProposalValueMaxSize() (s int) {
s = 1 + 5 + msgp.Uint64Size + 6 + basics.AddressMaxSize() + 4 + crypto.DigestMaxSize() + 7 + crypto.DigestMaxSize()
return
@@ -7105,7 +7105,7 @@ func (z *proposalVoteCounter) MsgIsZero() bool {
return ((*z).Count == 0) && (len((*z).Votes) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// ProposalVoteCounterMaxSize returns a maximum valid message size for this message type
func ProposalVoteCounterMaxSize() (s int) {
s = 1 + 6 + msgp.Uint64Size + 6
s += msgp.MapHeaderSize
@@ -7231,7 +7231,7 @@ func (z *proposerSeed) MsgIsZero() bool {
return ((*z).Addr.MsgIsZero()) && ((*z).VRF.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// ProposerSeedMaxSize returns a maximum valid message size for this message type
func ProposerSeedMaxSize() (s int) {
s = 1 + 5 + basics.AddressMaxSize() + 4 + crypto.VrfOutputMaxSize()
return
@@ -7459,7 +7459,7 @@ func (z *rawVote) MsgIsZero() bool {
return ((*z).Sender.MsgIsZero()) && ((*z).Round.MsgIsZero()) && ((*z).Period == 0) && ((*z).Step == 0) && ((*z).Proposal.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// RawVoteMaxSize returns a maximum valid message size for this message type
func RawVoteMaxSize() (s int) {
s = 1 + 4 + basics.AddressMaxSize() + 4 + basics.RoundMaxSize() + 4 + msgp.Uint64Size + 5 + msgp.Uint64Size + 5 + ProposalValueMaxSize()
return
@@ -7846,7 +7846,7 @@ func (z *rootRouter) MsgIsZero() bool {
return (len((*z).Children) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// RootRouterMaxSize returns a maximum valid message size for this message type
func RootRouterMaxSize() (s int) {
s = 1 + 16 + 1 + 15 + 1 + 9
s += msgp.MapHeaderSize
@@ -8222,7 +8222,7 @@ func (z *roundRouter) MsgIsZero() bool {
return ((*z).ProposalStore.MsgIsZero()) && (((*z).VoteTrackerRound.Freshest.MsgIsZero()) && ((*z).VoteTrackerRound.Ok == false)) && (len((*z).Children) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// RoundRouterMaxSize returns a maximum valid message size for this message type
func RoundRouterMaxSize() (s int) {
s = 1 + 14 + ProposalStoreMaxSize() + 17 + 1 + 9 + ThresholdEventMaxSize() + 3 + msgp.BoolSize + 9
s += msgp.MapHeaderSize
@@ -8348,7 +8348,7 @@ func (z *seedInput) MsgIsZero() bool {
return ((*z).Alpha.MsgIsZero()) && ((*z).History.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// SeedInputMaxSize returns a maximum valid message size for this message type
func SeedInputMaxSize() (s int) {
s = 1 + 6 + crypto.DigestMaxSize() + 5 + crypto.DigestMaxSize()
return
@@ -8523,7 +8523,7 @@ func (z *selector) MsgIsZero() bool {
return ((*z).Seed.MsgIsZero()) && ((*z).Round.MsgIsZero()) && ((*z).Period == 0) && ((*z).Step == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// SelectorMaxSize returns a maximum valid message size for this message type
func SelectorMaxSize() (s int) {
s = 1 + 5 + committee.SeedMaxSize() + 4 + basics.RoundMaxSize() + 4 + msgp.Uint64Size + 5 + msgp.Uint64Size
return
@@ -8583,7 +8583,7 @@ func (z serializableError) MsgIsZero() bool {
return z == ""
}
-// MaxSize returns a maximum valid message size for this message type
+// SerializableErrorMaxSize returns a maximum valid message size for this message type
func SerializableErrorMaxSize() (s int) {
panic("Unable to determine max size: String type string(z) is unbounded")
}
@@ -8642,7 +8642,7 @@ func (z step) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// StepMaxSize returns a maximum valid message size for this message type
func StepMaxSize() (s int) {
s = msgp.Uint64Size
return
@@ -8767,7 +8767,7 @@ func (z *stepRouter) MsgIsZero() bool {
return ((*z).VoteTracker.MsgIsZero()) && ((*z).VoteTrackerContract.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// StepRouterMaxSize returns a maximum valid message size for this message type
func StepRouterMaxSize() (s int) {
s = 1 + 12 + VoteTrackerMaxSize() + 20 + VoteTrackerContractMaxSize()
return
@@ -9001,7 +9001,7 @@ func (z *thresholdEvent) MsgIsZero() bool {
return ((*z).T == 0) && ((*z).Round.MsgIsZero()) && ((*z).Period == 0) && ((*z).Step == 0) && ((*z).Proposal.MsgIsZero()) && ((*z).Bundle.MsgIsZero()) && ((*z).Proto.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// ThresholdEventMaxSize returns a maximum valid message size for this message type
func ThresholdEventMaxSize() (s int) {
s = 1 + 2 + msgp.Uint8Size + 6 + basics.RoundMaxSize() + 7 + msgp.Uint64Size + 5 + msgp.Uint64Size + 9 + ProposalValueMaxSize() + 7 + UnauthenticatedBundleMaxSize() + 6 + protocol.ConsensusVersionMaxSize()
return
@@ -10162,7 +10162,7 @@ func (z *transmittedPayload) MsgIsZero() bool {
return ((*z).unauthenticatedProposal.Block.BlockHeader.Round.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Branch.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Branch512.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Seed.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnCommitments.NativeSha512_256Commitment.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnCommitments.Sha256Commitment.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnCommitments.Sha512Commitment.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.TimeStamp == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.GenesisID == "") && ((*z).unauthenticatedProposal.Block.BlockHeader.GenesisHash.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Proposer.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.FeesCollected.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.Bonus.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.ProposerPayout.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.FeeSink.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsPool.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsLevel == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRate == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsResidue == 0) && ((*z).unauthenticatedProposal.Block.BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocol.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolApprovals.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).unauthenticatedProposal.Block.BlockHeader.UpgradeVote.UpgradeApprove == false) && ((*z).unauthenticatedProposal.Block.BlockHeader.TxnCounter == 0) && (len((*z).unauthenticatedProposal.Block.BlockHeader.StateProofTracking) == 0) && (len((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) == 0) && (len((*z).unauthenticatedProposal.Block.BlockHeader.ParticipationUpdates.AbsentParticipationAccounts) == 0) && ((*z).unauthenticatedProposal.Block.Payset.MsgIsZero()) && ((*z).unauthenticatedProposal.SeedProof.MsgIsZero()) && ((*z).unauthenticatedProposal.OriginalPeriod == 0) && ((*z).unauthenticatedProposal.OriginalProposer.MsgIsZero()) && ((*z).PriorVote.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// TransmittedPayloadMaxSize returns a maximum valid message size for this message type
func TransmittedPayloadMaxSize() (s int) {
s = 3 + 4 + basics.RoundMaxSize() + 5 + bookkeeping.BlockHashMaxSize() + 8 + crypto.Sha512DigestMaxSize() + 5 + committee.SeedMaxSize() + 4 + crypto.DigestMaxSize() + 7 + crypto.DigestMaxSize() + 7 + crypto.Sha512DigestMaxSize() + 3 + msgp.Int64Size + 4 + msgp.StringPrefixSize + bounds.MaxGenesisIDLen + 3 + crypto.DigestMaxSize() + 4 + basics.AddressMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 5 + basics.AddressMaxSize() + 4 + basics.AddressMaxSize() + 5 + msgp.Uint64Size + 5 + msgp.Uint64Size + 5 + msgp.Uint64Size + 7 + basics.RoundMaxSize() + 6 + protocol.ConsensusVersionMaxSize() + 10 + protocol.ConsensusVersionMaxSize() + 8 + basics.RoundMaxSize() + 11 + basics.RoundMaxSize() + 11 + basics.RoundMaxSize() + 12 + protocol.ConsensusVersionMaxSize() + 13 + basics.RoundMaxSize() + 11 + msgp.BoolSize + 3 + msgp.Uint64Size + 4
s += msgp.MapHeaderSize
@@ -10533,7 +10533,7 @@ func (z *unauthenticatedBundle) MsgIsZero() bool {
return ((*z).Round.MsgIsZero()) && ((*z).Period == 0) && ((*z).Step == 0) && ((*z).Proposal.MsgIsZero()) && (len((*z).Votes) == 0) && (len((*z).EquivocationVotes) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// UnauthenticatedBundleMaxSize returns a maximum valid message size for this message type
func UnauthenticatedBundleMaxSize() (s int) {
s = 1 + 4 + basics.RoundMaxSize() + 4 + msgp.Uint64Size + 5 + msgp.Uint64Size + 5 + ProposalValueMaxSize() + 5
// Calculating size of slice: z.Votes
@@ -10873,7 +10873,7 @@ func (z *unauthenticatedEquivocationVote) MsgIsZero() bool {
return ((*z).Sender.MsgIsZero()) && ((*z).Round.MsgIsZero()) && ((*z).Period == 0) && ((*z).Step == 0) && ((*z).Cred.MsgIsZero()) && (((*z).Proposals[0].MsgIsZero()) && ((*z).Proposals[1].MsgIsZero())) && (((*z).Sigs[0].MsgIsZero()) && ((*z).Sigs[1].MsgIsZero()))
}
-// MaxSize returns a maximum valid message size for this message type
+// UnauthenticatedEquivocationVoteMaxSize returns a maximum valid message size for this message type
func UnauthenticatedEquivocationVoteMaxSize() (s int) {
s = 1 + 4 + basics.AddressMaxSize() + 4 + basics.RoundMaxSize() + 4 + msgp.Uint64Size + 5 + msgp.Uint64Size + 5 + committee.UnauthenticatedCredentialMaxSize() + 6
// Calculating size of array: z.Proposals
@@ -12016,7 +12016,7 @@ func (z *unauthenticatedProposal) MsgIsZero() bool {
return ((*z).Block.BlockHeader.Round.MsgIsZero()) && ((*z).Block.BlockHeader.Branch.MsgIsZero()) && ((*z).Block.BlockHeader.Branch512.MsgIsZero()) && ((*z).Block.BlockHeader.Seed.MsgIsZero()) && ((*z).Block.BlockHeader.TxnCommitments.NativeSha512_256Commitment.MsgIsZero()) && ((*z).Block.BlockHeader.TxnCommitments.Sha256Commitment.MsgIsZero()) && ((*z).Block.BlockHeader.TxnCommitments.Sha512Commitment.MsgIsZero()) && ((*z).Block.BlockHeader.TimeStamp == 0) && ((*z).Block.BlockHeader.GenesisID == "") && ((*z).Block.BlockHeader.GenesisHash.MsgIsZero()) && ((*z).Block.BlockHeader.Proposer.MsgIsZero()) && ((*z).Block.BlockHeader.FeesCollected.MsgIsZero()) && ((*z).Block.BlockHeader.Bonus.MsgIsZero()) && ((*z).Block.BlockHeader.ProposerPayout.MsgIsZero()) && ((*z).Block.BlockHeader.RewardsState.FeeSink.MsgIsZero()) && ((*z).Block.BlockHeader.RewardsState.RewardsPool.MsgIsZero()) && ((*z).Block.BlockHeader.RewardsState.RewardsLevel == 0) && ((*z).Block.BlockHeader.RewardsState.RewardsRate == 0) && ((*z).Block.BlockHeader.RewardsState.RewardsResidue == 0) && ((*z).Block.BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.NextProtocol.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.NextProtocolApprovals.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).Block.BlockHeader.UpgradeVote.UpgradeApprove == false) && ((*z).Block.BlockHeader.TxnCounter == 0) && (len((*z).Block.BlockHeader.StateProofTracking) == 0) && (len((*z).Block.BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) == 0) && (len((*z).Block.BlockHeader.ParticipationUpdates.AbsentParticipationAccounts) == 0) && ((*z).Block.Payset.MsgIsZero()) && ((*z).SeedProof.MsgIsZero()) && ((*z).OriginalPeriod == 0) && ((*z).OriginalProposer.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// UnauthenticatedProposalMaxSize returns a maximum valid message size for this message type
func UnauthenticatedProposalMaxSize() (s int) {
s = 3 + 4 + basics.RoundMaxSize() + 5 + bookkeeping.BlockHashMaxSize() + 8 + crypto.Sha512DigestMaxSize() + 5 + committee.SeedMaxSize() + 4 + crypto.DigestMaxSize() + 7 + crypto.DigestMaxSize() + 7 + crypto.Sha512DigestMaxSize() + 3 + msgp.Int64Size + 4 + msgp.StringPrefixSize + bounds.MaxGenesisIDLen + 3 + crypto.DigestMaxSize() + 4 + basics.AddressMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 5 + basics.AddressMaxSize() + 4 + basics.AddressMaxSize() + 5 + msgp.Uint64Size + 5 + msgp.Uint64Size + 5 + msgp.Uint64Size + 7 + basics.RoundMaxSize() + 6 + protocol.ConsensusVersionMaxSize() + 10 + protocol.ConsensusVersionMaxSize() + 8 + basics.RoundMaxSize() + 11 + basics.RoundMaxSize() + 11 + basics.RoundMaxSize() + 12 + protocol.ConsensusVersionMaxSize() + 13 + basics.RoundMaxSize() + 11 + msgp.BoolSize + 3 + msgp.Uint64Size + 4
s += msgp.MapHeaderSize
@@ -12197,7 +12197,7 @@ func (z *unauthenticatedVote) MsgIsZero() bool {
return ((*z).R.MsgIsZero()) && ((*z).Cred.MsgIsZero()) && ((*z).Sig.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// UnauthenticatedVoteMaxSize returns a maximum valid message size for this message type
func UnauthenticatedVoteMaxSize() (s int) {
s = 1 + 2 + RawVoteMaxSize() + 5 + committee.UnauthenticatedCredentialMaxSize() + 4 + crypto.OneTimeSignatureMaxSize()
return
@@ -12363,7 +12363,7 @@ func (z *vote) MsgIsZero() bool {
return ((*z).R.MsgIsZero()) && ((*z).Cred.MsgIsZero()) && ((*z).Sig.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// VoteMaxSize returns a maximum valid message size for this message type
func VoteMaxSize() (s int) {
s = 1 + 2 + RawVoteMaxSize() + 5 + committee.CredentialMaxSize() + 4 + crypto.OneTimeSignatureMaxSize()
return
@@ -12455,7 +12455,7 @@ func (z *voteAggregator) MsgIsZero() bool {
return true
}
-// MaxSize returns a maximum valid message size for this message type
+// VoteAggregatorMaxSize returns a maximum valid message size for this message type
func VoteAggregatorMaxSize() (s int) {
s = 1
return
@@ -12609,7 +12609,7 @@ func (z *voteAuthenticator) MsgIsZero() bool {
return ((*z).Sender.MsgIsZero()) && ((*z).Cred.MsgIsZero()) && ((*z).Sig.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// VoteAuthenticatorMaxSize returns a maximum valid message size for this message type
func VoteAuthenticatorMaxSize() (s int) {
s = 1 + 4 + basics.AddressMaxSize() + 5 + committee.UnauthenticatedCredentialMaxSize() + 4 + crypto.OneTimeSignatureMaxSize()
return
@@ -12975,7 +12975,7 @@ func (z *voteTracker) MsgIsZero() bool {
return (len((*z).Voters) == 0) && (len((*z).Counts) == 0) && (len((*z).Equivocators) == 0) && ((*z).EquivocatorsCount == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// VoteTrackerMaxSize returns a maximum valid message size for this message type
func VoteTrackerMaxSize() (s int) {
s = 1 + 7
s += msgp.MapHeaderSize
@@ -13126,7 +13126,7 @@ func (z *voteTrackerContract) MsgIsZero() bool {
return ((*z).Step == 0) && ((*z).StepOk == false) && ((*z).Emitted == false)
}
-// MaxSize returns a maximum valid message size for this message type
+// VoteTrackerContractMaxSize returns a maximum valid message size for this message type
func VoteTrackerContractMaxSize() (s int) {
s = 1 + 5 + msgp.Uint64Size + 7 + msgp.BoolSize + 8 + msgp.BoolSize
return
@@ -13368,7 +13368,7 @@ func (z *voteTrackerPeriod) MsgIsZero() bool {
return (((*z).Cached.Bottom == false) && ((*z).Cached.Proposal.MsgIsZero()))
}
-// MaxSize returns a maximum valid message size for this message type
+// VoteTrackerPeriodMaxSize returns a maximum valid message size for this message type
func VoteTrackerPeriodMaxSize() (s int) {
s = 1 + 7 + 1 + 7 + msgp.BoolSize + 9 + ProposalValueMaxSize()
return
@@ -13493,7 +13493,7 @@ func (z *voteTrackerRound) MsgIsZero() bool {
return ((*z).Freshest.MsgIsZero()) && ((*z).Ok == false)
}
-// MaxSize returns a maximum valid message size for this message type
+// VoteTrackerRoundMaxSize returns a maximum valid message size for this message type
func VoteTrackerRoundMaxSize() (s int) {
s = 1 + 9 + ThresholdEventMaxSize() + 3 + msgp.BoolSize
return
diff --git a/agreement/msgp_gen_test.go b/agreement/msgp_gen_test.go
index 2d3952add9..3c39a19979 100644
--- a/agreement/msgp_gen_test.go
+++ b/agreement/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package agreement
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package agreement
+
import (
"testing"
diff --git a/agreement/params.go b/agreement/params.go
index 09685f4918..cc0b8a70ab 100644
--- a/agreement/params.go
+++ b/agreement/params.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/persistence.go b/agreement/persistence.go
index 4bcda1c5bd..90841d4115 100644
--- a/agreement/persistence.go
+++ b/agreement/persistence.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/persistence_test.go b/agreement/persistence_test.go
index 3380833507..2cfac49ec6 100644
--- a/agreement/persistence_test.go
+++ b/agreement/persistence_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/player.go b/agreement/player.go
index 6336df9825..d6019d95c6 100644
--- a/agreement/player.go
+++ b/agreement/player.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/playerContract.go b/agreement/playerContract.go
index faa83f699e..6ee0a719fe 100644
--- a/agreement/playerContract.go
+++ b/agreement/playerContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/player_permutation_test.go b/agreement/player_permutation_test.go
index 81e7cc13c0..68cce957e6 100644
--- a/agreement/player_permutation_test.go
+++ b/agreement/player_permutation_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/player_test.go b/agreement/player_test.go
index 0095806041..d8697d544f 100644
--- a/agreement/player_test.go
+++ b/agreement/player_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposal.go b/agreement/proposal.go
index c74ce2b7a0..ca819768ed 100644
--- a/agreement/proposal.go
+++ b/agreement/proposal.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalManager.go b/agreement/proposalManager.go
index bde20fc67e..c6b187e31f 100644
--- a/agreement/proposalManager.go
+++ b/agreement/proposalManager.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -289,7 +289,7 @@ func proposalUsefulForCredentialHistory(curRound round, vote unauthenticatedVote
return false
}
-// voteFresh determines whether a proposal satisfies freshness rules.
+// proposalFresh determines whether a proposal satisfies freshness rules.
func proposalFresh(freshData freshnessData, vote unauthenticatedVote) error {
switch vote.R.Round {
case freshData.PlayerRound:
diff --git a/agreement/proposalManagerContract.go b/agreement/proposalManagerContract.go
index 00c3cb20fd..3a27c257eb 100644
--- a/agreement/proposalManagerContract.go
+++ b/agreement/proposalManagerContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalManager_test.go b/agreement/proposalManager_test.go
index e45f51058a..5a5c1d0387 100644
--- a/agreement/proposalManager_test.go
+++ b/agreement/proposalManager_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalStore.go b/agreement/proposalStore.go
index 9f8995add6..1e798a9214 100644
--- a/agreement/proposalStore.go
+++ b/agreement/proposalStore.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalStoreContract.go b/agreement/proposalStoreContract.go
index 22c9b14b98..eaebd5b584 100644
--- a/agreement/proposalStoreContract.go
+++ b/agreement/proposalStoreContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalStore_test.go b/agreement/proposalStore_test.go
index 4228e61951..ddd490b175 100644
--- a/agreement/proposalStore_test.go
+++ b/agreement/proposalStore_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalTable.go b/agreement/proposalTable.go
index 9d1d736fec..29a62191f8 100644
--- a/agreement/proposalTable.go
+++ b/agreement/proposalTable.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalTracker.go b/agreement/proposalTracker.go
index 0b23f198b2..9f78d63d6d 100644
--- a/agreement/proposalTracker.go
+++ b/agreement/proposalTracker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalTrackerContract.go b/agreement/proposalTrackerContract.go
index c6e944422d..42c3da9719 100644
--- a/agreement/proposalTrackerContract.go
+++ b/agreement/proposalTrackerContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/proposalTracker_test.go b/agreement/proposalTracker_test.go
index 4202dc0429..9cd9f07f70 100644
--- a/agreement/proposalTracker_test.go
+++ b/agreement/proposalTracker_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -158,7 +158,7 @@ func makeProposalTrackerZero() listener {
}
func (s *proposalTrackerTestShadow) execute(t *testing.T, errstr string) {
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: s.inputs,
expectedOutputs: s.outputs,
}
diff --git a/agreement/proposal_test.go b/agreement/proposal_test.go
index ac1463b569..4aa798bcfa 100644
--- a/agreement/proposal_test.go
+++ b/agreement/proposal_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/pseudonode.go b/agreement/pseudonode.go
index c0699c6ccb..222e6e8616 100644
--- a/agreement/pseudonode.go
+++ b/agreement/pseudonode.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/pseudonode_test.go b/agreement/pseudonode_test.go
index f8ae6548e7..dfb10ab088 100644
--- a/agreement/pseudonode_test.go
+++ b/agreement/pseudonode_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/router.go b/agreement/router.go
index 146a3d1250..665145b47a 100644
--- a/agreement/router.go
+++ b/agreement/router.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -27,7 +27,7 @@ import (
//msgp:ignore stateMachineTag
type stateMachineTag int
-//go:generate stringer -type=stateMachineTag
+//go:generate go tool -modfile=../tool.mod stringer -type=stateMachineTag
const (
demultiplexer stateMachineTag = iota // type demux
diff --git a/agreement/selector.go b/agreement/selector.go
index 91d559ffdc..b02aef9894 100644
--- a/agreement/selector.go
+++ b/agreement/selector.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/service.go b/agreement/service.go
index a3339bbc91..bcbc442b25 100644
--- a/agreement/service.go
+++ b/agreement/service.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/service_test.go b/agreement/service_test.go
index b46aefb659..27f35fba0f 100644
--- a/agreement/service_test.go
+++ b/agreement/service_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/sort.go b/agreement/sort.go
index d8b3006642..98a02b7b16 100644
--- a/agreement/sort.go
+++ b/agreement/sort.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/sort_test.go b/agreement/sort_test.go
index 11163abcc5..87ac1594ff 100644
--- a/agreement/sort_test.go
+++ b/agreement/sort_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/state_machine_test.go b/agreement/state_machine_test.go
index 437ec6799a..6fbcfc12f7 100644
--- a/agreement/state_machine_test.go
+++ b/agreement/state_machine_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -392,7 +392,7 @@ func (blackhole) Write(data []byte) (int, error) {
}
// deterministicTraceTestCase encapsulates a traditional unit test case.
-type determisticTraceTestCase struct {
+type deterministicTraceTestCase struct {
inputs []event
expectedOutputs []event
safetyProps []ioSafetyProp
@@ -400,13 +400,13 @@ type determisticTraceTestCase struct {
// Validate takes a given automata at zero state, drives it with the test case input,
// and validates the output.
-func (testCase *determisticTraceTestCase) Validate(automaton ioAutomata) (invalidErr error, runtimeErr error) {
+func (testCase *deterministicTraceTestCase) Validate(automaton ioAutomata) (invalidErr error, runtimeErr error) {
return testCase.ValidateAsExtension(automaton)
}
// ValidateAsExtension takes a given automata that is already in some state, drives it
// with some addition input (an "extension"), and validates the output.
-func (testCase *determisticTraceTestCase) ValidateAsExtension(automaton ioAutomata) (invalidErr error, runtimeErr error) {
+func (testCase *deterministicTraceTestCase) ValidateAsExtension(automaton ioAutomata) (invalidErr error, runtimeErr error) {
// suppress error logging from contract-checkers
logging.Base().SetOutput(blackhole{})
defer func() {
@@ -502,8 +502,8 @@ type testCaseBuilder struct {
safetyProps []ioSafetyProp
}
-func (b *testCaseBuilder) Build() *determisticTraceTestCase {
- return &determisticTraceTestCase{b.inputs, b.expectedOutputs, b.safetyProps}
+func (b *testCaseBuilder) Build() *deterministicTraceTestCase {
+ return &deterministicTraceTestCase{b.inputs, b.expectedOutputs, b.safetyProps}
}
func (b *testCaseBuilder) AddInOutPair(input event, output event) {
diff --git a/agreement/statemachinetag_string.go b/agreement/statemachinetag_string.go
index ea8b188d71..ddf8808de3 100644
--- a/agreement/statemachinetag_string.go
+++ b/agreement/statemachinetag_string.go
@@ -24,8 +24,9 @@ const _stateMachineTag_name = "demultiplexerplayerMachinevoteMachinevoteMachineR
var _stateMachineTag_index = [...]uint8{0, 13, 26, 37, 53, 70, 85, 100, 120, 141}
func (i stateMachineTag) String() string {
- if i < 0 || i >= stateMachineTag(len(_stateMachineTag_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_stateMachineTag_index)-1 {
return "stateMachineTag(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _stateMachineTag_name[_stateMachineTag_index[i]:_stateMachineTag_index[i+1]]
+ return _stateMachineTag_name[_stateMachineTag_index[idx]:_stateMachineTag_index[idx+1]]
}
diff --git a/agreement/trace.go b/agreement/trace.go
index a7860cd996..184df42d11 100644
--- a/agreement/trace.go
+++ b/agreement/trace.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/traceTime.go b/agreement/traceTime.go
index 82d9deb521..af779eaea1 100644
--- a/agreement/traceTime.go
+++ b/agreement/traceTime.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/types.go b/agreement/types.go
index 2b0145b14d..dc3a309964 100644
--- a/agreement/types.go
+++ b/agreement/types.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -117,7 +117,7 @@ func (s step) nextVoteRanges(deadlineTimeout time.Duration) (lower, upper time.D
return lower, upper
}
-// ReachesQuorum compares the current weight to the thresholds appropriate for the step,
+// reachesQuorum compares the current weight to the thresholds appropriate for the step,
// to determine if we've reached a quorum.
func (s step) reachesQuorum(proto config.ConsensusParams, weight uint64) bool {
switch s {
@@ -162,7 +162,7 @@ func (s step) threshold(proto config.ConsensusParams) uint64 {
}
}
-// CommitteeSize returns the size of the committee required for the step
+// committeeSize returns the size of the committee required for the step
func (s step) committeeSize(proto config.ConsensusParams) uint64 {
switch s {
case propose:
diff --git a/agreement/vote.go b/agreement/vote.go
index 5727f5f91b..22d21252ce 100644
--- a/agreement/vote.go
+++ b/agreement/vote.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteAggregator.go b/agreement/voteAggregator.go
index fc60d4ce6d..4d4490bf3e 100644
--- a/agreement/voteAggregator.go
+++ b/agreement/voteAggregator.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteAggregatorContract.go b/agreement/voteAggregatorContract.go
index fba3e42f8e..614cbf3c67 100644
--- a/agreement/voteAggregatorContract.go
+++ b/agreement/voteAggregatorContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteAggregator_test.go b/agreement/voteAggregator_test.go
index 1a690e8e76..86fcc4e03a 100644
--- a/agreement/voteAggregator_test.go
+++ b/agreement/voteAggregator_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteAuxiliary.go b/agreement/voteAuxiliary.go
index 42ba607d25..fd275100f6 100644
--- a/agreement/voteAuxiliary.go
+++ b/agreement/voteAuxiliary.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteAuxiliaryContract.go b/agreement/voteAuxiliaryContract.go
index cb58df59cf..1b03a728fc 100644
--- a/agreement/voteAuxiliaryContract.go
+++ b/agreement/voteAuxiliaryContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteAuxiliary_test.go b/agreement/voteAuxiliary_test.go
index 181f98ae9e..2a1925a92a 100644
--- a/agreement/voteAuxiliary_test.go
+++ b/agreement/voteAuxiliary_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -85,7 +85,7 @@ func TestVoteTrackerPeriodStepCachedThresholdPrivate(t *testing.T) {
}
// this is just piped up from the vote tracker... (for now)
expectedOutputs[len(expectedOutputs)-1] = thresholdEvent{T: nextThreshold, Proposal: bottom}
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -117,7 +117,7 @@ func TestVoteTrackerPeriodStepCachedThresholdPrivate(t *testing.T) {
expectedOutputs[i] = thresholdEvent{T: none}
}
expectedOutputs[len(expectedOutputs)-1] = thresholdEvent{T: nextThreshold, Proposal: fixedPVal}
- extensionTestCase := determisticTraceTestCase{
+ extensionTestCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
diff --git a/agreement/voteTracker.go b/agreement/voteTracker.go
index 7ca9b54a81..996ecbd33b 100644
--- a/agreement/voteTracker.go
+++ b/agreement/voteTracker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteTrackerContract.go b/agreement/voteTrackerContract.go
index 972039a9d0..2802d935f9 100644
--- a/agreement/voteTrackerContract.go
+++ b/agreement/voteTrackerContract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/agreement/voteTracker_test.go b/agreement/voteTracker_test.go
index a7186049f9..f353d8d0c7 100644
--- a/agreement/voteTracker_test.go
+++ b/agreement/voteTracker_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -43,7 +43,7 @@ func TestVoteTrackerNoOp(t *testing.T) {
helper.Setup()
voteAcceptEvent := helper.MakeValidVoteAccepted(t, 0, soft)
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: []event{
voteAcceptEvent,
},
@@ -77,7 +77,7 @@ func TestVoteTrackerSoftQuorum(t *testing.T) {
}
// given quorum of soft votes, we expect to see soft threshold
expectedOutputs[len(expectedOutputs)-1] = thresholdEvent{T: softThreshold, Proposal: *helper.proposal}
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -91,7 +91,7 @@ func TestVoteTrackerSoftQuorum(t *testing.T) {
// now, do the same thing, but have one less vote, so expect no threshold
inputVotes = inputVotes[:len(inputVotes)-1]
expectedOutputs = expectedOutputs[:len(expectedOutputs)-1]
- testCaseNoThreshold := determisticTraceTestCase{
+ testCaseNoThreshold := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -120,7 +120,7 @@ func TestVoteTrackerCertQuorum(t *testing.T) {
expectedOutputs[i] = thresholdEvent{T: none}
}
expectedOutputs[len(expectedOutputs)-1] = thresholdEvent{T: certThreshold, Proposal: *helper.proposal}
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -134,7 +134,7 @@ func TestVoteTrackerCertQuorum(t *testing.T) {
// now, do the same thing, but have one less vote
inputVotes = inputVotes[:len(inputVotes)-1]
expectedOutputs = expectedOutputs[:len(expectedOutputs)-1]
- testCaseNoThreshold := determisticTraceTestCase{
+ testCaseNoThreshold := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -163,7 +163,7 @@ func TestVoteTrackerNextQuorum(t *testing.T) {
expectedOutputs[i] = thresholdEvent{T: none}
}
expectedOutputs[len(expectedOutputs)-1] = thresholdEvent{T: nextThreshold, Proposal: *helper.proposal}
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -177,7 +177,7 @@ func TestVoteTrackerNextQuorum(t *testing.T) {
// now, do the same thing, but have one less vote
inputVotes = inputVotes[:len(inputVotes)-1]
expectedOutputs = expectedOutputs[:len(expectedOutputs)-1]
- testCaseNoThreshold := determisticTraceTestCase{
+ testCaseNoThreshold := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -204,7 +204,7 @@ func TestVoteTrackerProposeNoOp(t *testing.T) {
// here, each input is a separate test-case
for i := 0; i < NumUpperBound; i++ {
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes[i : i+1],
expectedOutputs: nil, // we expect the input to panic
}
@@ -235,7 +235,7 @@ func TestVoteTrackerEquivocatorWeightCountedOnce(t *testing.T) {
inputVotes[NumThreshold-1] = helper.MakeValidVoteAccepted(t, 0, soft)
expectedOutputs[NumThreshold-1] = thresholdEvent{T: none}
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -274,7 +274,7 @@ func TestVoteTrackerEquivDoesntReemitThreshold(t *testing.T) {
inputVotes[NumThreshold+1] = helper.MakeValidVoteAccepted(t, int(NumThreshold+1), soft)
expectedOutputs[NumThreshold+1] = thresholdEvent{T: none}
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -322,7 +322,7 @@ func TestVoteTrackerEquivocationsCount(t *testing.T) {
}
expectedOutputs[TotalThreshold-1] = thresholdEvent{T: certThreshold, Proposal: equivVal1}
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -375,7 +375,7 @@ func TestVoteTrackerSuperEquivocationsCount(t *testing.T) {
}
expectedOutputs[TotalThreshold-1] = thresholdEvent{T: certThreshold, Proposal: equivVal1}
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -418,7 +418,7 @@ func TestVoteTrackerPanicsOnTwoSoftQuorums(t *testing.T) {
// the last output should be a panic. Express this by shortening expected outputs
expectedOutputs = expectedOutputs[:2*NumThreshold-1]
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -451,7 +451,7 @@ func TestVoteTrackerPanicsOnSoftBotQuorum(t *testing.T) {
// the last output should be a panic. Express this by shortening expected outputs
expectedOutputs = expectedOutputs[:NumThreshold-1]
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -492,7 +492,7 @@ func TestVoteTrackerPanicsOnTwoNextQuorums(t *testing.T) {
// the last output should be a panic. Express this by shortening expected outputs
expectedOutputs = expectedOutputs[:2*NumThreshold-1]
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -520,7 +520,7 @@ func TestVoteTrackerRejectsTooManyEquivocators(t *testing.T) {
// We should now have threshold many equivocators... should have panicked when the last equivocation was seen.
expectedOutputs[2*Num-2] = thresholdEvent{T: softThreshold, Proposal: inputVotes[2*Num-2].(voteAcceptedEvent).Vote.R.Proposal}
expectedOutputs = expectedOutputs[:2*Num-1]
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -554,7 +554,7 @@ func TestVoteTrackerFiltersDuplicateVoteOnce(t *testing.T) {
expectedOutputs[i] = filteredStepEvent{T: voteFilteredStep}
}
}
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -623,7 +623,7 @@ func TestVoteTrackerForwardsFirstEquivocation(t *testing.T) {
expectedOutputs[i] = filteredStepEvent{T: voteFilteredStep}
}
}
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -668,7 +668,7 @@ func TestVoteTrackerFiltersFutureEquivocations(t *testing.T) {
expectedOutputs[i] = filteredStepEvent{T: voteFilteredStep}
}
}
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: inputVotes,
expectedOutputs: expectedOutputs,
}
@@ -685,7 +685,7 @@ func TestVoteTrackerFiltersFutureEquivocations(t *testing.T) {
func TestVoteTrackerRejectsUnknownEvent(t *testing.T) {
partitiontest.PartitionTest(t)
- testCase := determisticTraceTestCase{
+ testCase := deterministicTraceTestCase{
inputs: []event{
emptyEvent{},
},
diff --git a/agreement/vote_test.go b/agreement/vote_test.go
index 9c5f74c8c7..baf2fbaaf7 100644
--- a/agreement/vote_test.go
+++ b/agreement/vote_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/catchup/catchpointService.go b/catchup/catchpointService.go
index 95ad1d9b42..72ac5f9347 100644
--- a/catchup/catchpointService.go
+++ b/catchup/catchpointService.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/catchup/catchpointService_test.go b/catchup/catchpointService_test.go
index 045223f44d..7427464632 100644
--- a/catchup/catchpointService_test.go
+++ b/catchup/catchpointService_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/catchup/classBasedPeerSelector.go b/catchup/classBasedPeerSelector.go
index 360228269b..3596f7c7f0 100644
--- a/catchup/classBasedPeerSelector.go
+++ b/catchup/classBasedPeerSelector.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/catchup/classBasedPeerSelector_test.go b/catchup/classBasedPeerSelector_test.go
index bfaa2100cf..ff1470f0c6 100644
--- a/catchup/classBasedPeerSelector_test.go
+++ b/catchup/classBasedPeerSelector_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/catchup/fetcher_test.go b/catchup/fetcher_test.go
index aee0cb8ea0..8c5cd2aae1 100644
--- a/catchup/fetcher_test.go
+++ b/catchup/fetcher_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/catchup/ledgerFetcher.go b/catchup/ledgerFetcher.go
index a2ec642b66..e4569d6e1a 100644
--- a/catchup/ledgerFetcher.go
+++ b/catchup/ledgerFetcher.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/catchup/ledgerFetcher_test.go b/catchup/ledgerFetcher_test.go
index 521b435413..c7e98466ea 100644
--- a/catchup/ledgerFetcher_test.go
+++ b/catchup/ledgerFetcher_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/catchup/peerSelector.go b/catchup/peerSelector.go
index f534fec5c5..ee867001f0 100644
--- a/catchup/peerSelector.go
+++ b/catchup/peerSelector.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/catchup/peerSelector_test.go b/catchup/peerSelector_test.go
index 8935851fa9..e8b40e8cca 100644
--- a/catchup/peerSelector_test.go
+++ b/catchup/peerSelector_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -625,7 +625,7 @@ func TestPeerSelector_ClassLowerBound(t *testing.T) {
}
}
-// TestPeerSelector_Eviction tests that the peer is evicted after several download failures, and it handles same address for different peer classes
+// TestPeerSelector_EvictionAndUpgrade tests that the peer is evicted after several download failures, and it handles same address for different peer classes
func TestPeerSelector_EvictionAndUpgrade(t *testing.T) {
partitiontest.PartitionTest(t)
diff --git a/catchup/pref_test.go b/catchup/pref_test.go
index b7078cc6b4..9f20be4aa9 100644
--- a/catchup/pref_test.go
+++ b/catchup/pref_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/catchup/service.go b/catchup/service.go
index 88180df457..590d38f3e1 100644
--- a/catchup/service.go
+++ b/catchup/service.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/catchup/service_test.go b/catchup/service_test.go
index 4d28ad92c9..e7993225ca 100644
--- a/catchup/service_test.go
+++ b/catchup/service_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/catchup/universalFetcher.go b/catchup/universalFetcher.go
index d7089a4256..5e49e11f67 100644
--- a/catchup/universalFetcher.go
+++ b/catchup/universalFetcher.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -36,7 +36,7 @@ import (
"github.com/algorand/go-algorand/rpcs"
)
-// UniversalFetcher fetches blocks either from an http peer or ws peer.
+// universalBlockFetcher fetches blocks either from an http peer or ws peer.
type universalBlockFetcher struct {
config config.Local
net network.GossipNode
diff --git a/catchup/universalFetcher_test.go b/catchup/universalFetcher_test.go
index 9d7c4d3e7e..567a722161 100644
--- a/catchup/universalFetcher_test.go
+++ b/catchup/universalFetcher_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algocfg/getCommand.go b/cmd/algocfg/getCommand.go
index 2cd7c3fb6f..0a90060641 100644
--- a/cmd/algocfg/getCommand.go
+++ b/cmd/algocfg/getCommand.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algocfg/getCommand_test.go b/cmd/algocfg/getCommand_test.go
index e4def43d96..96d66b2a40 100644
--- a/cmd/algocfg/getCommand_test.go
+++ b/cmd/algocfg/getCommand_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algocfg/main.go b/cmd/algocfg/main.go
index 26a89e52c6..f503514703 100644
--- a/cmd/algocfg/main.go
+++ b/cmd/algocfg/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algocfg/profileCommand.go b/cmd/algocfg/profileCommand.go
index ce81491dc6..74d8222231 100644
--- a/cmd/algocfg/profileCommand.go
+++ b/cmd/algocfg/profileCommand.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -108,6 +108,7 @@ var (
cfg.EnableP2PHybridMode = true
cfg.P2PHybridNetAddress = ":4190"
cfg.EnableDHTProviders = true
+ cfg.DHTMode = "server"
return cfg
},
}
@@ -127,6 +128,7 @@ var (
cfg.EnableP2PHybridMode = true
cfg.P2PHybridNetAddress = ":4190"
cfg.EnableDHTProviders = true
+ cfg.DHTMode = "server"
return cfg
},
}
@@ -138,6 +140,7 @@ var (
// P2P config defaults
cfg.EnableP2PHybridMode = true
cfg.EnableDHTProviders = true
+ cfg.DHTMode = "client"
return cfg
},
}
diff --git a/cmd/algocfg/profileCommand_test.go b/cmd/algocfg/profileCommand_test.go
index 2e7c62f2d7..e9914279b7 100644
--- a/cmd/algocfg/profileCommand_test.go
+++ b/cmd/algocfg/profileCommand_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -83,6 +83,7 @@ func Test_getConfigForArg(t *testing.T) {
require.True(t, cfg.EnableP2PHybridMode)
require.Equal(t, ":4190", cfg.P2PHybridNetAddress)
require.True(t, cfg.EnableDHTProviders)
+ require.Equal(t, "server", cfg.DHTMode)
})
t.Run("valid config test hybrid archival", func(t *testing.T) {
@@ -103,6 +104,7 @@ func Test_getConfigForArg(t *testing.T) {
require.True(t, cfg.EnableP2PHybridMode)
require.Equal(t, ":4190", cfg.P2PHybridNetAddress)
require.True(t, cfg.EnableDHTProviders)
+ require.Equal(t, "server", cfg.DHTMode)
})
t.Run("valid config test hybrid client", func(t *testing.T) {
@@ -124,5 +126,6 @@ func Test_getConfigForArg(t *testing.T) {
require.True(t, cfg.EnableP2PHybridMode)
require.Equal(t, "", cfg.P2PHybridNetAddress)
require.True(t, cfg.EnableDHTProviders)
+ require.Equal(t, "client", cfg.DHTMode)
})
}
diff --git a/cmd/algocfg/report.go b/cmd/algocfg/report.go
index 3f0a1c684e..ed41cbc7ad 100644
--- a/cmd/algocfg/report.go
+++ b/cmd/algocfg/report.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algocfg/resetCommand.go b/cmd/algocfg/resetCommand.go
index cd51e054d8..4b33ca54bd 100644
--- a/cmd/algocfg/resetCommand.go
+++ b/cmd/algocfg/resetCommand.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algocfg/setCommand.go b/cmd/algocfg/setCommand.go
index 651d101980..3022b19f26 100644
--- a/cmd/algocfg/setCommand.go
+++ b/cmd/algocfg/setCommand.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algod/main.go b/cmd/algod/main.go
index 7f36c866a2..4b1a3a2ed8 100644
--- a/cmd/algod/main.go
+++ b/cmd/algod/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algod/main_test.go b/cmd/algod/main_test.go
index 031acaaf71..725fa08c3c 100644
--- a/cmd/algod/main_test.go
+++ b/cmd/algod/main_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algofix/deadlock.go b/cmd/algofix/deadlock.go
index 24bab521ae..90cc98cec4 100644
--- a/cmd/algofix/deadlock.go
+++ b/cmd/algofix/deadlock.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algofix/deadlock_test.go b/cmd/algofix/deadlock_test.go
index 1f9103015b..2e13c4b7bc 100644
--- a/cmd/algofix/deadlock_test.go
+++ b/cmd/algofix/deadlock_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/blockWatcher.go b/cmd/algoh/blockWatcher.go
index 94fc9b088d..f8ddcce146 100644
--- a/cmd/algoh/blockWatcher.go
+++ b/cmd/algoh/blockWatcher.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/blockWatcher_test.go b/cmd/algoh/blockWatcher_test.go
index 33e0235ddd..8d3d2662ac 100644
--- a/cmd/algoh/blockWatcher_test.go
+++ b/cmd/algoh/blockWatcher_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/blockstats.go b/cmd/algoh/blockstats.go
index fecb5295c7..0a828b8ee0 100644
--- a/cmd/algoh/blockstats.go
+++ b/cmd/algoh/blockstats.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/blockstats_test.go b/cmd/algoh/blockstats_test.go
index a8f1cf1129..cf848e96f4 100644
--- a/cmd/algoh/blockstats_test.go
+++ b/cmd/algoh/blockstats_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -77,7 +77,7 @@ func TestEventWithDetails(t *testing.T) {
// Create blocks with some senders in the payload.
makeStxnWithAddr := func(addr basics.Address) transactions.SignedTxnInBlock {
- return transactions.SignedTxnInBlock{SignedTxnWithAD: transactions.SignedTxnWithAD{SignedTxn: transactions.SignedTxn{Txn: transactions.Transaction{Header: transactions.Header{Sender: addr}}}}}
+ return transactions.SignedTxnInBlock{SignedTxnWithAD: transactions.SignedTxn{Txn: transactions.Transaction{Header: transactions.Header{Sender: addr}}}.WithAD()}
}
addr := basics.Address{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
otherAddr := basics.Address{0x7, 0xda, 0xcb, 0x4b, 0x6d, 0x9e, 0xd1, 0x41, 0xb1, 0x75, 0x76, 0xbd, 0x45, 0x9a, 0xe6, 0x42, 0x1d, 0x48, 0x6d, 0xa3, 0xd4, 0xef, 0x22, 0x47, 0xc4, 0x9, 0xa3, 0x96, 0xb8, 0x2e, 0xa2, 0x21}
diff --git a/cmd/algoh/client.go b/cmd/algoh/client.go
index 2f610d529f..cde42f9978 100644
--- a/cmd/algoh/client.go
+++ b/cmd/algoh/client.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/deadman.go b/cmd/algoh/deadman.go
index dc1952205a..e9b6a0a4c1 100644
--- a/cmd/algoh/deadman.go
+++ b/cmd/algoh/deadman.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/eventsender.go b/cmd/algoh/eventsender.go
index 6ecdbb0964..4f5b94809f 100644
--- a/cmd/algoh/eventsender.go
+++ b/cmd/algoh/eventsender.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/main.go b/cmd/algoh/main.go
index 8c11658a09..a476d5b9c8 100644
--- a/cmd/algoh/main.go
+++ b/cmd/algoh/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algoh/mockClient.go b/cmd/algoh/mockClient.go
index a23481bb94..5edc9657d9 100644
--- a/cmd/algoh/mockClient.go
+++ b/cmd/algoh/mockClient.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/common.go b/cmd/algokey/common.go
index 456d09e4d0..636bfb95c7 100644
--- a/cmd/algokey/common.go
+++ b/cmd/algokey/common.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/export.go b/cmd/algokey/export.go
index 5f35853e88..00fc4076e9 100644
--- a/cmd/algokey/export.go
+++ b/cmd/algokey/export.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/generate.go b/cmd/algokey/generate.go
index 3bf6190d76..68300d0740 100644
--- a/cmd/algokey/generate.go
+++ b/cmd/algokey/generate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/import.go b/cmd/algokey/import.go
index 8d5c047719..0d75ee048b 100644
--- a/cmd/algokey/import.go
+++ b/cmd/algokey/import.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/keyreg.go b/cmd/algokey/keyreg.go
index e7604518ce..262dc43653 100644
--- a/cmd/algokey/keyreg.go
+++ b/cmd/algokey/keyreg.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/main.go b/cmd/algokey/main.go
index 42f447ca78..1ee42ab25b 100644
--- a/cmd/algokey/main.go
+++ b/cmd/algokey/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/multisig.go b/cmd/algokey/multisig.go
index 66322f4ed9..9db2e47160 100644
--- a/cmd/algokey/multisig.go
+++ b/cmd/algokey/multisig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/part.go b/cmd/algokey/part.go
index 0eb0816a71..272a6d66de 100644
--- a/cmd/algokey/part.go
+++ b/cmd/algokey/part.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algokey/sign.go b/cmd/algokey/sign.go
index 622404b6e1..faf827d33f 100644
--- a/cmd/algokey/sign.go
+++ b/cmd/algokey/sign.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algons/commands.go b/cmd/algons/commands.go
index dc8c1c4cbd..8d0265bec6 100644
--- a/cmd/algons/commands.go
+++ b/cmd/algons/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algons/dnsCmd.go b/cmd/algons/dnsCmd.go
index 971578e2d3..c58b6d58b3 100644
--- a/cmd/algons/dnsCmd.go
+++ b/cmd/algons/dnsCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algons/dnsaddrCmd.go b/cmd/algons/dnsaddrCmd.go
index 822f6e10ec..5517bf6cec 100644
--- a/cmd/algons/dnsaddrCmd.go
+++ b/cmd/algons/dnsaddrCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algorelay/commands.go b/cmd/algorelay/commands.go
index 95799b89cb..9b3cb9ea93 100644
--- a/cmd/algorelay/commands.go
+++ b/cmd/algorelay/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algorelay/eb/eb.go b/cmd/algorelay/eb/eb.go
index 42dad1fd71..a21b85c197 100644
--- a/cmd/algorelay/eb/eb.go
+++ b/cmd/algorelay/eb/eb.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/algorelay/relayCmd.go b/cmd/algorelay/relayCmd.go
index 7167c7f7cb..8feeb158bc 100644
--- a/cmd/algorelay/relayCmd.go
+++ b/cmd/algorelay/relayCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/buildtools/commands.go b/cmd/buildtools/commands.go
index a2ab347951..3ff4180875 100644
--- a/cmd/buildtools/commands.go
+++ b/cmd/buildtools/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/buildtools/genesis.go b/cmd/buildtools/genesis.go
index 794d22d1b0..1ac001ea6c 100644
--- a/cmd/buildtools/genesis.go
+++ b/cmd/buildtools/genesis.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchpointdump/bench.go b/cmd/catchpointdump/bench.go
index e2094ef9f4..c061011366 100644
--- a/cmd/catchpointdump/bench.go
+++ b/cmd/catchpointdump/bench.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchpointdump/bench_report.go b/cmd/catchpointdump/bench_report.go
index 7daabdb137..970486e926 100644
--- a/cmd/catchpointdump/bench_report.go
+++ b/cmd/catchpointdump/bench_report.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchpointdump/commands.go b/cmd/catchpointdump/commands.go
index 6334e42e07..2f50a7d066 100644
--- a/cmd/catchpointdump/commands.go
+++ b/cmd/catchpointdump/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchpointdump/database.go b/cmd/catchpointdump/database.go
index 23581376ac..bd2adfb1bb 100644
--- a/cmd/catchpointdump/database.go
+++ b/cmd/catchpointdump/database.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchpointdump/file.go b/cmd/catchpointdump/file.go
index 3a1075b4ab..50c68fd440 100644
--- a/cmd/catchpointdump/file.go
+++ b/cmd/catchpointdump/file.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchpointdump/info.go b/cmd/catchpointdump/info.go
index ea62434f26..dc20327922 100644
--- a/cmd/catchpointdump/info.go
+++ b/cmd/catchpointdump/info.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchpointdump/net.go b/cmd/catchpointdump/net.go
index 908b8d6c84..2c1fff884a 100644
--- a/cmd/catchpointdump/net.go
+++ b/cmd/catchpointdump/net.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchupsrv/download.go b/cmd/catchupsrv/download.go
index 74a18ac60e..e662004754 100644
--- a/cmd/catchupsrv/download.go
+++ b/cmd/catchupsrv/download.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchupsrv/download_test.go b/cmd/catchupsrv/download_test.go
index 5e576ff55a..bf80605300 100644
--- a/cmd/catchupsrv/download_test.go
+++ b/cmd/catchupsrv/download_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchupsrv/main.go b/cmd/catchupsrv/main.go
index d80ae2701f..6bfdae0f9f 100644
--- a/cmd/catchupsrv/main.go
+++ b/cmd/catchupsrv/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/catchupsrv/tarblocks.go b/cmd/catchupsrv/tarblocks.go
index 8c921eaa07..a74b445806 100644
--- a/cmd/catchupsrv/tarblocks.go
+++ b/cmd/catchupsrv/tarblocks.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/dbgen/main.go b/cmd/dbgen/main.go
index 82f54318fc..2a2e126228 100644
--- a/cmd/dbgen/main.go
+++ b/cmd/dbgen/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/diagcfg/main.go b/cmd/diagcfg/main.go
index 672968d47c..eb425227d4 100644
--- a/cmd/diagcfg/main.go
+++ b/cmd/diagcfg/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/diagcfg/messages.go b/cmd/diagcfg/messages.go
index ed1e2b9684..6cdd5cb439 100644
--- a/cmd/diagcfg/messages.go
+++ b/cmd/diagcfg/messages.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/diagcfg/metric.go b/cmd/diagcfg/metric.go
index df3c3649dc..3882ebacf0 100644
--- a/cmd/diagcfg/metric.go
+++ b/cmd/diagcfg/metric.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/diagcfg/telemetry.go b/cmd/diagcfg/telemetry.go
index c04481319c..d908c9873a 100644
--- a/cmd/diagcfg/telemetry.go
+++ b/cmd/diagcfg/telemetry.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/dispenser/server.go b/cmd/dispenser/server.go
index 19649a6be3..e6f314a334 100644
--- a/cmd/dispenser/server.go
+++ b/cmd/dispenser/server.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/genesis/newgenesis.go b/cmd/genesis/newgenesis.go
index 22c0801f24..b9b21c5908 100644
--- a/cmd/genesis/newgenesis.go
+++ b/cmd/genesis/newgenesis.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/account.go b/cmd/goal/account.go
index b7c4188c35..5a4a553c65 100644
--- a/cmd/goal/account.go
+++ b/cmd/goal/account.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -161,16 +161,12 @@ func init() {
changeOnlineCmd.Flags().StringVarP(&signerAddress, "signer", "S", "", "Address of key to sign with, if different due to rekeying")
changeOnlineCmd.Flags().BoolVarP(&online, "online", "o", true, "Set this account to online or offline")
changeOnlineCmd.Flags().Uint64VarP(&transactionFee, "fee", "f", 0, "The Fee to set on the status change transaction (defaults to suggested fee)")
- changeOnlineCmd.Flags().Uint64VarP((*uint64)(&firstValid), "firstRound", "", 0, "")
changeOnlineCmd.Flags().Uint64VarP((*uint64)(&firstValid), "firstvalid", "", 0, "FirstValid for the status change transaction (0 for current)")
- changeOnlineCmd.Flags().Uint64VarP((*uint64)(&numValidRounds), "validRounds", "", 0, "")
changeOnlineCmd.Flags().Uint64VarP((*uint64)(&numValidRounds), "validrounds", "v", 0, "The validity period for the status change transaction")
changeOnlineCmd.Flags().Uint64Var((*uint64)(&lastValid), "lastvalid", 0, "The last round where the transaction may be committed to the ledger")
changeOnlineCmd.Flags().StringVarP(&statusChangeLease, "lease", "x", "", "Lease value (base64, optional): no transaction may also acquire this lease until lastvalid")
changeOnlineCmd.Flags().StringVarP(&statusChangeTxFile, "txfile", "t", "", "Write status change transaction to this file")
changeOnlineCmd.Flags().BoolVarP(&noWaitAfterSend, "no-wait", "N", false, "Don't wait for transaction to commit")
- changeOnlineCmd.Flags().MarkDeprecated("firstRound", "use --firstvalid instead")
- changeOnlineCmd.Flags().MarkDeprecated("validRounds", "use --validrounds instead")
// addParticipationKey flags
addParticipationKeyCmd.Flags().StringVarP(&accountAddress, "address", "a", "", "Account to associate with the generated partkey")
@@ -217,15 +213,11 @@ func init() {
markNonparticipatingCmd.MarkFlagRequired("address")
markNonparticipatingCmd.Flags().StringVarP(&signerAddress, "signer", "S", "", "Address of key to sign with, if different from address due to rekeying")
markNonparticipatingCmd.Flags().Uint64VarP(&transactionFee, "fee", "f", 0, "The Fee to set on the status change transaction (defaults to suggested fee)")
- markNonparticipatingCmd.Flags().Uint64VarP((*uint64)(&firstValid), "firstRound", "", 0, "")
markNonparticipatingCmd.Flags().Uint64VarP((*uint64)(&firstValid), "firstvalid", "", 0, "FirstValid for the status change transaction (0 for current)")
- markNonparticipatingCmd.Flags().Uint64VarP((*uint64)(&numValidRounds), "validRounds", "", 0, "")
markNonparticipatingCmd.Flags().Uint64VarP((*uint64)(&numValidRounds), "validrounds", "v", 0, "The validity period for the status change transaction")
markNonparticipatingCmd.Flags().Uint64Var((*uint64)(&lastValid), "lastvalid", 0, "The last round where the transaction may be committed to the ledger")
markNonparticipatingCmd.Flags().StringVarP(&statusChangeTxFile, "txfile", "t", "", "Write status change transaction to this file, rather than posting to network")
markNonparticipatingCmd.Flags().BoolVarP(&noWaitAfterSend, "no-wait", "N", false, "Don't wait for transaction to commit")
- markNonparticipatingCmd.Flags().MarkDeprecated("firstRound", "use --firstvalid instead")
- markNonparticipatingCmd.Flags().MarkDeprecated("validRounds", "use --validrounds instead")
dumpCmd.Flags().StringVarP(&dumpOutFile, "outfile", "o", "", "Save balance record to specified output file")
dumpCmd.Flags().StringVarP(&accountAddress, "address", "a", "", "Account address to retrieve balance (required)")
diff --git a/cmd/goal/accountsList.go b/cmd/goal/accountsList.go
index 4276da0248..fb553971e6 100644
--- a/cmd/goal/accountsList.go
+++ b/cmd/goal/accountsList.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/application.go b/cmd/goal/application.go
index 3a3e931747..01614a49a1 100644
--- a/cmd/goal/application.go
+++ b/cmd/goal/application.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -27,7 +27,6 @@ import (
"os"
"strconv"
"strings"
- "time"
"github.com/spf13/cobra"
@@ -84,8 +83,7 @@ var (
// controls whether all these refs put into the old-style "foreign arrays" or the new-style tx.Access
appUseAccess bool
- appArgs []string
- appInputFilename string
+ appArgs []string
fetchLocal bool
fetchGlobal bool
@@ -111,24 +109,27 @@ func init() {
appCmd.PersistentFlags().StringSliceVar(&foreignAssets, "foreign-asset", nil, "Indexes of assets whose parameters are read in this transaction")
appCmd.PersistentFlags().StringArrayVar(&appStrBoxes, "box", nil, "A Box that may be accessed by this transaction. Use the same form as app-arg to name the box, preceded by an optional app-id and comma. Zero or omitted app-id indicates the box is accessible by the app being called.")
appCmd.PersistentFlags().StringSliceVar(&appStrAccounts, "app-account", nil, "Accounts that may be accessed from application logic")
- appCmd.PersistentFlags().StringSliceVar(&appStrHoldings, "holding", nil, "A Holding that may be accessed from application logic. An asset-id followed by a comma and an address")
- appCmd.PersistentFlags().StringSliceVar(&appStrLocals, "local", nil, "A Local State that may be accessed from application logic. An optional app-id and comma, followed by an address. Zero or omitted app-id indicates the local state for app being called.")
+ appCmd.PersistentFlags().StringSliceVar(&appStrHoldings, "holding", nil, "A Holding that may be accessed from application logic. An asset-id followed by a plus sign and an address")
+ appCmd.PersistentFlags().StringSliceVar(&appStrLocals, "local", nil, "A Local State that may be accessed from application logic. An optional app-id and a plus sign, followed by an address. Zero or omitted app-id indicates the local state for app being called.")
appCmd.PersistentFlags().BoolVar(&appUseAccess, "access", false, "Put references into the transaction's access list, instead of foreign arrays.")
- appCmd.PersistentFlags().StringVarP(&appInputFilename, "app-input", "i", "", "JSON file containing encoded arguments and inputs (mutually exclusive with app-arg, app-account, foreign-app, foreign-asset, local, holding, and box)")
appCmd.PersistentFlags().StringVar(&approvalProgFile, "approval-prog", "", "(Uncompiled) TEAL assembly program filename for approving/rejecting transactions")
appCmd.PersistentFlags().StringVar(&clearProgFile, "clear-prog", "", "(Uncompiled) TEAL assembly program filename for updating application state when a user clears their local state")
- appCmd.PersistentFlags().StringVar(&approvalProgRawFile, "approval-prog-raw", "", "Compiled TEAL program filename for approving/rejecting transactions")
- appCmd.PersistentFlags().StringVar(&clearProgRawFile, "clear-prog-raw", "", "Compiled TEAL program filename for updating application state when a user clears their local state")
+ appCmd.PersistentFlags().StringVar(&approvalProgRawFile, "approval-prog-raw", "", "Compiled AVM bytecode program filename for approving/rejecting transactions")
+ appCmd.PersistentFlags().StringVar(&clearProgRawFile, "clear-prog-raw", "", "Compiled AVM bytecode program filename for updating application state when a user clears their local state")
- createAppCmd.Flags().Uint64Var(&globalSchemaUints, "global-ints", 0, "Maximum number of integer values that may be stored in the global key/value store. Immutable.")
- createAppCmd.Flags().Uint64Var(&globalSchemaByteSlices, "global-byteslices", 0, "Maximum number of byte slices that may be stored in the global key/value store. Immutable.")
+ createAppCmd.Flags().Uint64Var(&globalSchemaUints, "global-ints", 0, "Maximum number of integer values that may be stored in the global key/value store.")
+ createAppCmd.Flags().Uint64Var(&globalSchemaByteSlices, "global-byteslices", 0, "Maximum number of byte slices that may be stored in the global key/value store.")
createAppCmd.Flags().Uint64Var(&localSchemaUints, "local-ints", 0, "Maximum number of integer values that may be stored in local (per-account) key/value stores for this app. Immutable.")
createAppCmd.Flags().Uint64Var(&localSchemaByteSlices, "local-byteslices", 0, "Maximum number of byte slices that may be stored in local (per-account) key/value stores for this app. Immutable.")
createAppCmd.Flags().StringVar(&appCreator, "creator", "", "Account to create the application")
createAppCmd.Flags().StringVar(&onCompletion, "on-completion", "NoOp", "OnCompletion action for application transaction")
- createAppCmd.Flags().Uint32Var(&extraPages, "extra-pages", 0, "Additional program space for supporting larger TEAL assembly program. A maximum of 3 extra pages is allowed. A page is 1024 bytes.")
+ createAppCmd.Flags().Uint32Var(&extraPages, "extra-pages", 0, "Additional program space for supporting larger AVM bytecode program. A maximum of 3 extra pages is allowed. A page is 1024 bytes.")
+
+ updateAppCmd.Flags().Uint64Var(&globalSchemaUints, "global-ints", 0, "Maximum number of integer values that may be stored in the global key/value store.")
+ updateAppCmd.Flags().Uint64Var(&globalSchemaByteSlices, "global-byteslices", 0, "Maximum number of byte slices that may be stored in the global key/value store.")
+ updateAppCmd.Flags().Uint32Var(&extraPages, "extra-pages", 0, "Additional program space for supporting larger AVM program. A maximum of 3 extra pages is allowed. A page is 1024 bytes.")
callAppCmd.Flags().StringVarP(&account, "from", "f", "", "Account to call app from")
optInAppCmd.Flags().StringVarP(&account, "from", "f", "", "Account to opt in")
@@ -144,11 +145,11 @@ func init() {
methodAppCmd.Flags().StringVar(&onCompletion, "on-completion", "NoOp", "OnCompletion action for application transaction")
methodAppCmd.Flags().Uint64Var(&rejectVersion, "reject-version", 0, "RejectVersion for application transaction")
methodAppCmd.Flags().BoolVar(&methodCreatesApp, "create", false, "Create an application in this method call")
- methodAppCmd.Flags().Uint64Var(&globalSchemaUints, "global-ints", 0, "Maximum number of integer values that may be stored in the global key/value store. Immutable, only valid when passed with --create.")
- methodAppCmd.Flags().Uint64Var(&globalSchemaByteSlices, "global-byteslices", 0, "Maximum number of byte slices that may be stored in the global key/value store. Immutable, only valid when passed with --create.")
+ methodAppCmd.Flags().Uint64Var(&globalSchemaUints, "global-ints", 0, "Maximum number of integer values that may be stored in the global key/value store. Valid when passed with --create or when updating.")
+ methodAppCmd.Flags().Uint64Var(&globalSchemaByteSlices, "global-byteslices", 0, "Maximum number of byte slices that may be stored in the global key/value store. Valid when passed with --create or when updating.")
methodAppCmd.Flags().Uint64Var(&localSchemaUints, "local-ints", 0, "Maximum number of integer values that may be stored in local (per-account) key/value stores for this app. Immutable, only valid when passed with --create.")
methodAppCmd.Flags().Uint64Var(&localSchemaByteSlices, "local-byteslices", 0, "Maximum number of byte slices that may be stored in local (per-account) key/value stores for this app. Immutable, only valid when passed with --create.")
- methodAppCmd.Flags().Uint32Var(&extraPages, "extra-pages", 0, "Additional program space for supporting larger TEAL assembly program. A maximum of 3 extra pages is allowed. A page is 1024 bytes. Only valid when passed with --create.")
+ methodAppCmd.Flags().Uint32Var(&extraPages, "extra-pages", 0, "Additional program space for supporting larger AVM bytecode program. A maximum of 3 extra pages is allowed. A page is 1024 bytes. Valid when passed with --create or when updating.")
// Can't use PersistentFlags on the root because for some reason marking
// a root command as required with MarkPersistentFlagRequired isn't
@@ -383,26 +384,6 @@ func cliAddress(acct string) basics.Address {
return addr
}
-func getAppInputsFromFile() appCallInputs {
- reportWarnf("Using a JSON app input file is deprecated and will be removed soon. Please speak up if the feature matters to you.")
- time.Sleep(5 * time.Second)
-
- var inputs appCallInputs
- f, err := os.Open(appInputFilename)
- if err != nil {
- reportErrorf("Could not open app input JSON file: %v", err)
- }
- defer f.Close()
-
- dec := protocol.NewJSONDecoder(f)
- err = dec.Decode(&inputs)
- if err != nil {
- reportErrorf("Could not decode app input JSON file: %v", err)
- }
-
- return inputs
-}
-
func getAppInputsFromCLI() appCallInputs {
// we need to ignore empty strings from appArgs because app-arg was
// previously a StringSliceVar, which also does that, and some test depend
@@ -432,19 +413,7 @@ func getAppInputsFromCLI() appCallInputs {
}
func getAppInputs() ([][]byte, libgoal.RefBundle) {
- var inputs appCallInputs
- if appInputFilename != "" {
- if appArgs != nil || appStrAccounts != nil ||
- foreignApps != nil || foreignAssets != nil || appStrBoxes != nil ||
- appStrHoldings != nil || appStrLocals != nil {
- reportErrorf("Cannot specify both command-line arguments/resources and JSON input filename")
- }
- inputs = getAppInputsFromFile()
- } else {
- inputs = getAppInputsFromCLI()
- }
-
- return parseAppInputs(inputs)
+ return parseAppInputs(getAppInputsFromCLI())
}
var appCmd = &cobra.Command{
@@ -616,6 +585,11 @@ var updateAppCmd = &cobra.Command{
if err != nil {
reportErrorf("Cannot create application txn: %v", err)
}
+ tx.GlobalStateSchema = basics.StateSchema{
+ NumUint: globalSchemaUints,
+ NumByteSlice: globalSchemaByteSlices,
+ }
+ tx.ExtraProgramPages = extraPages
// Fill in note and lease
tx.Note = parseNoteField(cmd)
@@ -1125,6 +1099,11 @@ var infoAppCmd = &cobra.Command{
fmt.Printf("Program version: %d\n", *ver)
}
+ sponsor := params.SizeSponsor
+ if sponsor != nil {
+ fmt.Printf("Size sponsor: %v\n", *sponsor)
+ }
+
epp := params.ExtraProgramPages
if epp != nil {
fmt.Printf("Extra program pages: %d\n", *epp)
@@ -1369,12 +1348,16 @@ var methodAppCmd = &cobra.Command{
reportErrorf("one of --app-id or --create must be provided")
}
- if localSchema != (basics.StateSchema{}) || globalSchema != (basics.StateSchema{}) {
- reportErrorf("--global-ints, --global-byteslices, --local-ints, and --local-byteslices must only be provided with --create")
+ if onCompletionEnum != transactions.UpdateApplicationOC {
+ if !globalSchema.Empty() {
+ reportErrorf("--global-ints, --global-byteslices, --local-ints, and --local-byteslices must only be provided with --create or when updating")
+ }
+ if extraPages != 0 {
+ reportErrorf("--extra-pages must only be provided with --create or when updating")
+ }
}
-
- if extraPages != 0 {
- reportErrorf("--extra-pages must only be provided with --create")
+ if !localSchema.Empty() {
+ reportErrorf("--local-ints and --local-byteslices must only be provided with --create")
}
}
diff --git a/cmd/goal/application_test.go b/cmd/goal/application_test.go
index 2f614af558..bb5d7e1bf7 100644
--- a/cmd/goal/application_test.go
+++ b/cmd/goal/application_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/asset.go b/cmd/goal/asset.go
index 70802e03e3..5b3c1c88cf 100644
--- a/cmd/goal/asset.go
+++ b/cmd/goal/asset.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -85,12 +85,12 @@ func init() {
destroyAssetCmd.Flags().StringVar(&assetManager, "manager", "", "Manager account to issue the destroy transaction (defaults to creator)")
destroyAssetCmd.Flags().StringVar(&assetCreator, "creator", "", "Creator account address for asset to destroy")
destroyAssetCmd.Flags().Uint64Var((*uint64)(&assetID), "assetid", 0, "Asset ID to destroy")
- destroyAssetCmd.Flags().StringVar(&assetUnitName, "asset", "", "Unit name of asset to destroy")
+ destroyAssetCmd.Flags().StringVar(&assetUnitName, "unitname", "", "Unit name of asset to destroy")
configAssetCmd.Flags().StringVar(&assetManager, "manager", "", "Manager account to issue the config transaction")
configAssetCmd.Flags().StringVar(&assetCreator, "creator", "", "Account address for asset to configure (defaults to manager)")
configAssetCmd.Flags().Uint64Var((*uint64)(&assetID), "assetid", 0, "Asset ID to configure")
- configAssetCmd.Flags().StringVar(&assetUnitName, "asset", "", "Unit name of asset to configure")
+ configAssetCmd.Flags().StringVar(&assetUnitName, "unitname", "", "Unit name of asset to configure")
configAssetCmd.Flags().StringVar(&assetNewManager, "new-manager", "", "New manager address")
configAssetCmd.Flags().StringVar(&assetNewReserve, "new-reserve", "", "New reserve address")
configAssetCmd.Flags().StringVar(&assetNewFreezer, "new-freezer", "", "New freeze address")
@@ -100,7 +100,7 @@ func init() {
sendAssetCmd.Flags().StringVar(&assetClawback, "clawback", "", "Address to issue a clawback transaction from (defaults to no clawback)")
sendAssetCmd.Flags().StringVar(&assetCreator, "creator", "", "Account address for asset creator")
sendAssetCmd.Flags().Uint64Var((*uint64)(&assetID), "assetid", 0, "ID of the asset being transferred")
- sendAssetCmd.Flags().StringVar(&assetUnitName, "asset", "", "Unit name of the asset being transferred")
+ sendAssetCmd.Flags().StringVar(&assetUnitName, "unitname", "", "Unit name of the asset being transferred")
sendAssetCmd.Flags().StringVarP(&account, "from", "f", "", "Account address to send the money from (if not specified, uses default account)")
sendAssetCmd.Flags().StringVarP(&toAddress, "to", "t", "", "Address to send to money to (required)")
sendAssetCmd.Flags().Uint64VarP(&amount, "amount", "a", 0, "The amount to be transferred (required), in base units of the asset.")
@@ -111,14 +111,14 @@ func init() {
freezeAssetCmd.Flags().StringVar(&assetFreezer, "freezer", "", "Address to issue a freeze transaction from")
freezeAssetCmd.Flags().StringVar(&assetCreator, "creator", "", "Account address for asset creator")
freezeAssetCmd.Flags().Uint64Var((*uint64)(&assetID), "assetid", 0, "ID of the asset being frozen")
- freezeAssetCmd.Flags().StringVar(&assetUnitName, "asset", "", "Unit name of the asset being frozen")
+ freezeAssetCmd.Flags().StringVar(&assetUnitName, "unitname", "", "Unit name of the asset being frozen")
freezeAssetCmd.Flags().StringVar(&account, "account", "", "Account address to freeze/unfreeze")
freezeAssetCmd.Flags().BoolVar(&assetFrozen, "freeze", false, "Freeze or unfreeze")
freezeAssetCmd.MarkFlagRequired("freezer")
freezeAssetCmd.MarkFlagRequired("account")
freezeAssetCmd.MarkFlagRequired("freeze")
- optinAssetCmd.Flags().StringVar(&assetUnitName, "asset", "", "Unit name of the asset being accepted")
+ optinAssetCmd.Flags().StringVar(&assetUnitName, "unitname", "", "Unit name of the asset being accepted")
optinAssetCmd.Flags().Uint64Var((*uint64)(&assetID), "assetid", 0, "ID of the asset being accepted")
optinAssetCmd.Flags().StringVarP(&account, "account", "a", "", "Account address to opt in to using the asset (if not specified, uses default account)")
optinAssetCmd.Flags().StringVar(&assetCreator, "creator", "", "Account address for asset creator")
@@ -132,7 +132,6 @@ func init() {
addTxnFlags(optinAssetCmd)
infoAssetCmd.Flags().Uint64Var((*uint64)(&assetID), "assetid", 0, "ID of the asset to look up")
- infoAssetCmd.Flags().StringVar(&assetUnitName, "asset", "", "DEPRECATED! Unit name of the asset to look up")
infoAssetCmd.Flags().StringVar(&assetUnitName, "unitname", "", "Unit name of the asset to look up")
infoAssetCmd.Flags().StringVar(&assetCreator, "creator", "", "Account address of the asset creator")
}
@@ -148,17 +147,9 @@ var assetCmd = &cobra.Command{
}
func lookupAssetID(cmd *cobra.Command, creator string, client libgoal.Client) {
- if cmd.Flags().Changed("asset") {
- reportWarnln("The [--asset] flag is deprecated and will be removed in a future release, use [--unitname] instead.")
- }
-
- if cmd.Flags().Changed("asset") && cmd.Flags().Changed("unitname") {
- reportErrorf("The [--asset] flag has been replaced by [--unitname], do not provide both flags.")
- }
-
- assetOrUnit := cmd.Flags().Changed("asset") || cmd.Flags().Changed("unitname")
+ unitSpecified := cmd.Flags().Changed("unitname")
- if cmd.Flags().Changed("assetid") && assetOrUnit {
+ if cmd.Flags().Changed("assetid") && unitSpecified {
reportErrorf("Only one of [--assetid] or [--unitname and --creator] should be specified")
}
@@ -166,7 +157,7 @@ func lookupAssetID(cmd *cobra.Command, creator string, client libgoal.Client) {
return
}
- if !assetOrUnit {
+ if !unitSpecified {
reportErrorf("Missing required parameter [--assetid] or [--unitname and --creator] must be specified")
}
diff --git a/cmd/goal/box.go b/cmd/goal/box.go
index 12288d3fff..908d284a40 100644
--- a/cmd/goal/box.go
+++ b/cmd/goal/box.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/clerk.go b/cmd/goal/clerk.go
index df4fbbd589..23c4488b15 100644
--- a/cmd/goal/clerk.go
+++ b/cmd/goal/clerk.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -274,6 +274,9 @@ func writeTxnToFile(client libgoal.Client, signTx bool, dataDir string, walletNa
if err != nil {
reportErrorf("Signer invalid (%s): %v", signerAddress, err)
}
+ if authAddr == tx.Sender {
+ reportErrorf("AuthAddr cannot be the same as the transaction sender")
+ }
}
stxn, err := createSignedTransaction(client, signTx, dataDir, walletName, tx, authAddr)
@@ -449,6 +452,9 @@ var sendCmd = &cobra.Command{
if err != nil {
reportErrorf("Signer invalid (%s): %v", signerAddress, err)
}
+ if authAddr == payment.Sender {
+ reportErrorf("AuthAddr cannot be the same as the transaction sender")
+ }
}
var stx transactions.SignedTxn
@@ -531,7 +537,7 @@ var sendCmd = &cobra.Command{
// Append the signer since it's a rekey txn
if basics.Address(addr) == stx.Txn.Sender {
- reportWarnln(rekeySenderTargetSameError)
+ reportErrorf("AuthAddr cannot be the same as the transaction sender")
}
stx.AuthAddr = basics.Address(addr)
}
@@ -862,6 +868,9 @@ var signCmd = &cobra.Command{
if lsig.Logic != nil {
txn.Lsig = lsig
if signerAddress != "" {
+ if authAddr == txn.Txn.Sender {
+ reportErrorf("AuthAddr cannot be the same as the transaction sender")
+ }
txn.AuthAddr = authAddr
}
}
@@ -1159,6 +1168,8 @@ var dryrunCmd = &cobra.Command{
Short: "Test a program offline",
Long: "Test a TEAL program offline under various conditions and verbosity.",
Run: func(cmd *cobra.Command, args []string) {
+ reportWarnf("goal clerk dryrun is deprecated and will be removed soon. Please speak up if the feature matters to you.")
+ time.Sleep(3 * time.Second)
stxns := decodeTxnsFromFile(txFilename)
proto, params := getProto(protoVersion)
if dumpForDryrun {
@@ -1220,6 +1231,8 @@ var dryrunRemoteCmd = &cobra.Command{
Short: "Test a program with algod's dryrun REST endpoint",
Long: "Test a TEAL program with algod's dryrun REST endpoint under various conditions and verbosity.",
Run: func(cmd *cobra.Command, args []string) {
+ reportWarnf("goal clerk dryrun-remote is deprecated and will be removed soon. Please speak up if the feature matters to you.")
+ time.Sleep(3 * time.Second)
data, err := readFile(txFilename)
if err != nil {
reportErrorf(fileReadError, txFilename, err)
diff --git a/cmd/goal/clerk_test.go b/cmd/goal/clerk_test.go
index 7cd7700b67..c590bdb46c 100644
--- a/cmd/goal/clerk_test.go
+++ b/cmd/goal/clerk_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/commands.go b/cmd/goal/commands.go
index 9b520a2644..f0cd426068 100644
--- a/cmd/goal/commands.go
+++ b/cmd/goal/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -78,9 +78,6 @@ func init() {
// kmd.go
rootCmd.AddCommand(kmdCmd)
- // logging.go
- rootCmd.AddCommand(loggingCmd)
-
// network.go
rootCmd.AddCommand(networkCmd)
diff --git a/cmd/goal/commands_test.go b/cmd/goal/commands_test.go
index 0f33fb9f1e..2cebf09eda 100644
--- a/cmd/goal/commands_test.go
+++ b/cmd/goal/commands_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/common.go b/cmd/goal/common.go
index daa7a58301..4ba40d8bff 100644
--- a/cmd/goal/common.go
+++ b/cmd/goal/common.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/completion.go b/cmd/goal/completion.go
index 81d047c93c..fd2b87c222 100644
--- a/cmd/goal/completion.go
+++ b/cmd/goal/completion.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/formatting.go b/cmd/goal/formatting.go
index a977d611b7..c11ae7acaf 100644
--- a/cmd/goal/formatting.go
+++ b/cmd/goal/formatting.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/formatting_test.go b/cmd/goal/formatting_test.go
index 81b5454c76..bb87249dc8 100644
--- a/cmd/goal/formatting_test.go
+++ b/cmd/goal/formatting_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/inspect.go b/cmd/goal/inspect.go
index b66664e294..a1004b3d07 100644
--- a/cmd/goal/inspect.go
+++ b/cmd/goal/inspect.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -50,7 +50,7 @@ type inspectMultisigSig struct {
Subsigs []inspectMultisigSubsig `codec:"subsig"`
}
-// inspectMultisigSig is isomorphic to MultisigSig but uses different
+// inspectMultisigSubsig is isomorphic to MultisigSig but uses different
// types to print public keys using algorand's address format in JSON.
type inspectMultisigSubsig struct {
_struct struct{} `codec:",omitempty,omitemptyarray"`
diff --git a/cmd/goal/inspect_test.go b/cmd/goal/inspect_test.go
index 6c043f4bd3..eecd525cea 100644
--- a/cmd/goal/inspect_test.go
+++ b/cmd/goal/inspect_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/interact.go b/cmd/goal/interact.go
deleted file mode 100644
index acbac3cccf..0000000000
--- a/cmd/goal/interact.go
+++ /dev/null
@@ -1,758 +0,0 @@
-// Copyright (C) 2019-2025 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 main
-
-import (
- "encoding/base32"
- "encoding/base64"
- "encoding/json"
- "errors"
- "fmt"
- "net/http"
- "os"
- "strconv"
- "strings"
- "time"
-
- "github.com/spf13/cobra"
-
- "github.com/algorand/avm-abi/apps"
- "github.com/algorand/go-algorand/cmd/util/datadir"
- "github.com/algorand/go-algorand/crypto"
- apiclient "github.com/algorand/go-algorand/daemon/algod/api/client"
- "github.com/algorand/go-algorand/data/basics"
- "github.com/algorand/go-algorand/data/transactions"
- "github.com/algorand/go-algorand/data/transactions/logic"
- "github.com/algorand/go-algorand/libgoal"
- "github.com/algorand/go-algorand/util"
-)
-
-var (
- appHdr string
-)
-
-func init() {
- appCmd.AddCommand(appInteractCmd)
-
- appInteractCmd.AddCommand(appExecuteCmd)
- appInteractCmd.AddCommand(appQueryCmd)
- appInteractCmd.PersistentFlags().StringVarP(&appHdr, "header", "", "", "Application header")
-
- appQueryCmd.Flags().Uint64Var((*uint64)(&appIdx), "app-id", 0, "Application ID")
- appQueryCmd.Flags().StringVarP(&account, "from", "f", "", "Account to query state for (if omitted, query from global state)")
- appQueryCmd.Flags().SetInterspersed(false)
- appQueryCmd.MarkFlagRequired("app-id")
-
- appExecuteCmd.Flags().Uint64Var((*uint64)(&appIdx), "app-id", 0, "Application ID (if omitted, zero, which creates an application)")
- appExecuteCmd.Flags().StringVarP(&account, "from", "f", "", "Account to execute interaction from")
- appExecuteCmd.Flags().StringVarP(&signerAddress, "signer", "S", "", "Address of key to sign with, if different from \"from\" address due to rekeying")
- appExecuteCmd.Flags().SetInterspersed(false)
- appExecuteCmd.MarkFlagRequired("from")
-}
-
-var appInteractCmd = &cobra.Command{
- Use: "interact",
- Short: "Interact with an application",
- Args: cobra.ArbitraryArgs,
- Run: func(cmd *cobra.Command, args []string) {
- // If no arguments passed, we should fallback to help
- cmd.HelpFunc()(cmd, args)
- },
-}
-
-type appInteractDatum interface {
- kind() string
- help() string
- pseudo() bool
-}
-
-func helpList[V appInteractDatum](help map[string]V) string {
- largestName := 0
- largestKind := 0
- for k, v := range help {
- if v.pseudo() {
- continue
- }
- if len(k) > largestName {
- largestName = len(k)
- }
- if len(v.kind()) > largestKind {
- largestKind = len(v.kind())
- }
- }
-
- namesize := "%-" + fmt.Sprintf("%d", largestName+3) + "s"
- kindsize := "%-" + fmt.Sprintf("%d", largestKind+3) + "s"
- fmtstr := " " + namesize + " " + kindsize + " " + "%s"
-
- var entries []string
- for k, v := range help {
- if v.pseudo() {
- continue
- }
- entries = append(entries, fmt.Sprintf(fmtstr, k, v.kind(), v.help()))
- }
- return strings.Join(entries, "\n")
-}
-
-func appSpecRuneInvalid(r rune) bool {
- if 'a' <= r && r <= 'z' {
- return false
- }
- if 'A' <= r && r <= 'Z' {
- return false
- }
- if '0' <= r && r <= '9' {
- return false
- }
- if r == '-' || r == '+' || r == '_' {
- return false
- }
- return true
-}
-
-func appSpecStringInvalid(s string) error {
- for _, r := range s {
- if appSpecRuneInvalid(r) {
- return fmt.Errorf("%s contains an invalid rune", strconv.Quote(s))
- }
- }
- return nil
-}
-
-func appSpecHelpStringInvalid(s string) error {
- if printable, _ := unicodePrintable(s); !printable {
- return fmt.Errorf("%s is not Unicode printable", strconv.Quote(s))
- }
- return nil
-}
-
-type appInteractProc struct {
- Create bool `json:"create"`
- OnCompletion string `json:"on-completion"`
- Help string `json:"help"`
-
- Args []appInteractArg `json:"args"`
- Accounts []appInteractAccount `json:"accounts"`
- ForeignApps []appInteractForeign `json:"foreign"`
-}
-
-func (proc appInteractProc) validate() (err error) {
- err = appSpecStringInvalid(proc.OnCompletion)
- if err != nil {
- return fmt.Errorf("OnCompletion: %v", err)
- }
- err = appSpecHelpStringInvalid(proc.Help)
- if err != nil {
- return fmt.Errorf("Help: %v", err)
- }
- for i, arg := range proc.Args {
- err = arg.validate()
- if err != nil {
- return fmt.Errorf("Arg(%d): %v", i, err)
- }
- }
- for i, acc := range proc.Accounts {
- err = acc.validate()
- if err != nil {
- return fmt.Errorf("Account(%d): %v", i, err)
- }
- }
- for i, app := range proc.ForeignApps {
- err = app.validate()
- if err != nil {
- return fmt.Errorf("App(%d): %v", i, err)
- }
- }
- return
-}
-
-func (proc appInteractProc) kind() string {
- return proc.OnCompletion
-}
-
-func (proc appInteractProc) help() string {
- return proc.Help
-}
-
-func (proc appInteractProc) pseudo() bool {
- return false
-}
-
-type appInteractArg struct {
- Name string `json:"name"`
- Kind string `json:"kind"`
- Help string `json:"help"`
- Pseudo bool `json:"pseudo"`
- Default string `json:"default"`
-}
-
-func (arg appInteractArg) validate() (err error) {
- err = appSpecStringInvalid(arg.Name)
- if err != nil {
- return fmt.Errorf("Key: %v", err)
- }
- err = appSpecStringInvalid(arg.Kind)
- if err != nil {
- return fmt.Errorf("Kind: %v", err)
- }
- err = appSpecHelpStringInvalid(arg.Help)
- if err != nil {
- return fmt.Errorf("Help: %v", err)
- }
- // default values can be arbitrary
- // make sure to escape them before printing!
- // err = appSpecStringInvalid(arg.Default)
- return
-}
-
-func (arg appInteractArg) kind() string {
- return arg.Kind
-}
-
-func (arg appInteractArg) help() string {
- return arg.Help
-}
-
-func (arg appInteractArg) pseudo() bool {
- return arg.Pseudo
-}
-
-type appInteractAccount struct {
- Name string `json:"name"`
- Help string `json:"help"`
- Pseudo bool `json:"pseudo"` // TODO use this field in help
- Explicit bool `json:"explicit"`
-}
-
-func (acc appInteractAccount) validate() (err error) {
- err = appSpecStringInvalid(acc.Name)
- if err != nil {
- return fmt.Errorf("Name: %v", err)
- }
- err = appSpecHelpStringInvalid(acc.Help)
- if err != nil {
- return fmt.Errorf("Help: %v", err)
- }
- return
-}
-
-type appInteractForeign struct {
- Name string `json:"name"`
- Help string `json:"help"`
-}
-
-func (f appInteractForeign) validate() (err error) {
- err = appSpecStringInvalid(f.Name)
- if err != nil {
- return fmt.Errorf("Name: %v", err)
- }
- err = appSpecHelpStringInvalid(f.Help)
- if err != nil {
- return fmt.Errorf("Help: %v", err)
- }
- return
-}
-
-// map key -> data
-type appInteractSchema map[string]appInteractSchemaEntry
-
-func (sch appInteractSchema) validate() (err error) {
- for k, v := range sch {
- err = appSpecStringInvalid(k)
- if err != nil {
- return fmt.Errorf("Key: %v", err)
- }
- err = v.validate()
- if err != nil {
- return fmt.Errorf("Entry(%s): %v", k, err)
- }
- }
- return
-}
-
-func (sch appInteractSchema) EntryList() string {
- return helpList(sch)
-}
-
-func (sch appInteractSchema) EntryNames() (names []string) {
- for k := range sch {
- names = append(names, k)
- }
- return
-}
-
-func (sch appInteractSchema) ToStateSchema() (schema basics.StateSchema) {
- for name, entry := range sch {
- size := uint64(1)
- if entry.Map.Kind != "" {
- if entry.Size < 0 {
- reportErrorf("entry %s size %d < 0", name, entry.Size)
- }
- size = uint64(entry.Size)
- }
- switch entry.Kind {
- case "int", "integer":
- schema.NumUint += size
- default:
- schema.NumByteSlice += size
- }
- }
- return
-}
-
-type appInteractSchemaEntry struct {
- Key string `json:"key"`
- Kind string `json:"kind"`
- Help string `json:"help"`
- Size int `json:"size"`
- Explicit bool `json:"explicit"`
-
- Map appInteractMap `json:"map"` // TODO support for queries
-}
-
-func (entry appInteractSchemaEntry) validate() (err error) {
- err = appSpecStringInvalid(entry.Key)
- if err != nil {
- return fmt.Errorf("Key: %v", err)
- }
- err = appSpecStringInvalid(entry.Kind)
- if err != nil {
- return fmt.Errorf("Kind: %v", err)
- }
- err = appSpecHelpStringInvalid(entry.Help)
- if err != nil {
- return fmt.Errorf("Help: %v", err)
- }
- err = entry.Map.validate()
- if err != nil {
- return fmt.Errorf("Map: %v", err)
- }
- return
-}
-
-func (entry appInteractSchemaEntry) kind() string {
- if entry.Map.Kind != "" {
- return fmt.Sprintf("map %s -> %s", entry.Kind, entry.Map.Kind)
- }
- return entry.Kind
-}
-
-func (entry appInteractSchemaEntry) help() string {
- return entry.Help
-}
-
-func (entry appInteractSchemaEntry) pseudo() bool {
- return false
-}
-
-type appInteractMap struct {
- Kind string `json:"kind"`
- Prefix string `json:"prefix"`
-}
-
-func (m appInteractMap) validate() (err error) {
- err = appSpecStringInvalid(m.Kind)
- if err != nil {
- return fmt.Errorf("Kind: %v", m.Kind)
- }
- err = appSpecStringInvalid(m.Prefix)
- if err != nil {
- return fmt.Errorf("Prefix: %v", m.Prefix)
- }
- return
-}
-
-type appInteractState struct {
- Global appInteractSchema `json:"global"`
- Local appInteractSchema `json:"local"`
-}
-
-func (s appInteractState) validate() (err error) {
- err = s.Global.validate()
- if err != nil {
- return fmt.Errorf("Global: %v", err)
- }
- err = s.Local.validate()
- if err != nil {
- return fmt.Errorf("Local: %v", err)
- }
- return
-}
-
-// map procedure name -> procedure
-type appInteractProcs map[string]appInteractProc
-
-func (m appInteractProcs) validate() (err error) {
- for k, v := range m {
- err = appSpecStringInvalid(k)
- if err != nil {
- return fmt.Errorf("Key: %v", err)
- }
- err = v.validate()
- if err != nil {
- return fmt.Errorf("Proc(%s): %v", strconv.QuoteToASCII(k), err)
- }
- }
- return
-}
-
-type appInteractHeader struct {
- Execute appInteractProcs `json:"execute"`
- Query appInteractState `json:"query"`
-}
-
-// TODO use reflect to recursively validate
-func (hdr appInteractHeader) validate() (err error) {
- err = hdr.Execute.validate()
- if err != nil {
- return fmt.Errorf("Execute: %v", err)
- }
- err = hdr.Query.validate()
- if err != nil {
- return fmt.Errorf("Query: %v", err)
- }
- return
-}
-
-func (hdr appInteractHeader) ProcList() string {
- return helpList(hdr.Execute)
-}
-
-func (hdr appInteractHeader) ProcNames() (names []string) {
- for k := range hdr.Execute {
- names = append(names, k)
- }
- return
-}
-
-func parseAppHeader() (header appInteractHeader) {
- if appHdr == "" {
- reportErrorf("No header file provided")
- }
-
- f, err := os.Open(appHdr)
- if err != nil {
- reportErrorf("Could not open app header file %s: %v", appHdr, err)
- }
- defer f.Close()
-
- dec := json.NewDecoder(f)
- err = dec.Decode(&header)
- if err != nil {
- reportErrorf("Could not decode app header JSON file %s: %v", appHdr, err)
- }
-
- err = header.validate()
- if err != nil {
- reportErrorf("App header JSON file could not validate: %v", err)
- }
-
- return
-}
-
-// TODO print help correctly when --help is passed but procedure/state name is given
-// TODO complain when unknown flags are given
-
-var appExecuteCmd = &cobra.Command{
- Use: "execute",
- Short: "Execute a procedure on an application",
- Args: cobra.MinimumNArgs(1),
- Run: func(cmd *cobra.Command, args []string) {
- reportWarnf("app interact is deprecated and will be removed soon. Please speak up if the feature matters to you.")
- time.Sleep(3 * time.Second)
-
- dataDir := datadir.EnsureSingleDataDir()
- client := ensureFullClient(dataDir)
-
- header := parseAppHeader()
- proc, ok := header.Execute[args[0]]
- if !ok {
- reportErrorf("Unknown procedure name %s.\nDefined procedures in %s:\n%s", args[0], appHdr, header.ProcList())
- }
-
- if proc.Create != (appIdx == 0) {
- reportErrorf("Procedure %s has the create flag set to %v, but application ID set to %d", args[0], proc.Create, appIdx)
- }
-
- procFlags := cmd.Flags()
- procFlags.SetInterspersed(true)
- procArgs := make(map[string]interface{})
- procAccounts := make(map[string]*string)
- procApps := make(map[string]*uint64)
- for _, arg := range proc.Args {
- switch arg.Kind {
- case "int", "integer":
- procArgs[arg.Name] = procFlags.Uint64(arg.Name, 0, arg.Help)
- default:
- procArgs[arg.Name] = procFlags.String(arg.Name, "", arg.Help)
- }
- }
- for _, account := range proc.Accounts {
- procAccounts[account.Name] = procFlags.String(account.Name, "", account.Help)
- }
- for _, app := range proc.ForeignApps {
- procApps[app.Name] = procFlags.Uint64(app.Name, 0, app.Help)
- }
- procFlags.Parse(os.Args[1:])
-
- var inputs appCallInputs
- for _, arg := range proc.Args {
- var callArg apps.AppCallBytes
- callArg.Encoding = arg.Kind
-
- if !procFlags.Changed(arg.Name) && arg.Default != "" {
- callArg.Value = arg.Default
- } else {
- v := procArgs[arg.Name]
- s, ok := v.(*string)
- if ok {
- callArg.Value = *s
- } else {
- i, ok := v.(*uint64)
- if ok {
- // TODO this decodes and re-encodes redundantly
- callArg.Value = strconv.FormatUint(*i, 10)
- } else {
- reportErrorf("Could not re-encode key %s", arg.Name)
- }
- }
- }
- inputs.Args = append(inputs.Args, callArg)
- }
- for _, account := range proc.Accounts {
- var addr basics.Address
- s := *procAccounts[account.Name]
- if s == "" {
- if account.Explicit {
- reportErrorf("Required account %s not provided", account.Name)
- }
- } else {
- var err error
- addr, err = basics.UnmarshalChecksumAddress(s)
- if err != nil {
- reportErrorf("Could not unmarshal address for %s (%s): %v", account.Name, s, err)
- }
- }
- inputs.Accounts = append(inputs.Accounts, addr.String())
- }
- for _, app := range proc.ForeignApps {
- inputs.ForeignApps = append(inputs.ForeignApps, *procApps[app.Name])
- }
-
- if proc.OnCompletion == "" {
- proc.OnCompletion = "NoOp"
- }
- onCompletion := mustParseOnCompletion(proc.OnCompletion)
- refs := libgoal.RefBundle{
- Accounts: util.Map(inputs.Accounts, cliAddress),
- Apps: util.Map(inputs.ForeignApps, func(idx uint64) basics.AppIndex { return basics.AppIndex(idx) }),
- Assets: util.Map(inputs.ForeignAssets, func(idx uint64) basics.AssetIndex { return basics.AssetIndex(idx) }),
- // goal app interact is old and doesn't know about holdings, locals, boxes.
- }
-
- appArgs := make([][]byte, len(inputs.Args))
- for i, arg := range inputs.Args {
- rawValue, err := arg.Raw()
- if err != nil {
- reportErrorf("Could not parse argument corresponding to '%s': %v", proc.Args[i].Name, err)
- }
- appArgs[i] = rawValue
- }
-
- if appIdx == 0 {
- switch onCompletion {
- case transactions.CloseOutOC, transactions.ClearStateOC:
- reportWarnf("OnCompletion %s may be ill-formed when creating an application", onCompletion)
- }
- }
-
- var localSchema, globalSchema basics.StateSchema
- var approvalProg, clearProg []byte
- if appIdx == 0 {
- approvalProg, clearProg = mustParseProgArgs()
- localSchema = header.Query.Local.ToStateSchema()
- globalSchema = header.Query.Global.ToStateSchema()
- }
- tx, err := client.MakeUnsignedApplicationCallTx(appIdx, appArgs, refs, onCompletion, approvalProg, clearProg, globalSchema, localSchema, 0, rejectVersion)
- if err != nil {
- reportErrorf("Cannot create application txn: %v", err)
- }
-
- // Fill in note and lease
- tx.Note = parseNoteField(cmd)
- tx.Lease = parseLease(cmd)
-
- // Fill in rounds, fee, etc.
- fv, lv, _, err := client.ComputeValidityRounds(firstValid, lastValid, numValidRounds)
- if err != nil {
- reportErrorf("Cannot determine last valid round: %s", err)
- }
-
- tx, err = client.FillUnsignedTxTemplate(account, fv, lv, fee, tx)
- if err != nil {
- reportErrorf("Cannot construct transaction: %s", err)
- }
- explicitFee := cmd.Flags().Changed("fee")
- if explicitFee {
- tx.Fee = basics.MicroAlgos{Raw: fee}
- }
-
- if outFilename == "" {
- wh, pw := ensureWalletHandleMaybePassword(dataDir, walletName, true)
- signedTxn, err2 := client.SignTransactionWithWalletAndSigner(wh, pw, signerAddress, tx)
- if err2 != nil {
- reportErrorf(errorSigningTX, err2)
- }
-
- txid, err2 := client.BroadcastTransaction(signedTxn)
- if err2 != nil {
- reportErrorf(errorBroadcastingTX, err2)
- }
-
- if appIdx == 0 {
- reportInfof("Attempting to create app (global ints %d, global blobs %d, local ints %d, local blobs %d, approval size %d, hash %v; clear size %d, hash %v)", globalSchema.NumUint, globalSchema.NumByteSlice, localSchema.NumUint, localSchema.NumByteSlice, len(approvalProg), logic.HashProgram(approvalProg), len(clearProg), crypto.HashObj(logic.Program(clearProg)))
- } else if onCompletion == transactions.UpdateApplicationOC {
- reportInfof("Attempting to update app (approval size %d, hash %v; clear size %d, hash %v)", len(approvalProg), crypto.HashObj(logic.Program(approvalProg)), len(clearProg), logic.HashProgram(clearProg))
- }
- reportInfof("Issued transaction from account %s, txid %s (fee %d)", tx.Sender, txid, tx.Fee.Raw)
-
- if !noWaitAfterSend {
- txn, err1 := waitForCommit(client, txid, lv)
- if err1 != nil {
- reportErrorln(err1)
- }
- if txn.ApplicationIndex != nil && *txn.ApplicationIndex != 0 {
- reportInfof("Created app with app index %d", *txn.ApplicationIndex)
- }
- }
- } else {
- // Broadcast or write transaction to file
- err = writeTxnToFile(client, sign, dataDir, walletName, tx, outFilename)
- if err != nil {
- reportErrorln(err)
- }
- }
- },
-}
-
-var appQueryCmd = &cobra.Command{
- Use: "query",
- Short: "Query local or global state from an application",
- Args: cobra.MinimumNArgs(1),
- Run: func(cmd *cobra.Command, args []string) {
- reportWarnf("app interact is deprecated and will be removed soon. Please speak up if the feature matters to you.")
- time.Sleep(5 * time.Second)
-
- dataDir := datadir.EnsureSingleDataDir()
- client := ensureFullClient(dataDir)
-
- header := parseAppHeader()
- scope := "local"
- storeName := account
- lookup := header.Query.Local
- if account == "" {
- scope = "global"
- storeName = ""
- lookup = header.Query.Global
- }
-
- param := args[0]
- meta, ok := lookup[param]
- if !ok {
- reportErrorf("Unknown schema entry %s.\nDefined %s schema entries in %s:\n%s", param, scope, appHdr, lookup.EntryList())
- }
-
- var tealval basics.TealValue
- if scope == "local" {
- // Fetching local state. Get account information
- ai, err := client.RawAccountApplicationInformation(account, appIdx)
- if err != nil {
- var httpError apiclient.HTTPError
- if errors.As(err, &httpError) && httpError.StatusCode == http.StatusNotFound {
- reportErrorf(errorAccountNotOptedInToApp, account, appIdx)
- }
- reportErrorf(errorRequestFail, err)
- }
-
- if ai.AppLocalState == nil {
- reportErrorf(errorAccountNotOptedInToApp, account, appIdx)
- }
-
- kv := ai.AppLocalState.KeyValue
- tealval = kv[meta.Key]
- }
-
- if scope == "global" {
- // Fetching global state. Get application creator
- app, err := client.ApplicationInformation(appIdx)
- if err != nil {
- reportErrorf(errorRequestFail, err)
- }
-
- // Get creator information
- ai, err := client.RawAccountApplicationInformation(app.Params.Creator, appIdx)
- if err != nil {
- reportErrorf(errorRequestFail, err)
- }
-
- if ai.AppParams == nil {
- reportErrorf(errorAccountNotOptedInToApp, account, appIdx)
- }
-
- kv := ai.AppParams.GlobalState
- tealval = kv[meta.Key]
- }
-
- var decoded string
- switch meta.Kind {
- case "int", "integer":
- if tealval.Type == 0 {
- if meta.Explicit {
- reportErrorf("%s not set for %d.%s", param, appIdx, storeName)
- }
- } else if tealval.Type != basics.TealUintType {
- reportErrorf("Expected kind %s but got teal type %s", meta.Kind, tealval.Type)
- }
- decoded = fmt.Sprintf("%d", tealval.Uint)
- default:
- if tealval.Type == 0 {
- if meta.Explicit {
- reportErrorf("%s not set for %d.%s", param, appIdx, storeName)
- }
- } else if tealval.Type != basics.TealBytesType {
- reportErrorf("Expected kind %s but got teal type %s", meta.Kind, tealval.Type)
- }
- raw := []byte(tealval.Bytes)
- switch meta.Kind {
- case "str", "string":
- decoded = tealval.Bytes
- case "addr", "address":
- var addr basics.Address
- copy(addr[:], raw)
- decoded = addr.String()
- case "b32", "base32", "byte base32":
- decoded = base32.StdEncoding.EncodeToString(raw)
- case "b64", "base64", "byte base64":
- decoded = base64.StdEncoding.EncodeToString(raw)
- default:
- decoded = tealval.Bytes
- }
- }
- reportInfoln(decoded)
- },
-}
diff --git a/cmd/goal/kmd.go b/cmd/goal/kmd.go
index 3caef1eaea..548764dcec 100644
--- a/cmd/goal/kmd.go
+++ b/cmd/goal/kmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/ledger.go b/cmd/goal/ledger.go
index cea9ed406e..e866451ce3 100644
--- a/cmd/goal/ledger.go
+++ b/cmd/goal/ledger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/logging.go b/cmd/goal/logging.go
deleted file mode 100644
index f32cae2b57..0000000000
--- a/cmd/goal/logging.go
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright (C) 2019-2025 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 main
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "time"
-
- "github.com/spf13/cobra"
-
- "github.com/algorand/go-algorand/cmd/util/datadir"
- "github.com/algorand/go-algorand/config"
- "github.com/algorand/go-algorand/logging"
-)
-
-var (
- nodeName string
- logChannel string
-)
-
-func init() {
- loggingCmd.AddCommand(enableCmd)
- loggingCmd.AddCommand(disableCmd)
- loggingCmd.AddCommand(loggingSendCmd)
-
- // Enable Logging : node name
- enableCmd.Flags().StringVarP(&nodeName, "name", "n", "", "Friendly-name to use for node")
-
- loggingSendCmd.Flags().StringVarP(&logChannel, "channel", "c", "", "Release channel for log file source")
-}
-
-var loggingCmd = &cobra.Command{
- Use: "logging",
- Short: "Control and manage Algorand logging",
- Long: `Enable/disable and configure Algorand remote logging.`,
- Args: validateNoPosArgsFn,
- Run: func(cmd *cobra.Command, _ []string) {
- reportWarnln("`goal logging` deprecated, use `diagcfg telemetry status`")
- dataDir := datadir.EnsureSingleDataDir()
- root, err := config.GetGlobalConfigFileRoot()
- var cfgDir *string
- if err == nil {
- cfgDir = &root
- }
- cfg, err := logging.EnsureTelemetryConfig(&dataDir, cfgDir)
-
- // If error loading config, can't disable / no need to disable
- if err != nil {
- fmt.Println(err)
- fmt.Println(loggingNotConfigured)
- } else if !cfg.Enable {
- fmt.Println(loggingNotEnabled)
- } else {
- fmt.Printf(loggingEnabled, cfg.Name, cfg.GUID)
- }
- },
-}
-
-var enableCmd = &cobra.Command{
- Use: "enable -n nodeName",
- Short: "Enable Algorand remote logging",
- Long: `This will turn on remote logging. The "friendly name" for the node, used by logging, will be determined by -n nodename.`,
- Args: validateNoPosArgsFn,
- Run: func(cmd *cobra.Command, _ []string) {
- reportWarnln("`goal logging enable` deprecated, use `diagcfg telemetry enable`")
- dataDir := datadir.EnsureSingleDataDir()
- root, err := config.GetGlobalConfigFileRoot()
- var cfgDir *string
- if err == nil {
- cfgDir = &root
- }
- cfg, err := logging.EnsureTelemetryConfig(&dataDir, cfgDir)
- if err != nil {
- fmt.Println(err)
- return
- }
- cfg.Enable = true
- if len(nodeName) > 0 {
- cfg.Name = nodeName
- }
- cfg.Save(cfg.FilePath)
- fmt.Printf("Logging enabled: Name = %s, Guid = %s\n", cfg.Name, cfg.GUID)
- },
-}
-
-var disableCmd = &cobra.Command{
- Use: "disable",
- Short: "Disable Algorand remote logging",
- Args: validateNoPosArgsFn,
- Run: func(cmd *cobra.Command, _ []string) {
- reportWarnf("`goal logging disable` deprecated, use `diagcfg telemetry disable`")
- dataDir := datadir.EnsureSingleDataDir()
- root, err := config.GetGlobalConfigFileRoot()
- var cfgDir *string
- if err == nil {
- cfgDir = &root
- }
- cfg, err := logging.EnsureTelemetryConfig(&dataDir, cfgDir)
-
- // If error loading config, can't disable / no need to disable
- if err != nil {
- return
- }
-
- cfg.Enable = false
- cfg.Save(cfg.FilePath)
- },
-}
-
-var loggingSendCmd = &cobra.Command{
- Use: "send",
- Short: "Upload logs and debugging information for analysis",
- Long: `Upload logs and debugging information to Algorand for analysis. Ledger and wallet data are not included.`,
- Args: validateNoPosArgsFn,
- Run: func(cmd *cobra.Command, _ []string) {
- timestamp := time.Now().UTC().Format("20060102150405")
-
- if logChannel == "" {
- logChannel = config.GetCurrentVersion().Channel
- }
-
- targetFolder := filepath.Join("channel", logChannel)
-
- modifier := ""
- counter := uint(1)
- errcount := 0
- var firsterr error = nil
- datadir.OnDataDirs(func(dataDir string) {
- root, err := config.GetGlobalConfigFileRoot()
- var cfgDir *string
- if err == nil {
- cfgDir = &root
- }
- cfg, err := logging.EnsureTelemetryConfig(&dataDir, cfgDir)
- if err != nil {
- fmt.Println(err)
- return
- }
- basename := cfg.Name
- if len(basename) > 0 {
- basename = basename + "-"
- }
- dirname := filepath.Base(dataDir)
- name := basename + cfg.GUID + "_" + dirname + "-" + timestamp + modifier + ".tar.gz"
-
- for err := range logging.CollectAndUploadData(dataDir, name, targetFolder) {
- fmt.Fprintf(os.Stderr, "%v\n", err)
- if firsterr == nil {
- firsterr = err
- }
- errcount++
- }
- modifier = fmt.Sprintf("-%d", counter)
- counter++
- })
- if errcount != 0 {
- reportErrorf("had %d errors, first: %v", errcount, firsterr)
- }
- },
-}
diff --git a/cmd/goal/messages.go b/cmd/goal/messages.go
index 13be8dc7e7..662e6d065e 100644
--- a/cmd/goal/messages.go
+++ b/cmd/goal/messages.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/multisig.go b/cmd/goal/multisig.go
index 402e80ec21..fb453dec8c 100644
--- a/cmd/goal/multisig.go
+++ b/cmd/goal/multisig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/network.go b/cmd/goal/network.go
index b1ff14e839..c41674f7fd 100644
--- a/cmd/goal/network.go
+++ b/cmd/goal/network.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/node.go b/cmd/goal/node.go
index dd91319f97..1c7de1ca69 100644
--- a/cmd/goal/node.go
+++ b/cmd/goal/node.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -100,12 +100,6 @@ func init() {
createCmd.Flags().BoolVarP(&newNodeArchival, "archival", "a", localDefaults.Archival, "Make the new node archival, storing all blocks")
createCmd.Flags().BoolVarP(&runUnderHost, "hosted", "H", localDefaults.RunHosted, "Configure the new node to run hosted by algoh")
- // The flag for enabling an internal indexer is now deprecated, but we keep it for backwards compatibility for now.
- indexerFlagName := "indexer"
- _ = createCmd.Flags().BoolP(indexerFlagName, "i", false, "")
- createCmd.Flags().MarkDeprecated(indexerFlagName, "no longer used, please remove from your scripts")
- createCmd.Flags().MarkShorthandDeprecated(indexerFlagName, "no longer used, please remove from your scripts")
-
createCmd.Flags().StringVar(&newNodeRelay, "relay", localDefaults.NetAddress, "Configure as a relay with specified listening address (NetAddress)")
createCmd.Flags().StringVar(&listenIP, "api", "", "REST API Endpoint")
createCmd.Flags().BoolVar(&newNodeFullConfig, "full-config", false, "Store full config file")
diff --git a/cmd/goal/node_test.go b/cmd/goal/node_test.go
index b743d8a640..5ab6b3b53a 100644
--- a/cmd/goal/node_test.go
+++ b/cmd/goal/node_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/p2pid.go b/cmd/goal/p2pid.go
index de51c00ab7..2ccdfdc571 100644
--- a/cmd/goal/p2pid.go
+++ b/cmd/goal/p2pid.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/tealsign.go b/cmd/goal/tealsign.go
index bfbad5d526..74b718ece2 100644
--- a/cmd/goal/tealsign.go
+++ b/cmd/goal/tealsign.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/goal/wallet.go b/cmd/goal/wallet.go
index 5dadd597c9..66b9fd2b79 100644
--- a/cmd/goal/wallet.go
+++ b/cmd/goal/wallet.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/incorporate/incorporate.go b/cmd/incorporate/incorporate.go
index 3205f3ed48..92b12db70b 100644
--- a/cmd/incorporate/incorporate.go
+++ b/cmd/incorporate/incorporate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/kmd/codes/codes.go b/cmd/kmd/codes/codes.go
index 5f164c8b05..94bb78c261 100644
--- a/cmd/kmd/codes/codes.go
+++ b/cmd/kmd/codes/codes.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/kmd/main.go b/cmd/kmd/main.go
index 83fe77f795..bd1192a9ad 100644
--- a/cmd/kmd/main.go
+++ b/cmd/kmd/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/kmd/mlock_darwin.go b/cmd/kmd/mlock_darwin.go
index 8734c947bd..73bd7b42f2 100644
--- a/cmd/kmd/mlock_darwin.go
+++ b/cmd/kmd/mlock_darwin.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/kmd/mlock_linux.go b/cmd/kmd/mlock_linux.go
index 1120bdd0fe..f2b7ffb2b6 100644
--- a/cmd/kmd/mlock_linux.go
+++ b/cmd/kmd/mlock_linux.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/kmd/mlock_windows.go b/cmd/kmd/mlock_windows.go
index 373442f94d..1c06adacff 100644
--- a/cmd/kmd/mlock_windows.go
+++ b/cmd/kmd/mlock_windows.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/loadgenerator/config.go b/cmd/loadgenerator/config.go
index a696e5c6a4..8a8053e05d 100644
--- a/cmd/loadgenerator/config.go
+++ b/cmd/loadgenerator/config.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/loadgenerator/main.go b/cmd/loadgenerator/main.go
index eec97721c0..aaf62c0577 100644
--- a/cmd/loadgenerator/main.go
+++ b/cmd/loadgenerator/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/msgpacktool/main.go b/cmd/msgpacktool/main.go
index dc6f87072c..aae95ec9d3 100644
--- a/cmd/msgpacktool/main.go
+++ b/cmd/msgpacktool/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/netdummy/main.go b/cmd/netdummy/main.go
index 5d9fdf370f..f77aa827f4 100644
--- a/cmd/netdummy/main.go
+++ b/cmd/netdummy/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/netgoal/commands.go b/cmd/netgoal/commands.go
index 699a2f393b..c87f060816 100644
--- a/cmd/netgoal/commands.go
+++ b/cmd/netgoal/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/netgoal/generate.go b/cmd/netgoal/generate.go
index 353c2b71bd..49aff61dab 100644
--- a/cmd/netgoal/generate.go
+++ b/cmd/netgoal/generate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/netgoal/messages.go b/cmd/netgoal/messages.go
index e378097170..e57a7490d1 100644
--- a/cmd/netgoal/messages.go
+++ b/cmd/netgoal/messages.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/netgoal/network.go b/cmd/netgoal/network.go
index 487ac4cdcc..af25c2787c 100644
--- a/cmd/netgoal/network.go
+++ b/cmd/netgoal/network.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/netgoal/recipe.go b/cmd/netgoal/recipe.go
index 32c4305e0f..202fca45d3 100644
--- a/cmd/netgoal/recipe.go
+++ b/cmd/netgoal/recipe.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/nodecfg/apply.go b/cmd/nodecfg/apply.go
index 1f349f4681..9bffda0b62 100644
--- a/cmd/nodecfg/apply.go
+++ b/cmd/nodecfg/apply.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/nodecfg/commands.go b/cmd/nodecfg/commands.go
index 1d2258945c..c795e95ddb 100644
--- a/cmd/nodecfg/commands.go
+++ b/cmd/nodecfg/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/nodecfg/download.go b/cmd/nodecfg/download.go
index 85c554e7ef..8ee245cd4d 100644
--- a/cmd/nodecfg/download.go
+++ b/cmd/nodecfg/download.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/nodecfg/get.go b/cmd/nodecfg/get.go
index c42554da45..9a47fb40a8 100644
--- a/cmd/nodecfg/get.go
+++ b/cmd/nodecfg/get.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/nodecfg/untar.go b/cmd/nodecfg/untar.go
index 2339bbe00d..c704dd958c 100644
--- a/cmd/nodecfg/untar.go
+++ b/cmd/nodecfg/untar.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/opdoc/opdoc.go b/cmd/opdoc/opdoc.go
index 8b2243879f..cdc17619d3 100644
--- a/cmd/opdoc/opdoc.go
+++ b/cmd/opdoc/opdoc.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -22,7 +22,7 @@ import (
"io"
"math"
"os"
- "sort"
+ "slices"
"strings"
"github.com/algorand/go-algorand/config"
@@ -30,7 +30,15 @@ import (
"github.com/algorand/go-algorand/protocol"
)
-// OpImmediateNote returns a short string about immediate data which follows the op byte
+// slug returns the auto generated named anchor "slug" for a given heading
+// created by mdbook.
+func slug(s string) string {
+ s = strings.ToLower(s)
+ s = strings.ReplaceAll(s, " ", "-")
+ return s
+}
+
+// opImmediateNoteSyntaxMarkdown returns a short string about immediate data which follows the op byte
func opImmediateNoteSyntaxMarkdown(name string, oids []logic.OpImmediateDetails) string {
if len(oids) == 0 {
return ""
@@ -41,7 +49,7 @@ func opImmediateNoteSyntaxMarkdown(name string, oids []logic.OpImmediateDetails)
for idx, oid := range oids {
argNote := oid.Comment
if oid.Reference != "" {
- argNote = fmt.Sprintf("[%s](#field-group-%s)", oid.Reference, strings.ToLower(oid.Reference))
+ argNote = fmt.Sprintf("[%s](#%s)", oid.Reference, slug(oid.Reference))
}
argNames[idx] = oid.Name
argDocs[idx] = fmt.Sprintf("%s: %s", oid.Name, argNote)
@@ -63,8 +71,8 @@ func opImmediateNoteEncoding(opcode byte, oids []logic.OpImmediateDetails) strin
}
func opGroupMarkdownTable(names []string, out io.Writer, version uint64) {
- fmt.Fprint(out, `| Opcode | Description |
-| - | -- |
+ fmt.Fprint(out, `| OPCODE | DESCRIPTION |
+| :-: | :---------- |
`)
opSpecs := logic.OpsByName[version]
for _, opname := range names {
@@ -74,7 +82,7 @@ func opGroupMarkdownTable(names []string, out io.Writer, version uint64) {
}
fmt.Fprintf(out, "| `%s%s` | %s |\n",
markdownTableEscape(spec.Name), immediateMarkdown(&spec),
- markdownTableEscape(logic.OpDoc(opname)))
+ markdownTableEscape(logic.OpDescOf(opname).Short))
}
}
@@ -83,33 +91,30 @@ func markdownTableEscape(x string) string {
}
func namedStackTypesMarkdown(out io.Writer, stackTypes []namedType) {
- fmt.Fprintf(out, "#### Definitions\n\n")
- fmt.Fprintf(out, "| Name | Bound | AVM Type |\n")
- fmt.Fprintf(out, "| ---- | ---- | -------- |\n")
+ fmt.Fprintf(out, "| NAME | BOUND | AVM TYPE |\n")
+ fmt.Fprintf(out, "| :--- | :---- | :------: |\n")
for _, st := range stackTypes {
- fmt.Fprintf(out, "| %s | %s | %s |\n", st.Name, st.boundString(), st.AVMType)
+ bound := st.boundString()
+ if bound == "" {
+ fmt.Fprintf(out, "| `%s` | | `%s` |\n", st.Name, st.AVMType)
+ } else {
+ fmt.Fprintf(out, "| `%s` | %s | `%s` |\n", st.Name, bound, st.AVMType)
+ }
}
- fmt.Fprintf(out, "\n")
}
-func integerConstantsTableMarkdown(out io.Writer) {
- fmt.Fprintf(out, "#### OnComplete\n\n")
- fmt.Fprintf(out, "%s\n\n", logic.OnCompletionPreamble)
- fmt.Fprintf(out, "| Value | Name | Description |\n")
- fmt.Fprintf(out, "| - | ---- | -------- |\n")
- for i, name := range logic.OnCompletionNames {
- value := uint64(i)
- fmt.Fprintf(out, "| %d | %s | %s |\n", value, markdownTableEscape(name), logic.OnCompletionDescription(value))
- }
- fmt.Fprintf(out, "\n")
- fmt.Fprintf(out, "#### TypeEnum constants\n\n")
- fmt.Fprintf(out, "| Value | Name | Description |\n")
- fmt.Fprintf(out, "| - | --- | ------ |\n")
- for i, name := range logic.TxnTypeNames {
- fmt.Fprintf(out, "| %d | %s | %s |\n", i, markdownTableEscape(name), logic.TypeNameDescriptions[name])
- }
- out.Write([]byte("\n"))
+func integerConstantsTableMarkdown(out io.Writer, what string, names []string, descs map[string]string) {
+ fmt.Fprintf(out, "| %s | VALUE | DESCRIPTION |\n", what)
+ fmt.Fprintf(out, "| :----: | :---: | :---------- |\n")
+ for i, name := range names {
+ description := descs[name]
+ if description == "" {
+ fmt.Fprintf(os.Stderr, "%s is undocumented\n", name)
+ os.Exit(1)
+ }
+ fmt.Fprintf(out, "| `%s` | `%d` | %s |\n", markdownTableEscape(name), i, description)
+ }
}
func fieldGroupMarkdown(out io.Writer, group *logic.FieldGroup, version uint64) {
@@ -131,18 +136,18 @@ func fieldGroupMarkdown(out io.Writer, group *logic.FieldGroup, version uint64)
showVers = true
}
}
- headers := "| Index | Name |"
- widths := "| - | ------ |"
+ headers := "| INDEX | NAME |"
+ widths := "| :-: | :------ |"
if showTypes {
- headers += " Type |"
- widths += " -- |"
+ headers += " TYPE |"
+ widths += ":--:|"
}
if showVers {
- headers += " In |"
- widths += " - |"
+ headers += " IN |"
+ widths += ":-:|"
}
- headers += " Notes |\n"
- widths += " --------- |\n"
+ headers += " NOTES |\n"
+ widths += " :--------- |\n"
fmt.Fprint(out, headers, widths)
for i, name := range group.Names {
spec, ok := group.SpecByName(name)
@@ -162,7 +167,6 @@ func fieldGroupMarkdown(out io.Writer, group *logic.FieldGroup, version uint64)
}
fmt.Fprintf(out, "%s | %s |\n", str, spec.Note())
}
- fmt.Fprint(out, "\n")
}
func immediateMarkdown(op *logic.OpSpec) string {
@@ -228,7 +232,11 @@ func opToMarkdown(out io.Writer, op *logic.OpSpec, groupDocWritten map[string]bo
fmt.Fprintf(out, "\n## %s\n\n%s%s\n%s", op.Name, syntax, encoding, stackEffects)
- fmt.Fprintf(out, "- %s\n", logic.OpDoc(op.Name))
+ desc := logic.OpDescOf(op.Name)
+ fmt.Fprintf(out, "- %s\n", desc.Short)
+ if desc.Sugar != "" {
+ fmt.Fprintf(out, "- %s\n", desc.Sugar)
+ }
cost := op.DocCost(version)
if cost != "1" {
fmt.Fprintf(out, "- **Cost**: %s\n", cost)
@@ -243,20 +251,30 @@ func opToMarkdown(out io.Writer, op *logic.OpSpec, groupDocWritten map[string]bo
for i := range op.OpDetails.Immediates {
group := op.OpDetails.Immediates[i].Group
if group != nil && group.Doc != "" && !groupDocWritten[group.Name] {
- fmt.Fprintf(out, "\n### %s\n\n%s\n\n", group.Name, group.Doc)
+ fmt.Fprintf(out, "\n### %s\n\n", group.Heading())
+ if strings.Contains(group.Doc, " ") {
+ fmt.Fprintf(out, "%s\n\n", group.Doc)
+ }
fieldGroupMarkdown(out, group, version)
groupDocWritten[group.Name] = true
}
}
- ode := logic.OpDocExtra(op.Name)
- if ode != "" {
- fmt.Fprintf(out, "\n%s\n", ode)
+ if desc.Extra != "" {
+ fmt.Fprintf(out, "\n%s\n", desc.Extra)
}
return nil
}
func opsToMarkdown(out io.Writer, version uint64) error {
- _, err := fmt.Fprintf(out, "# v%d Opcodes\n\nOps have a 'cost' of 1 unless otherwise specified.\n\n", version)
+ _, err := fmt.Fprintf(out, `
+# Version %d Opcodes
+
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
+`, version)
if err != nil {
return err
}
@@ -311,19 +329,19 @@ func (nt namedType) boundString() string {
// If they're equal, the val should match exactly
if nt.Bound[0] > 0 && nt.Bound[0] == nt.Bound[1] {
- return fmt.Sprintf("%s == %d", val, nt.Bound[0])
+ return fmt.Sprintf(`\\( %s = %d \\)`, val, nt.Bound[0])
}
// otherwise, provide min/max bounds as lte expression
minBound, maxBound := "", ""
if nt.Bound[0] > 0 {
- minBound = fmt.Sprintf("%d <= ", nt.Bound[0])
+ minBound = fmt.Sprintf(`%d \leq `, nt.Bound[0])
}
if nt.Bound[1] > 0 {
- maxBound = fmt.Sprintf(" <= %d", nt.Bound[1])
+ maxBound = fmt.Sprintf(` \leq %d`, nt.Bound[1])
}
- return fmt.Sprintf("%s%s%s", minBound, val, maxBound)
+ return fmt.Sprintf(`\\( %s%s%s \\)`, minBound, val, maxBound)
}
@@ -418,8 +436,9 @@ func buildLanguageSpec(opGroups map[string][]string, namedTypes []namedType, ver
records[i].Size = spec.OpDetails.Size
records[i].DocCost = spec.DocCost(version)
records[i].ArgEnum, records[i].ArgEnumTypes = argEnums(spec.Name, version)
- records[i].Doc = strings.ReplaceAll(logic.OpDoc(spec.Name), " ", "\n")
- records[i].DocExtra = logic.OpDocExtra(spec.Name)
+ desc := logic.OpDescOf(spec.Name)
+ records[i].Doc = desc.Short
+ records[i].DocExtra = desc.Extra
records[i].ImmediateNote = logic.OpImmediateDetailsFromSpec(spec)
records[i].Groups = opGroups[spec.Name]
records[i].IntroducedVersion = spec.Version
@@ -447,8 +466,9 @@ func main() {
opGroups := make(map[string][]string, len(logic.OpSpecs))
for grp, names := range logic.OpGroups {
- fname := fmt.Sprintf("%s.md", grp)
- fname = strings.ReplaceAll(fname, " ", "_")
+ fname := fmt.Sprintf("%s.md", strings.ToLower(grp))
+ fname = strings.ReplaceAll(fname, " ", "-")
+
fout := create(fname)
opGroupMarkdownTable(names, fout, docVersion)
fout.Close()
@@ -457,37 +477,30 @@ func main() {
}
}
- named := make([]namedType, 0, len(logic.AllStackTypes))
+ stackTypes := make([]namedType, 0, len(logic.AllStackTypes))
for abbr, t := range logic.AllStackTypes {
- named = append(named, namedType{
+ stackTypes = append(stackTypes, namedType{
Name: t.String(),
Bound: []uint64{t.Bound[0], t.Bound[1]},
Abbreviation: string(abbr),
AVMType: t.AVMType.String(),
})
}
- sort.Slice(named, func(i, j int) bool { return named[i].Name < named[j].Name })
+ slices.SortFunc(stackTypes, func(a, b namedType) int {
+ return strings.Compare(a.Name, b.Name)
+ })
- constants := create("named_integer_constants.md")
- integerConstantsTableMarkdown(constants)
- constants.Close()
+ oc := create("constants-on-completion.md")
+ integerConstantsTableMarkdown(oc, "ACTION", logic.OnCompletionNames[:], logic.OnCompletionDescriptions)
+ oc.Close()
- namedStackTypes := create("named_stack_types.md")
- namedStackTypesMarkdown(namedStackTypes, named)
- namedStackTypes.Close()
+ te := create("constants-type-enums.md")
+ integerConstantsTableMarkdown(te, "TYPE", logic.TxnTypeNames[:], logic.TypeNameDescriptions)
+ te.Close()
- written := make(map[string]bool)
- opSpecs := logic.OpcodesByVersion(uint64(docVersion))
- for _, spec := range opSpecs {
- for _, imm := range spec.OpDetails.Immediates {
- if imm.Group != nil && !written[imm.Group.Name] {
- out := create(strings.ToLower(imm.Group.Name) + "_fields.md")
- fieldGroupMarkdown(out, imm.Group, docVersion)
- out.Close()
- written[imm.Group.Name] = true
- }
- }
- }
+ namedStackTypes := create("avm-stack-types.md")
+ namedStackTypesMarkdown(namedStackTypes, stackTypes)
+ namedStackTypes.Close()
tealtm := create("teal.tmLanguage.json")
enc := json.NewEncoder(tealtm)
@@ -502,7 +515,7 @@ func main() {
langspecjs := create(fmt.Sprintf("langspec_v%d.json", v))
enc := json.NewEncoder(langspecjs)
enc.SetIndent("", " ")
- if err := enc.Encode(buildLanguageSpec(opGroups, named, v)); err != nil {
+ if err := enc.Encode(buildLanguageSpec(opGroups, stackTypes, v)); err != nil {
fmt.Fprintf(os.Stderr, "error encoding langspec JSON for version %d: %v\n", v, err)
os.Exit(1)
}
diff --git a/cmd/opdoc/tmLanguage.go b/cmd/opdoc/tmLanguage.go
index 4ccb794da8..e6d22be8fa 100644
--- a/cmd/opdoc/tmLanguage.go
+++ b/cmd/opdoc/tmLanguage.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -199,7 +199,7 @@ func buildSyntaxHighlight(version uint64) *tmLanguage {
Name: "keyword.other.teal",
Match: fmt.Sprintf("^(%s)\\b", strings.Join(loading, "|")),
})
- case "State Access", "Box Access":
+ case "Block Access", "Account Access", "Asset Access", "Application Access", "Box Access":
allAccess = append(allAccess, names...)
// For these, accumulate into allArithmetics,
// and only add to keyword.Patterns later, when all
diff --git a/cmd/partitiontest_linter/linter.go b/cmd/partitiontest_linter/linter.go
index 6807e8c2ed..ee09c901d1 100644
--- a/cmd/partitiontest_linter/linter.go
+++ b/cmd/partitiontest_linter/linter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/partitiontest_linter/linter_test.go b/cmd/partitiontest_linter/linter_test.go
index 5422eeb47d..abd7374314 100644
--- a/cmd/partitiontest_linter/linter_test.go
+++ b/cmd/partitiontest_linter/linter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/partitiontest_linter/testdata/linter_testdata_test.go b/cmd/partitiontest_linter/testdata/linter_testdata_test.go
index 2e06e15dfd..82dd19e7b4 100644
--- a/cmd/partitiontest_linter/testdata/linter_testdata_test.go
+++ b/cmd/partitiontest_linter/testdata/linter_testdata_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/pingpong/commands.go b/cmd/pingpong/commands.go
index ab938063b7..361af92a3f 100644
--- a/cmd/pingpong/commands.go
+++ b/cmd/pingpong/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/pingpong/runCmd.go b/cmd/pingpong/runCmd.go
index 5d70be44ad..e122a46078 100644
--- a/cmd/pingpong/runCmd.go
+++ b/cmd/pingpong/runCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/pingpong/teal_programs.go b/cmd/pingpong/teal_programs.go
index 850f9a1dbb..cbc6acee41 100644
--- a/cmd/pingpong/teal_programs.go
+++ b/cmd/pingpong/teal_programs.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/bundle_home_html.sh b/cmd/tealdbg/bundle_home_html.sh
index 63091361ff..d2d2909fc8 100755
--- a/cmd/tealdbg/bundle_home_html.sh
+++ b/cmd/tealdbg/bundle_home_html.sh
@@ -3,7 +3,7 @@
THISDIR=$(dirname $0)
cat < $THISDIR/homepage.go
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/cdt/proto.go b/cmd/tealdbg/cdt/proto.go
index 60e7f9c4d5..0aef5ed009 100644
--- a/cmd/tealdbg/cdt/proto.go
+++ b/cmd/tealdbg/cdt/proto.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/cdtSession.go b/cmd/tealdbg/cdtSession.go
index 71d25c7348..4b49a7d466 100644
--- a/cmd/tealdbg/cdtSession.go
+++ b/cmd/tealdbg/cdtSession.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/cdtSession_test.go b/cmd/tealdbg/cdtSession_test.go
index 83b9ca815e..b6700b1127 100644
--- a/cmd/tealdbg/cdtSession_test.go
+++ b/cmd/tealdbg/cdtSession_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/cdtState.go b/cmd/tealdbg/cdtState.go
index b84d5916a7..eaa6eb4ba5 100644
--- a/cmd/tealdbg/cdtState.go
+++ b/cmd/tealdbg/cdtState.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/cdtStateObjects.go b/cmd/tealdbg/cdtStateObjects.go
index 13b8f6724a..c13810e656 100644
--- a/cmd/tealdbg/cdtStateObjects.go
+++ b/cmd/tealdbg/cdtStateObjects.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/cdtdbg.go b/cmd/tealdbg/cdtdbg.go
index 0394d6dc63..ea38efff7f 100644
--- a/cmd/tealdbg/cdtdbg.go
+++ b/cmd/tealdbg/cdtdbg.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/cdtdbg_test.go b/cmd/tealdbg/cdtdbg_test.go
index 2faa76ca45..ab0e2c11a2 100644
--- a/cmd/tealdbg/cdtdbg_test.go
+++ b/cmd/tealdbg/cdtdbg_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/debugger.go b/cmd/tealdbg/debugger.go
index ceb7c46a3c..2090256316 100644
--- a/cmd/tealdbg/debugger.go
+++ b/cmd/tealdbg/debugger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/debugger_test.go b/cmd/tealdbg/debugger_test.go
index 46b562cc1d..d03e656c35 100644
--- a/cmd/tealdbg/debugger_test.go
+++ b/cmd/tealdbg/debugger_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/dryrunRequest.go b/cmd/tealdbg/dryrunRequest.go
index 79dcfa1e8d..e89e8cfc3d 100644
--- a/cmd/tealdbg/dryrunRequest.go
+++ b/cmd/tealdbg/dryrunRequest.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/homepage.go b/cmd/tealdbg/homepage.go
index e82c5ce23e..4338844c2e 100644
--- a/cmd/tealdbg/homepage.go
+++ b/cmd/tealdbg/homepage.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/local.go b/cmd/tealdbg/local.go
index 5921b9e0cd..946d12f001 100644
--- a/cmd/tealdbg/local.go
+++ b/cmd/tealdbg/local.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/localLedger.go b/cmd/tealdbg/localLedger.go
index d420c2edc6..cea5b2adbb 100644
--- a/cmd/tealdbg/localLedger.go
+++ b/cmd/tealdbg/localLedger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/localLedger_test.go b/cmd/tealdbg/localLedger_test.go
index 7e74ec5b9a..ff0469dc3c 100644
--- a/cmd/tealdbg/localLedger_test.go
+++ b/cmd/tealdbg/localLedger_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/local_test.go b/cmd/tealdbg/local_test.go
index f789253768..c781e1d3c0 100644
--- a/cmd/tealdbg/local_test.go
+++ b/cmd/tealdbg/local_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/main.go b/cmd/tealdbg/main.go
index f081bde83f..51848f5f1f 100644
--- a/cmd/tealdbg/main.go
+++ b/cmd/tealdbg/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -17,8 +17,10 @@
package main
import (
+ "fmt"
"log"
"os"
+ "time"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
@@ -29,6 +31,9 @@ import (
)
func main() {
+ fmt.Println("tealdbg is deprecated and will be removed soon. Please speak up if the feature matters to you.")
+ time.Sleep(3 * time.Second)
+
// Hidden command to generate docs in a given directory
// tealdbg generate-docs [path]
if len(os.Args) == 3 && os.Args[1] == "generate-docs" {
diff --git a/cmd/tealdbg/remote.go b/cmd/tealdbg/remote.go
index ff4f66a2d9..f4459b8dab 100644
--- a/cmd/tealdbg/remote.go
+++ b/cmd/tealdbg/remote.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/remote_test.go b/cmd/tealdbg/remote_test.go
index f79464ef24..e9806ad909 100644
--- a/cmd/tealdbg/remote_test.go
+++ b/cmd/tealdbg/remote_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/server.go b/cmd/tealdbg/server.go
index 2fffb2cb2d..216c746e24 100644
--- a/cmd/tealdbg/server.go
+++ b/cmd/tealdbg/server.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/server_test.go b/cmd/tealdbg/server_test.go
index df15bc3736..04c03725de 100644
--- a/cmd/tealdbg/server_test.go
+++ b/cmd/tealdbg/server_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/util.go b/cmd/tealdbg/util.go
index e0ad536513..c21f6083e5 100644
--- a/cmd/tealdbg/util.go
+++ b/cmd/tealdbg/util.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/webdbg.go b/cmd/tealdbg/webdbg.go
index 8039259cd5..9d4dde8b44 100644
--- a/cmd/tealdbg/webdbg.go
+++ b/cmd/tealdbg/webdbg.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/tealdbg/webdbg_test.go b/cmd/tealdbg/webdbg_test.go
index f7aadd7bf3..cb36742821 100644
--- a/cmd/tealdbg/webdbg_test.go
+++ b/cmd/tealdbg/webdbg_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/updater/commands.go b/cmd/updater/commands.go
index d32a7a8434..337d42a3df 100644
--- a/cmd/updater/commands.go
+++ b/cmd/updater/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/updater/sendCmd.go b/cmd/updater/sendCmd.go
index ce348e3f6e..fde96170cd 100644
--- a/cmd/updater/sendCmd.go
+++ b/cmd/updater/sendCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/updater/toolsCmd.go b/cmd/updater/toolsCmd.go
index b03825244a..2e1b1f7694 100644
--- a/cmd/updater/toolsCmd.go
+++ b/cmd/updater/toolsCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/updater/update.sh b/cmd/updater/update.sh
index f0544204f3..8f45210188 100755
--- a/cmd/updater/update.sh
+++ b/cmd/updater/update.sh
@@ -492,7 +492,7 @@ function run_systemd_action() {
function backup_binaries() {
echo "Backing up current binary files..."
mkdir -p "${BINDIR}/backup"
- BACKUPFILES="algod kmd carpenter doberman goal update.sh updater diagcfg"
+ BACKUPFILES="algod kmd goal update.sh updater diagcfg"
# add node_exporter to the files list we're going to backup, but only we if had it previously deployed.
[ -f "${BINDIR}/node_exporter" ] && BACKUPFILES="${BACKUPFILES} node_exporter"
# If we have algotmpl, we should back it up too
@@ -691,6 +691,16 @@ function apply_fixups() {
# Delete obsolete algorand binary - renamed to 'goal'
rm "${BINDIR}/algorand" >/dev/null 2>&1
+ # Delete obsolete binaries removed in go-algorand
+ rm "${BINDIR}/carpenter" >/dev/null 2>&1
+ rm "${BINDIR}/catchupsrv" >/dev/null 2>&1
+ rm "${BINDIR}/doberman" >/dev/null 2>&1
+ rm "${BINDIR}/ddconfig.sh" >/dev/null 2>&1
+ rm "${BINDIR}/tealcut" >/dev/null 2>&1
+ rm "${BINDIR}/cc_service" >/dev/null 2>&1
+ rm "${BINDIR}/cc_agent" >/dev/null 2>&1
+ rm "${BINDIR}/cc_client" >/dev/null 2>&1
+
for DD in ${DATADIRS[@]}; do
clean_legacy_logs "${DD}"
diff --git a/cmd/updater/util.go b/cmd/updater/util.go
index 954d2bbc1c..5b156102e8 100644
--- a/cmd/updater/util.go
+++ b/cmd/updater/util.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/updater/versionCmd.go b/cmd/updater/versionCmd.go
index 5468e06cdb..eb09f49c8c 100644
--- a/cmd/updater/versionCmd.go
+++ b/cmd/updater/versionCmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/updater/version_test.go b/cmd/updater/version_test.go
index 9409717da2..51d5ec4303 100644
--- a/cmd/updater/version_test.go
+++ b/cmd/updater/version_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/util/cmd.go b/cmd/util/cmd.go
index f1f6c58022..7be18d3742 100644
--- a/cmd/util/cmd.go
+++ b/cmd/util/cmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/util/datadir/datadir.go b/cmd/util/datadir/datadir.go
index 3c9364f7e6..b70a5e79b9 100644
--- a/cmd/util/datadir/datadir.go
+++ b/cmd/util/datadir/datadir.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/util/datadir/messages.go b/cmd/util/datadir/messages.go
index a5a7d4813a..824b38048d 100644
--- a/cmd/util/datadir/messages.go
+++ b/cmd/util/datadir/messages.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/cmd/util/datadir/report.go b/cmd/util/datadir/report.go
index 5d8325a13f..f45e937a17 100644
--- a/cmd/util/datadir/report.go
+++ b/cmd/util/datadir/report.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/components/mocks/mockCatchpointCatchupAccessor.go b/components/mocks/mockCatchpointCatchupAccessor.go
index 4297db66c8..880ce4b8ad 100644
--- a/components/mocks/mockCatchpointCatchupAccessor.go
+++ b/components/mocks/mockCatchpointCatchupAccessor.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/components/mocks/mockNetwork.go b/components/mocks/mockNetwork.go
index 21d640a084..f8de305799 100644
--- a/components/mocks/mockNetwork.go
+++ b/components/mocks/mockNetwork.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/components/mocks/mockParticipationRegistry.go b/components/mocks/mockParticipationRegistry.go
index 3e4cfaf5ca..1bee47ae74 100644
--- a/components/mocks/mockParticipationRegistry.go
+++ b/components/mocks/mockParticipationRegistry.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/bounds/bounds.go b/config/bounds/bounds.go
index 0613087df0..db451ecec4 100644
--- a/config/bounds/bounds.go
+++ b/config/bounds/bounds.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -115,6 +115,9 @@ var MaxTxnBytesPerBlock int
// MaxAppTxnForeignApps is the max number of foreign apps per txn across all consensus versions
var MaxAppTxnForeignApps int
+// MaxAppAccess is the max number of references allowed in txn.Access per txn across all consensus versions
+var MaxAppAccess int
+
// MaxEvalDeltaTotalLogSize is the maximum size of the sum of all log sizes in a single eval delta.
const MaxEvalDeltaTotalLogSize = 1024
diff --git a/config/buildvars.go b/config/buildvars.go
index de55a25f27..18e1300406 100644
--- a/config/buildvars.go
+++ b/config/buildvars.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/config.go b/config/config.go
index 96bf001a5b..b235f3e317 100644
--- a/config/config.go
+++ b/config/config.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/config_test.go b/config/config_test.go
index 88e90289e3..19cf29952d 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -575,7 +575,7 @@ func TestLocal_GetVersionedDefaultLocalConfig(t *testing.T) {
}
}
-// TestLocalVersionField - ensures the Version contains only versions tags, the versions are all contiguous, and that no non-version tags are included there.
+// TestLocal_VersionField - ensures the Version contains only versions tags, the versions are all contiguous, and that no non-version tags are included there.
func TestLocal_VersionField(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
@@ -653,83 +653,83 @@ func TestLocal_TxFiltering(t *testing.T) {
require.True(t, cfg.TxFilterCanonicalEnabled())
}
-func TestLocal_IsGossipServer(t *testing.T) {
+func TestLocal_IsListenServer(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
cfg := GetDefaultLocal()
- require.False(t, cfg.IsGossipServer())
- require.False(t, cfg.IsWsGossipServer())
- require.False(t, cfg.IsP2PGossipServer())
+ require.False(t, cfg.IsListenServer())
+ require.False(t, cfg.IsWsListenServer())
+ require.False(t, cfg.IsP2PListenServer())
require.False(t, cfg.IsHybridServer())
cfg.NetAddress = ":4160"
- require.True(t, cfg.IsGossipServer())
- require.True(t, cfg.IsWsGossipServer())
- require.False(t, cfg.IsP2PGossipServer())
+ require.True(t, cfg.IsListenServer())
+ require.True(t, cfg.IsWsListenServer())
+ require.False(t, cfg.IsP2PListenServer())
require.False(t, cfg.IsHybridServer())
cfg.EnableGossipService = false
// EnableGossipService does not matter
- require.True(t, cfg.IsGossipServer())
- require.True(t, cfg.IsWsGossipServer())
- require.False(t, cfg.IsP2PGossipServer())
+ require.True(t, cfg.IsListenServer())
+ require.True(t, cfg.IsWsListenServer())
+ require.False(t, cfg.IsP2PListenServer())
require.False(t, cfg.IsHybridServer())
cfg.EnableP2P = true
cfg.NetAddress = ":4160"
- require.True(t, cfg.IsGossipServer())
- require.False(t, cfg.IsWsGossipServer())
- require.True(t, cfg.IsP2PGossipServer())
+ require.True(t, cfg.IsListenServer())
+ require.False(t, cfg.IsWsListenServer())
+ require.True(t, cfg.IsP2PListenServer())
require.False(t, cfg.IsHybridServer())
cfg.EnableP2P = false
cfg.EnableP2PHybridMode = true
// with net address set it is ws net gossip server
- require.True(t, cfg.IsGossipServer())
- require.True(t, cfg.IsWsGossipServer())
- require.False(t, cfg.IsP2PGossipServer())
+ require.True(t, cfg.IsListenServer())
+ require.True(t, cfg.IsWsListenServer())
+ require.False(t, cfg.IsP2PListenServer())
require.False(t, cfg.IsHybridServer())
cfg.EnableP2PHybridMode = true
cfg.NetAddress = ""
- require.False(t, cfg.IsGossipServer())
- require.False(t, cfg.IsWsGossipServer())
- require.False(t, cfg.IsP2PGossipServer())
+ require.False(t, cfg.IsListenServer())
+ require.False(t, cfg.IsWsListenServer())
+ require.False(t, cfg.IsP2PListenServer())
require.False(t, cfg.IsHybridServer())
cfg.EnableP2PHybridMode = true
cfg.P2PHybridNetAddress = ":4190"
- require.True(t, cfg.IsGossipServer())
- require.False(t, cfg.IsWsGossipServer())
- require.True(t, cfg.IsP2PGossipServer())
+ require.True(t, cfg.IsListenServer())
+ require.False(t, cfg.IsWsListenServer())
+ require.True(t, cfg.IsP2PListenServer())
require.False(t, cfg.IsHybridServer())
cfg.EnableP2PHybridMode = true
cfg.NetAddress = ":4160"
cfg.P2PHybridNetAddress = ":4190"
- require.True(t, cfg.IsGossipServer())
- require.True(t, cfg.IsWsGossipServer())
- require.True(t, cfg.IsP2PGossipServer())
+ require.True(t, cfg.IsListenServer())
+ require.True(t, cfg.IsWsListenServer())
+ require.True(t, cfg.IsP2PListenServer())
require.True(t, cfg.IsHybridServer())
cfg.EnableP2PHybridMode = true
cfg.EnableP2P = true
cfg.NetAddress = ":4160"
cfg.P2PHybridNetAddress = ":4190"
- require.True(t, cfg.IsGossipServer())
- require.True(t, cfg.IsWsGossipServer())
- require.True(t, cfg.IsP2PGossipServer())
+ require.True(t, cfg.IsListenServer())
+ require.True(t, cfg.IsWsListenServer())
+ require.True(t, cfg.IsP2PListenServer())
require.True(t, cfg.IsHybridServer())
cfg.EnableP2PHybridMode = true
cfg.EnableP2P = true
cfg.NetAddress = ":4160"
cfg.P2PHybridNetAddress = ""
- require.True(t, cfg.IsGossipServer())
- require.True(t, cfg.IsWsGossipServer())
- require.False(t, cfg.IsP2PGossipServer())
+ require.True(t, cfg.IsListenServer())
+ require.True(t, cfg.IsWsListenServer())
+ require.False(t, cfg.IsP2PListenServer())
require.False(t, cfg.IsHybridServer())
}
diff --git a/config/consensus.go b/config/consensus.go
index 3045b83eb9..a464c250dc 100644
--- a/config/consensus.go
+++ b/config/consensus.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -247,6 +247,9 @@ type ConsensusParams struct {
// SupportRekeying indicates support for account rekeying (the RekeyTo and AuthAddr fields)
SupportRekeying bool
+ // EnforceAuthAddrSenderDiff requires that AuthAddr must be empty or different from Sender
+ EnforceAuthAddrSenderDiff bool
+
// application support
Application bool
@@ -539,11 +542,6 @@ type ConsensusParams struct {
// EnableBoxRefNameError specifies that box ref names should be validated early
EnableBoxRefNameError bool
- // EnableUnnamedBoxAccessInNewApps allows newly created (in this group) apps to
- // create boxes that were not named in a box ref. Each empty box ref in the
- // group allows one such creation.
- EnableUnnamedBoxAccessInNewApps bool
-
// ExcludeExpiredCirculation excludes expired stake from the total online stake
// used by agreement for Circulation, and updates the calculation of StateProofOnlineTotalWeight used
// by state proofs to use the same method (rather than excluding stake from the top N stakeholders as before).
@@ -572,11 +570,16 @@ type ConsensusParams struct {
// EnableSha512BlockHash adds an additional SHA-512 hash to the block header.
EnableSha512BlockHash bool
- // EnableInnerClawbackWithoutSenderHolding allows an inner clawback (axfer
- // w/ AssetSender) even if the Sender holding of the asset is not
- // available. This parameters can be removed and assumed true after the
- // first consensus release in which it is set true.
- EnableInnerClawbackWithoutSenderHolding bool
+ // AppSizeUpdates allows application update transactions to change
+ // the extra-program-pages and global schema sizes. Since it enables newly
+ // legal transactions, this parameter can be removed and assumed true after
+ // the first consensus release in which it is set true.
+ AppSizeUpdates bool
+
+ // AllowZeroLocalAppRef allows for a 0 in a LocalRef of the access list to
+ // specify the current app. This parameter can be removed and assumed true
+ // after the first consensus release in which it is set true.
+ AllowZeroLocalAppRef bool
}
// ProposerPayoutRules puts several related consensus parameters in one place. The same
@@ -762,6 +765,7 @@ func checkSetAllocBounds(p ConsensusParams) {
checkSetMax(p.MaxTxnBytesPerBlock, &bounds.MaxTxnBytesPerBlock)
checkSetMax(p.MaxAppTxnForeignApps, &bounds.MaxAppTxnForeignApps)
+ checkSetMax(p.MaxAppAccess, &bounds.MaxAppAccess)
}
// DeepCopy creates a deep copy of a consensus protocols map.
@@ -1438,13 +1442,10 @@ func initConsensusProtocols() {
v41.EnableAppVersioning = true
v41.EnableSha512BlockHash = true
- v41.EnableUnnamedBoxAccessInNewApps = true
-
// txn.Access work
v41.MaxAppTxnAccounts = 8 // Accounts are no worse than others, they should be the same
v41.MaxAppAccess = 16 // Twice as many, though cross products are explicit
v41.BytesPerBoxReference = 2048 // Count is more important that bytes, loosen up
- v41.EnableInnerClawbackWithoutSenderHolding = true
v41.LogicSigMsig = false
v41.LogicSigLMsig = true
@@ -1462,6 +1463,10 @@ func initConsensusProtocols() {
vFuture.LogicSigVersion = 13 // When moving this to a release, put a new higher LogicSigVersion here
+ vFuture.AppSizeUpdates = true
+ vFuture.AllowZeroLocalAppRef = true
+ vFuture.EnforceAuthAddrSenderDiff = true
+
Consensus[protocol.ConsensusFuture] = vFuture
// vAlphaX versions are an separate series of consensus parameters and versions for alphanet
diff --git a/config/consensus_test.go b/config/consensus_test.go
index ed09422916..53af3a9aaa 100644
--- a/config/consensus_test.go
+++ b/config/consensus_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/defaultsGenerator/defaultsGenerator.go b/config/defaultsGenerator/defaultsGenerator.go
index 25bd60b165..a83334ab80 100644
--- a/config/defaultsGenerator/defaultsGenerator.go
+++ b/config/defaultsGenerator/defaultsGenerator.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/dnsbootstrap.go b/config/dnsbootstrap.go
index b01876cc3b..a9d8a8f02f 100644
--- a/config/dnsbootstrap.go
+++ b/config/dnsbootstrap.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/dnsbootstrap_test.go b/config/dnsbootstrap_test.go
index 1e12b64f0d..43caa73134 100644
--- a/config/dnsbootstrap_test.go
+++ b/config/dnsbootstrap_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/keyfile.go b/config/keyfile.go
index b9282ce0d6..f938202f2a 100644
--- a/config/keyfile.go
+++ b/config/keyfile.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/localTemplate.go b/config/localTemplate.go
index 523707ba23..5f6a4e63c5 100644
--- a/config/localTemplate.go
+++ b/config/localTemplate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -43,7 +43,7 @@ type Local struct {
// Version tracks the current version of the defaults so we can migrate old -> new
// This is specifically important whenever we decide to change the default value
// for an existing parameter. This field tag must be updated any time we add a new version.
- Version uint32 `version[0]:"0" version[1]:"1" version[2]:"2" version[3]:"3" version[4]:"4" version[5]:"5" version[6]:"6" version[7]:"7" version[8]:"8" version[9]:"9" version[10]:"10" version[11]:"11" version[12]:"12" version[13]:"13" version[14]:"14" version[15]:"15" version[16]:"16" version[17]:"17" version[18]:"18" version[19]:"19" version[20]:"20" version[21]:"21" version[22]:"22" version[23]:"23" version[24]:"24" version[25]:"25" version[26]:"26" version[27]:"27" version[28]:"28" version[29]:"29" version[30]:"30" version[31]:"31" version[32]:"32" version[33]:"33" version[34]:"34" version[35]:"35" version[36]:"36" version[37]:"37"`
+ Version uint32 `version[0]:"0" version[1]:"1" version[2]:"2" version[3]:"3" version[4]:"4" version[5]:"5" version[6]:"6" version[7]:"7" version[8]:"8" version[9]:"9" version[10]:"10" version[11]:"11" version[12]:"12" version[13]:"13" version[14]:"14" version[15]:"15" version[16]:"16" version[17]:"17" version[18]:"18" version[19]:"19" version[20]:"20" version[21]:"21" version[22]:"22" version[23]:"23" version[24]:"24" version[25]:"25" version[26]:"26" version[27]:"27" version[28]:"28" version[29]:"29" version[30]:"30" version[31]:"31" version[32]:"32" version[33]:"33" version[34]:"34" version[35]:"35" version[36]:"36" version[37]:"37" version[38]:"38"`
// Archival nodes retain a full copy of the block history. Non-Archival nodes will delete old blocks and only retain what's need to properly validate blockchain messages (the precise number of recent blocks depends on the consensus parameters. Currently the last 1321 blocks are required). This means that non-Archival nodes require significantly less storage than Archival nodes. If setting this to true for the first time, the existing ledger may need to be deleted to get the historical values stored as the setting only affects current blocks forward. To do this, shutdown the node and delete all .sqlite files within the data/testnet-version directory, except the crash.sqlite file. Restart the node and wait for the node to sync.
Archival bool `version[0]:"false"`
@@ -247,10 +247,12 @@ type Local struct {
// TxBacklogAppTxPerSecondRate determines a target app per second rate for the app tx rate limiter
TxBacklogAppTxPerSecondRate int `version[32]:"100"`
- // TxBacklogRateLimitingCongestionRatio determines the backlog filling threshold percentage at which the app limiter kicks in
- // or the tx backlog rate limiter kicks off.
+ // TxBacklogRateLimitingCongestionRatio determines the backlog filling threshold percentage at which the tx backlog rate limiter kicks off
TxBacklogRateLimitingCongestionPct int `version[32]:"50"`
+ // TxBacklogAppRateLimitingCongestionPct determines the backlog filling threshold percentage at which the app limiter kicks in
+ TxBacklogAppRateLimitingCongestionPct int `version[38]:"10"`
+
// EnableTxBacklogAppRateLimiting controls if an app rate limiter should be attached to the tx backlog enqueue process
EnableTxBacklogAppRateLimiting bool `version[32]:"true"`
@@ -624,9 +626,17 @@ type Local struct {
// P2PHybridNetAddress sets the listen address used for P2P networking, if hybrid mode is set.
P2PHybridNetAddress string `version[34]:""`
- // EnableDHT will turn on the hash table for use with capabilities advertisement
+ // EnableDHTProviders enables the DHT for peer discovery and capabilities advertisement.
EnableDHTProviders bool `version[34]:"false"`
+ // DHTMode controls the DHT operation mode.
+ // Valid values:
+ // - "" (default): nodes with a listen address (NetAddress or P2PHybridNetAddress) use "server" mode
+ // to be discoverable; other nodes use "client" mode
+ // - "server": always operate as DHT server, respond to queries and advertise peer ID
+ // - "client": operate as DHT client only, query the DHT without advertising or being discoverable
+ DHTMode string `version[38]:""`
+
// P2PPersistPeerID will write the private key used for the node's PeerID to the P2PPrivateKeyLocation.
// This is only used when P2PEnable is true. If P2PPrivateKey is not specified, it uses the default location.
P2PPersistPeerID bool `version[29]:"false"`
@@ -765,20 +775,20 @@ func (cfg Local) TxFilterCanonicalEnabled() bool {
return cfg.TxIncomingFilteringFlags&txFilterCanonical != 0
}
-// IsGossipServer returns true if this node supposed to start websocket or p2p server
-func (cfg Local) IsGossipServer() bool {
- return cfg.IsWsGossipServer() || cfg.IsP2PGossipServer()
+// IsListenServer returns true if this node supposed to start websocket or p2p server
+func (cfg Local) IsListenServer() bool {
+ return cfg.IsWsListenServer() || cfg.IsP2PListenServer()
}
-// IsWsGossipServer returns true if a node is configured to run a listening ws net
-func (cfg Local) IsWsGossipServer() bool {
+// IsWsListenServer returns true if a node is configured to run a listening ws net
+func (cfg Local) IsWsListenServer() bool {
// 1. NetAddress is set and EnableP2P is not set
// 2. NetAddress is set and EnableP2PHybridMode is set then EnableP2P is overridden by EnableP2PHybridMode
return cfg.NetAddress != "" && (!cfg.EnableP2P || cfg.EnableP2PHybridMode)
}
-// IsP2PGossipServer returns true if a node is configured to run a listening p2p net
-func (cfg Local) IsP2PGossipServer() bool {
+// IsP2PListenServer returns true if a node is configured to run a listening p2p net
+func (cfg Local) IsP2PListenServer() bool {
return (cfg.EnableP2P && !cfg.EnableP2PHybridMode && cfg.NetAddress != "") || (cfg.EnableP2PHybridMode && cfg.P2PHybridNetAddress != "")
}
@@ -1014,7 +1024,7 @@ func (cfg *Local) AdjustConnectionLimits(requiredFDs, maxFDs uint64) bool {
// split the rest of the delta between ws and p2p evenly
splitRatio = 2
}
- if cfg.IsWsGossipServer() || cfg.IsP2PGossipServer() {
+ if cfg.IsWsListenServer() || cfg.IsP2PListenServer() {
if cfg.IncomingConnectionsLimit > int(restDelta) {
cfg.IncomingConnectionsLimit -= int(restDelta) / splitRatio
} else {
diff --git a/config/local_defaults.go b/config/local_defaults.go
index ad090e0289..de60b1e522 100644
--- a/config/local_defaults.go
+++ b/config/local_defaults.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -20,7 +20,7 @@
package config
var defaultLocal = Local{
- Version: 37,
+ Version: 38,
AccountUpdatesStatsInterval: 5000000000,
AccountsRebuildSynchronousMode: 1,
AgreementIncomingBundlesQueueLength: 15,
@@ -50,6 +50,7 @@ var defaultLocal = Local{
ConnectionsRateLimitingCount: 60,
ConnectionsRateLimitingWindowSeconds: 1,
CrashDBDir: "",
+ DHTMode: "",
DNSBootstrapID: ".algorand.network?backup=.algorand.net&dedup=.algorand-.(network|net)",
DNSSecurityFlags: 9,
DeadlockDetection: 0,
@@ -151,6 +152,7 @@ var defaultLocal = Local{
TrackerDBDir: "",
TransactionSyncDataExchangeRate: 0,
TransactionSyncSignificantMessageThreshold: 0,
+ TxBacklogAppRateLimitingCongestionPct: 10,
TxBacklogAppRateLimitingCountERLDrops: false,
TxBacklogAppTxPerSecondRate: 100,
TxBacklogAppTxRateLimiterMaxSize: 1048576,
diff --git a/config/migrate.go b/config/migrate.go
index 238725af47..229cbde67a 100644
--- a/config/migrate.go
+++ b/config/migrate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/config/version.go b/config/version.go
index e80842afbc..45955101fa 100644
--- a/config/version.go
+++ b/config/version.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -33,7 +33,7 @@ const VersionMajor = 4
// 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 = 4
+const VersionMinor = 5
// Version is the type holding our full version information.
type Version struct {
diff --git a/config/version_test.go b/config/version_test.go
index d462008020..bf289d65de 100644
--- a/config/version_test.go
+++ b/config/version_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/batchverifier.go b/crypto/batchverifier.go
index cd0168ae1f..a4d5d6a32f 100644
--- a/crypto/batchverifier.go
+++ b/crypto/batchverifier.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/batchverifier_bench_test.go b/crypto/batchverifier_bench_test.go
index c676a5265e..0fc983a831 100644
--- a/crypto/batchverifier_bench_test.go
+++ b/crypto/batchverifier_bench_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/batchverifier_test.go b/crypto/batchverifier_test.go
index ac91c19023..f286196dce 100644
--- a/crypto/batchverifier_test.go
+++ b/crypto/batchverifier_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go
index 82273c6fbe..f5973608f0 100644
--- a/crypto/crypto_test.go
+++ b/crypto/crypto_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/cryptoerror.go b/crypto/cryptoerror.go
index 6d1b468c5e..b2d953d84c 100644
--- a/crypto/cryptoerror.go
+++ b/crypto/cryptoerror.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/curve25519.go b/crypto/curve25519.go
index 1f6dfcbd16..4d44950e72 100644
--- a/crypto/curve25519.go
+++ b/crypto/curve25519.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/curve25519_test.go b/crypto/curve25519_test.go
index 9bbbb11158..81362748f9 100644
--- a/crypto/curve25519_test.go
+++ b/crypto/curve25519_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/digest.go b/crypto/digest.go
index 3e20fb236a..39389a2572 100644
--- a/crypto/digest.go
+++ b/crypto/digest.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/encoding_test.go b/crypto/encoding_test.go
index e400a19f7a..1a72fcad2d 100644
--- a/crypto/encoding_test.go
+++ b/crypto/encoding_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/falconWrapper.go b/crypto/falconWrapper.go
index 63158fcc85..697726ba1d 100644
--- a/crypto/falconWrapper.go
+++ b/crypto/falconWrapper.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/falconWrapper_test.go b/crypto/falconWrapper_test.go
index 4d8720e9f9..a105ed8845 100644
--- a/crypto/falconWrapper_test.go
+++ b/crypto/falconWrapper_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/gobatchverifier.go b/crypto/gobatchverifier.go
index 46fcd0cae5..7e7fe64918 100644
--- a/crypto/gobatchverifier.go
+++ b/crypto/gobatchverifier.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/gobatchverifier_test.go b/crypto/gobatchverifier_test.go
index 884e65eb44..a096ec5fe7 100644
--- a/crypto/gobatchverifier_test.go
+++ b/crypto/gobatchverifier_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/hashes.go b/crypto/hashes.go
index 557ff23d2c..039c38d239 100644
--- a/crypto/hashes.go
+++ b/crypto/hashes.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -141,7 +141,7 @@ func hashBytes(hash hash.Hash, m []byte) []byte {
return outhash
}
-// InvalidHash is used to identify errors on the factory.
+// invalidHash is used to identify errors on the factory.
// this function will return nil slice
type invalidHash struct {
}
diff --git a/crypto/hashes_test.go b/crypto/hashes_test.go
index 8999834423..0f748322e9 100644
--- a/crypto/hashes_test.go
+++ b/crypto/hashes_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/memcpy_chk_windows.c b/crypto/memcpy_chk_windows.c
index c48d685f0d..fa1877a992 100644
--- a/crypto/memcpy_chk_windows.c
+++ b/crypto/memcpy_chk_windows.c
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklearray/array.go b/crypto/merklearray/array.go
index cfab888cde..1bcb2e5301 100644
--- a/crypto/merklearray/array.go
+++ b/crypto/merklearray/array.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklearray/layer.go b/crypto/merklearray/layer.go
index 728653ff7e..a22fc62ff8 100644
--- a/crypto/merklearray/layer.go
+++ b/crypto/merklearray/layer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklearray/merkle.go b/crypto/merklearray/merkle.go
index f77b6dcf7b..cb090f1110 100644
--- a/crypto/merklearray/merkle.go
+++ b/crypto/merklearray/merkle.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklearray/merkle_test.go b/crypto/merklearray/merkle_test.go
index b84beef624..b2b3836a25 100644
--- a/crypto/merklearray/merkle_test.go
+++ b/crypto/merklearray/merkle_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklearray/msgp_gen.go b/crypto/merklearray/msgp_gen.go
index db308439e0..c82fa0aa85 100644
--- a/crypto/merklearray/msgp_gen.go
+++ b/crypto/merklearray/msgp_gen.go
@@ -1,7 +1,7 @@
-package merklearray
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package merklearray
+
import (
"github.com/algorand/msgp/msgp"
@@ -130,7 +130,7 @@ func (z Layer) MsgIsZero() bool {
return len(z) == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// LayerMaxSize returns a maximum valid message size for this message type
func LayerMaxSize() (s int) {
// Calculating size of slice: z
s += msgp.ArrayHeaderSize + ((MaxNumLeavesOnEncodedTree) * (crypto.GenericDigestMaxSize()))
@@ -350,7 +350,7 @@ func (z *Proof) MsgIsZero() bool {
return (len((*z).Path) == 0) && ((*z).HashFactory.MsgIsZero()) && ((*z).TreeDepth == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// ProofMaxSize returns a maximum valid message size for this message type
func ProofMaxSize() (s int) {
s = 1 + 4
// Calculating size of slice: z.Path
@@ -860,7 +860,7 @@ func (z *Tree) MsgIsZero() bool {
return (len((*z).Levels) == 0) && ((*z).NumOfElements == 0) && ((*z).Hash.MsgIsZero()) && ((*z).IsVectorCommitment == false)
}
-// MaxSize returns a maximum valid message size for this message type
+// TreeMaxSize returns a maximum valid message size for this message type
func TreeMaxSize() (s int) {
s = 1 + 5
// Calculating size of slice: z.Levels
diff --git a/crypto/merklearray/msgp_gen_test.go b/crypto/merklearray/msgp_gen_test.go
index 2b50c643b4..4edf2cb78e 100644
--- a/crypto/merklearray/msgp_gen_test.go
+++ b/crypto/merklearray/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package merklearray
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package merklearray
+
import (
"testing"
diff --git a/crypto/merklearray/partial.go b/crypto/merklearray/partial.go
index e16dc7f12c..03ba23101f 100644
--- a/crypto/merklearray/partial.go
+++ b/crypto/merklearray/partial.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklearray/proof.go b/crypto/merklearray/proof.go
index bd88562d51..5ea9fabf1d 100644
--- a/crypto/merklearray/proof.go
+++ b/crypto/merklearray/proof.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklearray/proof_test.go b/crypto/merklearray/proof_test.go
index dd93d1a8f4..47c9281709 100644
--- a/crypto/merklearray/proof_test.go
+++ b/crypto/merklearray/proof_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklearray/vectorCommitmentArray.go b/crypto/merklearray/vectorCommitmentArray.go
index 82bdc8c67e..af79871f88 100644
--- a/crypto/merklearray/vectorCommitmentArray.go
+++ b/crypto/merklearray/vectorCommitmentArray.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklearray/vectorCommitmentArray_test.go b/crypto/merklearray/vectorCommitmentArray_test.go
index 136609df78..fdd64fd9f7 100644
--- a/crypto/merklearray/vectorCommitmentArray_test.go
+++ b/crypto/merklearray/vectorCommitmentArray_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklearray/worker.go b/crypto/merklearray/worker.go
index e3c2607353..c10201dd28 100644
--- a/crypto/merklearray/worker.go
+++ b/crypto/merklearray/worker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklesignature/committablePublicKeys.go b/crypto/merklesignature/committablePublicKeys.go
index 8cd8857057..57f07280e2 100644
--- a/crypto/merklesignature/committablePublicKeys.go
+++ b/crypto/merklesignature/committablePublicKeys.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklesignature/committablePublicKeys_test.go b/crypto/merklesignature/committablePublicKeys_test.go
index 979528f236..acff420379 100644
--- a/crypto/merklesignature/committablePublicKeys_test.go
+++ b/crypto/merklesignature/committablePublicKeys_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklesignature/const.go b/crypto/merklesignature/const.go
index a7e529771f..26330650b1 100644
--- a/crypto/merklesignature/const.go
+++ b/crypto/merklesignature/const.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklesignature/kats_test.go b/crypto/merklesignature/kats_test.go
index c4c1962fae..dfddbd48bd 100644
--- a/crypto/merklesignature/kats_test.go
+++ b/crypto/merklesignature/kats_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklesignature/keysBuilder.go b/crypto/merklesignature/keysBuilder.go
index aaf8ce8a47..b9d4b15633 100644
--- a/crypto/merklesignature/keysBuilder.go
+++ b/crypto/merklesignature/keysBuilder.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklesignature/keysBuilder_test.go b/crypto/merklesignature/keysBuilder_test.go
index c54c230bd9..11e9881917 100644
--- a/crypto/merklesignature/keysBuilder_test.go
+++ b/crypto/merklesignature/keysBuilder_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklesignature/merkleSignatureScheme.go b/crypto/merklesignature/merkleSignatureScheme.go
index 51b0a9e2c7..39eadc0d2d 100644
--- a/crypto/merklesignature/merkleSignatureScheme.go
+++ b/crypto/merklesignature/merkleSignatureScheme.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklesignature/merkleSignatureScheme_test.go b/crypto/merklesignature/merkleSignatureScheme_test.go
index 83515099df..a4b7ed2beb 100644
--- a/crypto/merklesignature/merkleSignatureScheme_test.go
+++ b/crypto/merklesignature/merkleSignatureScheme_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklesignature/msgp_gen.go b/crypto/merklesignature/msgp_gen.go
index 8cac8a7395..6ec4827584 100644
--- a/crypto/merklesignature/msgp_gen.go
+++ b/crypto/merklesignature/msgp_gen.go
@@ -1,7 +1,7 @@
-package merklesignature
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package merklesignature
+
import (
"github.com/algorand/msgp/msgp"
@@ -118,7 +118,7 @@ func (z *Commitment) MsgIsZero() bool {
return (*z) == (Commitment{})
}
-// MaxSize returns a maximum valid message size for this message type
+// CommitmentMaxSize returns a maximum valid message size for this message type
func CommitmentMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((MerkleSignatureSchemeRootSize) * (msgp.ByteSize))
@@ -293,7 +293,7 @@ func (z *KeyRoundPair) MsgIsZero() bool {
return ((*z).Round == 0) && ((*z).Key == nil)
}
-// MaxSize returns a maximum valid message size for this message type
+// KeyRoundPairMaxSize returns a maximum valid message size for this message type
func KeyRoundPairMaxSize() (s int) {
s = 1 + 4 + msgp.Uint64Size + 4
s += crypto.FalconSignerMaxSize()
@@ -460,7 +460,7 @@ func (z *Secrets) MsgIsZero() bool {
return ((*z).SignerContext.FirstValid == 0) && ((*z).SignerContext.KeyLifetime == 0) && ((*z).SignerContext.Tree.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// SecretsMaxSize returns a maximum valid message size for this message type
func SecretsMaxSize() (s int) {
s = 1 + 3 + msgp.Uint64Size + 3 + msgp.Uint64Size + 5 + merklearray.TreeMaxSize()
return
@@ -649,7 +649,7 @@ func (z *Signature) MsgIsZero() bool {
return ((*z).Signature.MsgIsZero()) && ((*z).VectorCommitmentIndex == 0) && ((*z).Proof.MsgIsZero()) && ((*z).VerifyingKey.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// SignatureMaxSize returns a maximum valid message size for this message type
func SignatureMaxSize() (s int) {
s = 1 + 4 + crypto.FalconSignatureMaxSize() + 4 + msgp.Uint64Size + 4 + merklearray.SingleLeafProofMaxSize() + 5 + crypto.FalconVerifierMaxSize()
return
@@ -815,7 +815,7 @@ func (z *SignerContext) MsgIsZero() bool {
return ((*z).FirstValid == 0) && ((*z).KeyLifetime == 0) && ((*z).Tree.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// SignerContextMaxSize returns a maximum valid message size for this message type
func SignerContextMaxSize() (s int) {
s = 1 + 3 + msgp.Uint64Size + 3 + msgp.Uint64Size + 5 + merklearray.TreeMaxSize()
return
@@ -958,7 +958,7 @@ func (z *Verifier) MsgIsZero() bool {
return ((*z).Commitment == (Commitment{})) && ((*z).KeyLifetime == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// VerifierMaxSize returns a maximum valid message size for this message type
func VerifierMaxSize() (s int) {
s = 1 + 4
// Calculating size of array: z.Commitment
diff --git a/crypto/merklesignature/msgp_gen_test.go b/crypto/merklesignature/msgp_gen_test.go
index 7a53df31a3..a421603921 100644
--- a/crypto/merklesignature/msgp_gen_test.go
+++ b/crypto/merklesignature/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package merklesignature
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package merklesignature
+
import (
"testing"
diff --git a/crypto/merklesignature/persistentMerkleSignatureScheme.go b/crypto/merklesignature/persistentMerkleSignatureScheme.go
index e3cd8c4b9d..51cdfb87ac 100644
--- a/crypto/merklesignature/persistentMerkleSignatureScheme.go
+++ b/crypto/merklesignature/persistentMerkleSignatureScheme.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklesignature/persistentMerkleSignatureScheme_test.go b/crypto/merklesignature/persistentMerkleSignatureScheme_test.go
index 95179f3f04..ba516a8c28 100644
--- a/crypto/merklesignature/persistentMerkleSignatureScheme_test.go
+++ b/crypto/merklesignature/persistentMerkleSignatureScheme_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklesignature/posdivs.go b/crypto/merklesignature/posdivs.go
index b1d8374b10..887f432b36 100644
--- a/crypto/merklesignature/posdivs.go
+++ b/crypto/merklesignature/posdivs.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merklesignature/posdivs_test.go b/crypto/merklesignature/posdivs_test.go
index cb3fd5275a..ccc8aff41f 100644
--- a/crypto/merklesignature/posdivs_test.go
+++ b/crypto/merklesignature/posdivs_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merkletrie/bitset.go b/crypto/merkletrie/bitset.go
index 7862576b78..a29e29b502 100644
--- a/crypto/merkletrie/bitset.go
+++ b/crypto/merkletrie/bitset.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merkletrie/bitset_test.go b/crypto/merkletrie/bitset_test.go
index 2bf3bc392a..f65d7a818b 100644
--- a/crypto/merkletrie/bitset_test.go
+++ b/crypto/merkletrie/bitset_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merkletrie/cache.go b/crypto/merkletrie/cache.go
index 5d8fd78779..8d1de9832f 100644
--- a/crypto/merkletrie/cache.go
+++ b/crypto/merkletrie/cache.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -689,7 +689,7 @@ func decodePage(bytes []byte) (nodesMap map[storedNodeIdentifier]*node, err erro
return nodesMap, nil
}
-// decodePage encodes a page contents into a byte array
+// encodePage encodes a page contents into a byte array
func (mtc *merkleTrieCache) encodePage(nodeIDs map[storedNodeIdentifier]*node, serializedBuffer []byte) []byte {
version := binary.PutUvarint(serializedBuffer[:], nodePageVersion)
length := binary.PutVarint(serializedBuffer[version:], int64(len(nodeIDs)))
diff --git a/crypto/merkletrie/cache_test.go b/crypto/merkletrie/cache_test.go
index 9ff3649efb..cc93893089 100644
--- a/crypto/merkletrie/cache_test.go
+++ b/crypto/merkletrie/cache_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -209,7 +209,7 @@ func TestCacheEvictionFuzzer(t *testing.T) {
}
}
-// TestCacheEvictionFuzzer generates bursts of random Add/Delete operations on the trie, and
+// TestCacheEvictionFuzzer2 generates bursts of random Add/Delete operations on the trie, and
// testing the correctness of the cache internal buffers priodically.
func TestCacheEvictionFuzzer2(t *testing.T) {
partitiontest.PartitionTest(t)
@@ -396,7 +396,7 @@ func TestCacheDeleteNodeMidTransaction(t *testing.T) {
}
}
-// TestCachePageLoading ensures that during page loading, the number of cachedNodeCount is not
+// TestCachePageReloading ensures that during page loading, the number of cachedNodeCount is not
// increased if the page was already loaded previously into memory.
func TestCachePageReloading(t *testing.T) {
partitiontest.PartitionTest(t)
diff --git a/crypto/merkletrie/committer.go b/crypto/merkletrie/committer.go
index eb935a901e..851359ca32 100644
--- a/crypto/merkletrie/committer.go
+++ b/crypto/merkletrie/committer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merkletrie/committer_test.go b/crypto/merkletrie/committer_test.go
index 004c0b60f7..ad401377ed 100644
--- a/crypto/merkletrie/committer_test.go
+++ b/crypto/merkletrie/committer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merkletrie/node.go b/crypto/merkletrie/node.go
index 6611c649f2..f5925bc1f7 100644
--- a/crypto/merkletrie/node.go
+++ b/crypto/merkletrie/node.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merkletrie/node_test.go b/crypto/merkletrie/node_test.go
index 1ffa67bb8b..efd57de357 100644
--- a/crypto/merkletrie/node_test.go
+++ b/crypto/merkletrie/node_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merkletrie/trie.go b/crypto/merkletrie/trie.go
index 4686647e75..1c9c226eef 100644
--- a/crypto/merkletrie/trie.go
+++ b/crypto/merkletrie/trie.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/merkletrie/trie_test.go b/crypto/merkletrie/trie_test.go
index 96eae19f66..29c88c8001 100644
--- a/crypto/merkletrie/trie_test.go
+++ b/crypto/merkletrie/trie_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/msgp_gen.go b/crypto/msgp_gen.go
index 0b7142457f..6e64233c0d 100644
--- a/crypto/msgp_gen.go
+++ b/crypto/msgp_gen.go
@@ -1,7 +1,7 @@
-package crypto
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package crypto
+
import (
_ "runtime/cgo"
_ "unsafe"
@@ -419,7 +419,7 @@ func (z *Digest) MsgIsZero() bool {
return (*z) == (Digest{})
}
-// MaxSize returns a maximum valid message size for this message type
+// DigestMaxSize returns a maximum valid message size for this message type
func DigestMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((DigestSize) * (msgp.ByteSize))
@@ -473,7 +473,7 @@ func (z *FalconPrivateKey) MsgIsZero() bool {
return (*z) == (FalconPrivateKey{})
}
-// MaxSize returns a maximum valid message size for this message type
+// FalconPrivateKeyMaxSize returns a maximum valid message size for this message type
func FalconPrivateKeyMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((cfalcon.PrivateKeySize) * (msgp.ByteSize))
@@ -527,7 +527,7 @@ func (z *FalconPublicKey) MsgIsZero() bool {
return (*z) == (FalconPublicKey{})
}
-// MaxSize returns a maximum valid message size for this message type
+// FalconPublicKeyMaxSize returns a maximum valid message size for this message type
func FalconPublicKeyMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((cfalcon.PublicKeySize) * (msgp.ByteSize))
@@ -581,7 +581,7 @@ func (z *FalconSeed) MsgIsZero() bool {
return (*z) == (FalconSeed{})
}
-// MaxSize returns a maximum valid message size for this message type
+// FalconSeedMaxSize returns a maximum valid message size for this message type
func FalconSeedMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((FalconSeedSize) * (msgp.ByteSize))
@@ -652,7 +652,7 @@ func (z FalconSignature) MsgIsZero() bool {
return len(z) == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// FalconSignatureMaxSize returns a maximum valid message size for this message type
func FalconSignatureMaxSize() (s int) {
s = msgp.BytesPrefixSize + FalconMaxSignatureSize
return
@@ -795,7 +795,7 @@ func (z *FalconSigner) MsgIsZero() bool {
return ((*z).PublicKey == (FalconPublicKey{})) && ((*z).PrivateKey == (FalconPrivateKey{}))
}
-// MaxSize returns a maximum valid message size for this message type
+// FalconSignerMaxSize returns a maximum valid message size for this message type
func FalconSignerMaxSize() (s int) {
s = 1 + 3
// Calculating size of array: z.PublicKey
@@ -920,7 +920,7 @@ func (z *FalconVerifier) MsgIsZero() bool {
return ((*z).PublicKey == (FalconPublicKey{}))
}
-// MaxSize returns a maximum valid message size for this message type
+// FalconVerifierMaxSize returns a maximum valid message size for this message type
func FalconVerifierMaxSize() (s int) {
s = 1 + 2
// Calculating size of array: z.PublicKey
@@ -992,7 +992,7 @@ func (z GenericDigest) MsgIsZero() bool {
return len(z) == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// GenericDigestMaxSize returns a maximum valid message size for this message type
func GenericDigestMaxSize() (s int) {
s = msgp.BytesPrefixSize + MaxHashDigestSize
return
@@ -1123,7 +1123,7 @@ func (z *HashFactory) MsgIsZero() bool {
return ((*z).HashType == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// HashFactoryMaxSize returns a maximum valid message size for this message type
func HashFactoryMaxSize() (s int) {
s = 1 + 2 + msgp.Uint16Size
return
@@ -1183,7 +1183,7 @@ func (z HashType) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// HashTypeMaxSize returns a maximum valid message size for this message type
func HashTypeMaxSize() (s int) {
s = msgp.Uint16Size
return
@@ -1395,7 +1395,7 @@ func (z *HeartbeatProof) MsgIsZero() bool {
return ((*z).Sig == (ed25519Signature{})) && ((*z).PK == (ed25519PublicKey{})) && ((*z).PK2 == (ed25519PublicKey{})) && ((*z).PK1Sig == (ed25519Signature{})) && ((*z).PK2Sig == (ed25519Signature{}))
}
-// MaxSize returns a maximum valid message size for this message type
+// HeartbeatProofMaxSize returns a maximum valid message size for this message type
func HeartbeatProofMaxSize() (s int) {
s = 1 + 2
// Calculating size of array: z.Sig
@@ -1462,7 +1462,7 @@ func (z *MasterDerivationKey) MsgIsZero() bool {
return (*z) == (MasterDerivationKey{})
}
-// MaxSize returns a maximum valid message size for this message type
+// MasterDerivationKeyMaxSize returns a maximum valid message size for this message type
func MasterDerivationKeyMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((masterDerivationKeyLenBytes) * (msgp.ByteSize))
@@ -1681,7 +1681,7 @@ func (z *MultisigSig) MsgIsZero() bool {
return ((*z).Version == 0) && ((*z).Threshold == 0) && (len((*z).Subsigs) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// MultisigSigMaxSize returns a maximum valid message size for this message type
func MultisigSigMaxSize() (s int) {
s = 1 + 2 + msgp.Uint8Size + 4 + msgp.Uint8Size + 7
// Calculating size of slice: z.Subsigs
@@ -1826,7 +1826,7 @@ func (z *MultisigSubsig) MsgIsZero() bool {
return ((*z).Key == (PublicKey{})) && ((*z).Sig == (Signature{}))
}
-// MaxSize returns a maximum valid message size for this message type
+// MultisigSubsigMaxSize returns a maximum valid message size for this message type
func MultisigSubsigMaxSize() (s int) {
s = 1 + 3
// Calculating size of array: z.Key
@@ -2024,7 +2024,7 @@ func (z *OneTimeSignature) MsgIsZero() bool {
return ((*z).Sig == (ed25519Signature{})) && ((*z).PK == (ed25519PublicKey{})) && ((*z).PKSigOld == (ed25519Signature{})) && ((*z).PK2 == (ed25519PublicKey{})) && ((*z).PK1Sig == (ed25519Signature{})) && ((*z).PK2Sig == (ed25519Signature{}))
}
-// MaxSize returns a maximum valid message size for this message type
+// OneTimeSignatureMaxSize returns a maximum valid message size for this message type
func OneTimeSignatureMaxSize() (s int) {
s = 1 + 2
// Calculating size of array: z.Sig
@@ -2385,7 +2385,7 @@ func (z *OneTimeSignatureSecrets) MsgIsZero() bool {
return ((*z).OneTimeSignatureSecretsPersistent.OneTimeSignatureVerifier == (OneTimeSignatureVerifier{})) && ((*z).OneTimeSignatureSecretsPersistent.FirstBatch == 0) && (len((*z).OneTimeSignatureSecretsPersistent.Batches) == 0) && ((*z).OneTimeSignatureSecretsPersistent.FirstOffset == 0) && (len((*z).OneTimeSignatureSecretsPersistent.Offsets) == 0) && ((*z).OneTimeSignatureSecretsPersistent.OffsetsPK2 == (ed25519PublicKey{})) && ((*z).OneTimeSignatureSecretsPersistent.OffsetsPK2Sig == (ed25519Signature{}))
}
-// MaxSize returns a maximum valid message size for this message type
+// OneTimeSignatureSecretsMaxSize returns a maximum valid message size for this message type
func OneTimeSignatureSecretsMaxSize() (s int) {
s = 1 + 25
// Calculating size of array: z.OneTimeSignatureSecretsPersistent.OneTimeSignatureVerifier
@@ -2733,7 +2733,7 @@ func (z *OneTimeSignatureSecretsPersistent) MsgIsZero() bool {
return ((*z).OneTimeSignatureVerifier == (OneTimeSignatureVerifier{})) && ((*z).FirstBatch == 0) && (len((*z).Batches) == 0) && ((*z).FirstOffset == 0) && (len((*z).Offsets) == 0) && ((*z).OffsetsPK2 == (ed25519PublicKey{})) && ((*z).OffsetsPK2Sig == (ed25519Signature{}))
}
-// MaxSize returns a maximum valid message size for this message type
+// OneTimeSignatureSecretsPersistentMaxSize returns a maximum valid message size for this message type
func OneTimeSignatureSecretsPersistentMaxSize() (s int) {
s = 1 + 25
// Calculating size of array: z.OneTimeSignatureVerifier
@@ -2862,7 +2862,7 @@ func (z *OneTimeSignatureSubkeyBatchID) MsgIsZero() bool {
return ((*z).SubKeyPK == (ed25519PublicKey{})) && ((*z).Batch == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// OneTimeSignatureSubkeyBatchIDMaxSize returns a maximum valid message size for this message type
func OneTimeSignatureSubkeyBatchIDMaxSize() (s int) {
s = 1 + 3
// Calculating size of array: z.SubKeyPK
@@ -3007,7 +3007,7 @@ func (z *OneTimeSignatureSubkeyOffsetID) MsgIsZero() bool {
return ((*z).SubKeyPK == (ed25519PublicKey{})) && ((*z).Batch == 0) && ((*z).Offset == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// OneTimeSignatureSubkeyOffsetIDMaxSize returns a maximum valid message size for this message type
func OneTimeSignatureSubkeyOffsetIDMaxSize() (s int) {
s = 1 + 3
// Calculating size of array: z.SubKeyPK
@@ -3063,7 +3063,7 @@ func (z *OneTimeSignatureVerifier) MsgIsZero() bool {
return (*z) == (OneTimeSignatureVerifier{})
}
-// MaxSize returns a maximum valid message size for this message type
+// OneTimeSignatureVerifierMaxSize returns a maximum valid message size for this message type
func OneTimeSignatureVerifierMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((32) * (msgp.ByteSize))
@@ -3117,7 +3117,7 @@ func (z *PrivateKey) MsgIsZero() bool {
return (*z) == (PrivateKey{})
}
-// MaxSize returns a maximum valid message size for this message type
+// PrivateKeyMaxSize returns a maximum valid message size for this message type
func PrivateKeyMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((64) * (msgp.ByteSize))
@@ -3171,7 +3171,7 @@ func (z *PublicKey) MsgIsZero() bool {
return (*z) == (PublicKey{})
}
-// MaxSize returns a maximum valid message size for this message type
+// PublicKeyMaxSize returns a maximum valid message size for this message type
func PublicKeyMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((32) * (msgp.ByteSize))
@@ -3225,7 +3225,7 @@ func (z *Seed) MsgIsZero() bool {
return (*z) == (Seed{})
}
-// MaxSize returns a maximum valid message size for this message type
+// SeedMaxSize returns a maximum valid message size for this message type
func SeedMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((32) * (msgp.ByteSize))
@@ -3279,7 +3279,7 @@ func (z *Sha512Digest) MsgIsZero() bool {
return (*z) == (Sha512Digest{})
}
-// MaxSize returns a maximum valid message size for this message type
+// Sha512DigestMaxSize returns a maximum valid message size for this message type
func Sha512DigestMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((Sha512Size) * (msgp.ByteSize))
@@ -3333,7 +3333,7 @@ func (z *Signature) MsgIsZero() bool {
return (*z) == (Signature{})
}
-// MaxSize returns a maximum valid message size for this message type
+// SignatureMaxSize returns a maximum valid message size for this message type
func SignatureMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((64) * (msgp.ByteSize))
@@ -3459,7 +3459,7 @@ func (z *SignatureSecrets) MsgIsZero() bool {
return ((*z).SignatureVerifier == (PublicKey{})) && ((*z).SK == (ed25519PrivateKey{}))
}
-// MaxSize returns a maximum valid message size for this message type
+// SignatureSecretsMaxSize returns a maximum valid message size for this message type
func SignatureSecretsMaxSize() (s int) {
s = 1 + 18
// Calculating size of array: z.SignatureVerifier
@@ -3589,7 +3589,7 @@ func (z *VRFSecrets) MsgIsZero() bool {
return ((*z).PK == (VrfPubkey{})) && ((*z).SK == (VrfPrivkey{}))
}
-// MaxSize returns a maximum valid message size for this message type
+// VRFSecretsMaxSize returns a maximum valid message size for this message type
func VRFSecretsMaxSize() (s int) {
s = 1 + 3
// Calculating size of array: z.PK
@@ -3647,7 +3647,7 @@ func (z *VrfOutput) MsgIsZero() bool {
return (*z) == (VrfOutput{})
}
-// MaxSize returns a maximum valid message size for this message type
+// VrfOutputMaxSize returns a maximum valid message size for this message type
func VrfOutputMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((64) * (msgp.ByteSize))
@@ -3701,7 +3701,7 @@ func (z *VrfPrivkey) MsgIsZero() bool {
return (*z) == (VrfPrivkey{})
}
-// MaxSize returns a maximum valid message size for this message type
+// VrfPrivkeyMaxSize returns a maximum valid message size for this message type
func VrfPrivkeyMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((64) * (msgp.ByteSize))
@@ -3755,7 +3755,7 @@ func (z *VrfProof) MsgIsZero() bool {
return (*z) == (VrfProof{})
}
-// MaxSize returns a maximum valid message size for this message type
+// VrfProofMaxSize returns a maximum valid message size for this message type
func VrfProofMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((80) * (msgp.ByteSize))
@@ -3809,7 +3809,7 @@ func (z *VrfPubkey) MsgIsZero() bool {
return (*z) == (VrfPubkey{})
}
-// MaxSize returns a maximum valid message size for this message type
+// VrfPubkeyMaxSize returns a maximum valid message size for this message type
func VrfPubkeyMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((32) * (msgp.ByteSize))
@@ -3863,7 +3863,7 @@ func (z *ed25519PrivateKey) MsgIsZero() bool {
return (*z) == (ed25519PrivateKey{})
}
-// MaxSize returns a maximum valid message size for this message type
+// Ed25519PrivateKeyMaxSize returns a maximum valid message size for this message type
func Ed25519PrivateKeyMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((64) * (msgp.ByteSize))
@@ -3917,7 +3917,7 @@ func (z *ed25519PublicKey) MsgIsZero() bool {
return (*z) == (ed25519PublicKey{})
}
-// MaxSize returns a maximum valid message size for this message type
+// Ed25519PublicKeyMaxSize returns a maximum valid message size for this message type
func Ed25519PublicKeyMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((32) * (msgp.ByteSize))
@@ -3971,7 +3971,7 @@ func (z *ed25519Seed) MsgIsZero() bool {
return (*z) == (ed25519Seed{})
}
-// MaxSize returns a maximum valid message size for this message type
+// Ed25519SeedMaxSize returns a maximum valid message size for this message type
func Ed25519SeedMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((32) * (msgp.ByteSize))
@@ -4025,7 +4025,7 @@ func (z *ed25519Signature) MsgIsZero() bool {
return (*z) == (ed25519Signature{})
}
-// MaxSize returns a maximum valid message size for this message type
+// Ed25519SignatureMaxSize returns a maximum valid message size for this message type
func Ed25519SignatureMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((64) * (msgp.ByteSize))
@@ -4185,7 +4185,7 @@ func (z *ephemeralSubkey) MsgIsZero() bool {
return ((*z).PK == (ed25519PublicKey{})) && ((*z).SK == (ed25519PrivateKey{})) && ((*z).PKSigOld == (ed25519Signature{})) && ((*z).PKSigNew == (ed25519Signature{}))
}
-// MaxSize returns a maximum valid message size for this message type
+// EphemeralSubkeyMaxSize returns a maximum valid message size for this message type
func EphemeralSubkeyMaxSize() (s int) {
s = 1 + 3
// Calculating size of array: z.PK
diff --git a/crypto/msgp_gen_test.go b/crypto/msgp_gen_test.go
index f864b58c44..8516b8c71c 100644
--- a/crypto/msgp_gen_test.go
+++ b/crypto/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package crypto
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package crypto
+
import (
"testing"
diff --git a/crypto/multisig.go b/crypto/multisig.go
index ee02401ae1..93817c7414 100644
--- a/crypto/multisig.go
+++ b/crypto/multisig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/multisig_test.go b/crypto/multisig_test.go
index 2527fda740..3b7736d06d 100644
--- a/crypto/multisig_test.go
+++ b/crypto/multisig_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/onetimesig.go b/crypto/onetimesig.go
index 420ae442e8..6aee8ae2da 100644
--- a/crypto/onetimesig.go
+++ b/crypto/onetimesig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/onetimesig_test.go b/crypto/onetimesig_test.go
index d9eec123d3..8c00aaf1c5 100644
--- a/crypto/onetimesig_test.go
+++ b/crypto/onetimesig_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/passphrase/errors.go b/crypto/passphrase/errors.go
index 00d2d948fb..0a7ec6c066 100644
--- a/crypto/passphrase/errors.go
+++ b/crypto/passphrase/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/passphrase/passphrase.go b/crypto/passphrase/passphrase.go
index 3bcee21107..99f52d2be7 100644
--- a/crypto/passphrase/passphrase.go
+++ b/crypto/passphrase/passphrase.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -198,7 +198,7 @@ func indexOf(arr []string, s string) int {
return -1
}
-// Checksum returns a word that represents the 11 bit checksum of the data
+// checksum returns a word that represents the 11 bit checksum of the data
func checksum(data []byte) string {
// Compute the full hash of the data to checksum
fullHash := sha512.Sum512_256(data)
diff --git a/crypto/passphrase/passphrase_test.go b/crypto/passphrase/passphrase_test.go
index 66a9ae51fd..e8b5bf8220 100644
--- a/crypto/passphrase/passphrase_test.go
+++ b/crypto/passphrase/passphrase_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/passphrase/wordlist.go b/crypto/passphrase/wordlist.go
index 66ebac5111..14c3e1236a 100644
--- a/crypto/passphrase/wordlist.go
+++ b/crypto/passphrase/wordlist.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/rand.go b/crypto/rand.go
index 7d9e391072..91a6e567b5 100644
--- a/crypto/rand.go
+++ b/crypto/rand.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/rand_test.go b/crypto/rand_test.go
index b2e768b067..1da0380418 100644
--- a/crypto/rand_test.go
+++ b/crypto/rand_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/secp256k1/dummy.go b/crypto/secp256k1/dummy.go
index 479e07dc8e..6164afd5ba 100644
--- a/crypto/secp256k1/dummy.go
+++ b/crypto/secp256k1/dummy.go
@@ -1,5 +1,4 @@
//go:build dummy
-// +build dummy
// This file is part of a workaround for `go mod vendor` which won't vendor
// C files if there's no Go file in the same directory.
diff --git a/crypto/secp256k1/panic_cb.go b/crypto/secp256k1/panic_cb.go
index a30b04f51b..77119118a0 100644
--- a/crypto/secp256k1/panic_cb.go
+++ b/crypto/secp256k1/panic_cb.go
@@ -3,7 +3,6 @@
// the LICENSE file.
//go:build !gofuzz && cgo
-// +build !gofuzz,cgo
package secp256k1
diff --git a/crypto/secp256k1/scalar_mult_cgo.go b/crypto/secp256k1/scalar_mult_cgo.go
index d1b4c8b20e..d25046fd53 100644
--- a/crypto/secp256k1/scalar_mult_cgo.go
+++ b/crypto/secp256k1/scalar_mult_cgo.go
@@ -3,7 +3,6 @@
// the LICENSE file.
//go:build !gofuzz && cgo
-// +build !gofuzz,cgo
package secp256k1
diff --git a/crypto/secp256k1/scalar_mult_nocgo.go b/crypto/secp256k1/scalar_mult_nocgo.go
index 22f53ac6ae..956cfdb869 100644
--- a/crypto/secp256k1/scalar_mult_nocgo.go
+++ b/crypto/secp256k1/scalar_mult_nocgo.go
@@ -3,7 +3,6 @@
// the LICENSE file.
//go:build gofuzz || !cgo
-// +build gofuzz !cgo
package secp256k1
diff --git a/crypto/secp256k1/secp256.go b/crypto/secp256k1/secp256.go
index 7fbce862e1..f2927c3bcd 100644
--- a/crypto/secp256k1/secp256.go
+++ b/crypto/secp256k1/secp256.go
@@ -3,7 +3,6 @@
// the LICENSE file.
//go:build !gofuzz && cgo
-// +build !gofuzz,cgo
// Package secp256k1 wraps the bitcoin secp256k1 C library.
package secp256k1
diff --git a/crypto/stateproof/coinGenerator.go b/crypto/stateproof/coinGenerator.go
index a8a7199ad1..530d0fda0f 100644
--- a/crypto/stateproof/coinGenerator.go
+++ b/crypto/stateproof/coinGenerator.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/stateproof/coinGenerator_test.go b/crypto/stateproof/coinGenerator_test.go
index 38df47c179..403dda0b35 100644
--- a/crypto/stateproof/coinGenerator_test.go
+++ b/crypto/stateproof/coinGenerator_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/stateproof/committableSignatureSlot.go b/crypto/stateproof/committableSignatureSlot.go
index 07a1d9885e..7458c82779 100644
--- a/crypto/stateproof/committableSignatureSlot.go
+++ b/crypto/stateproof/committableSignatureSlot.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/stateproof/committableSignatureSlot_test.go b/crypto/stateproof/committableSignatureSlot_test.go
index 93a890d427..3faacd4ebf 100644
--- a/crypto/stateproof/committableSignatureSlot_test.go
+++ b/crypto/stateproof/committableSignatureSlot_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/stateproof/const.go b/crypto/stateproof/const.go
index 3580aaba6b..c4a60fe2bd 100644
--- a/crypto/stateproof/const.go
+++ b/crypto/stateproof/const.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/stateproof/msgp_gen.go b/crypto/stateproof/msgp_gen.go
index 51b3dc3848..6cf9a5308b 100644
--- a/crypto/stateproof/msgp_gen.go
+++ b/crypto/stateproof/msgp_gen.go
@@ -1,7 +1,7 @@
-package stateproof
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package stateproof
+
import (
"sort"
@@ -122,7 +122,7 @@ func (z *MessageHash) MsgIsZero() bool {
return (*z) == (MessageHash{})
}
-// MaxSize returns a maximum valid message size for this message type
+// MessageHashMaxSize returns a maximum valid message size for this message type
func MessageHashMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((32) * (msgp.ByteSize))
@@ -466,7 +466,7 @@ func (z *Prover) MsgIsZero() bool {
return ((*z).ProverPersistedFields.Data == (MessageHash{})) && ((*z).ProverPersistedFields.Round == 0) && (len((*z).ProverPersistedFields.Participants) == 0) && ((*z).ProverPersistedFields.Parttree == nil) && ((*z).ProverPersistedFields.LnProvenWeight == 0) && ((*z).ProverPersistedFields.ProvenWeight == 0) && ((*z).ProverPersistedFields.StrengthTarget == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// ProverMaxSize returns a maximum valid message size for this message type
func ProverMaxSize() (s int) {
s = 1 + 5
// Calculating size of array: z.ProverPersistedFields.Data
@@ -817,7 +817,7 @@ func (z *ProverPersistedFields) MsgIsZero() bool {
return ((*z).Data == (MessageHash{})) && ((*z).Round == 0) && (len((*z).Participants) == 0) && ((*z).Parttree == nil) && ((*z).LnProvenWeight == 0) && ((*z).ProvenWeight == 0) && ((*z).StrengthTarget == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// ProverPersistedFieldsMaxSize returns a maximum valid message size for this message type
func ProverPersistedFieldsMaxSize() (s int) {
s = 1 + 5
// Calculating size of array: z.Data
@@ -1118,7 +1118,7 @@ func (z *Reveal) MsgIsZero() bool {
return (((*z).SigSlot.Sig.MsgIsZero()) && ((*z).SigSlot.L == 0)) && ((*z).Part.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// RevealMaxSize returns a maximum valid message size for this message type
func RevealMaxSize() (s int) {
s = 1 + 2 + 1 + 2 + merklesignature.SignatureMaxSize() + 2 + msgp.Uint64Size + 2 + basics.ParticipantMaxSize()
return
@@ -1504,7 +1504,7 @@ func (z *StateProof) MsgIsZero() bool {
return ((*z).SigCommit.MsgIsZero()) && ((*z).SignedWeight == 0) && ((*z).SigProofs.MsgIsZero()) && ((*z).PartProofs.MsgIsZero()) && ((*z).MerkleSignatureSaltVersion == 0) && (len((*z).Reveals) == 0) && (len((*z).PositionsToReveal) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// StateProofMaxSize returns a maximum valid message size for this message type
func StateProofMaxSize() (s int) {
s = 1 + 2 + crypto.GenericDigestMaxSize() + 2 + msgp.Uint64Size + 2
// Using maxtotalbytes for: z.SigProofs
@@ -1661,7 +1661,7 @@ func (z *sigslotCommit) MsgIsZero() bool {
return ((*z).Sig.MsgIsZero()) && ((*z).L == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// SigslotCommitMaxSize returns a maximum valid message size for this message type
func SigslotCommitMaxSize() (s int) {
s = 1 + 2 + merklesignature.SignatureMaxSize() + 2 + msgp.Uint64Size
return
diff --git a/crypto/stateproof/msgp_gen_test.go b/crypto/stateproof/msgp_gen_test.go
index 2812908b34..8d95e59119 100644
--- a/crypto/stateproof/msgp_gen_test.go
+++ b/crypto/stateproof/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package stateproof
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package stateproof
+
import (
"testing"
diff --git a/crypto/stateproof/prover.go b/crypto/stateproof/prover.go
index f7c6e69282..56e85baa72 100644
--- a/crypto/stateproof/prover.go
+++ b/crypto/stateproof/prover.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/stateproof/prover_test.go b/crypto/stateproof/prover_test.go
index d804e9cf0c..5cb5bb32a4 100644
--- a/crypto/stateproof/prover_test.go
+++ b/crypto/stateproof/prover_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/stateproof/structs.go b/crypto/stateproof/structs.go
index 418e2bbed3..db47e49cfd 100644
--- a/crypto/stateproof/structs.go
+++ b/crypto/stateproof/structs.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/stateproof/verifier.go b/crypto/stateproof/verifier.go
index 823f2a0c72..cc3b3700ae 100644
--- a/crypto/stateproof/verifier.go
+++ b/crypto/stateproof/verifier.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/stateproof/verifier_test.go b/crypto/stateproof/verifier_test.go
index 5d26d642f3..e8a194e1a1 100644
--- a/crypto/stateproof/verifier_test.go
+++ b/crypto/stateproof/verifier_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/stateproof/weights.go b/crypto/stateproof/weights.go
index 95e72d627e..94e7817d39 100644
--- a/crypto/stateproof/weights.go
+++ b/crypto/stateproof/weights.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/stateproof/weights_test.go b/crypto/stateproof/weights_test.go
index 667257a259..5620b66fb3 100644
--- a/crypto/stateproof/weights_test.go
+++ b/crypto/stateproof/weights_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/statetrie/nibbles/nibbles.go b/crypto/statetrie/nibbles/nibbles.go
index 30518148b3..2528005c19 100644
--- a/crypto/statetrie/nibbles/nibbles.go
+++ b/crypto/statetrie/nibbles/nibbles.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/statetrie/nibbles/nibbles_test.go b/crypto/statetrie/nibbles/nibbles_test.go
index 0e81bef5e9..088b25923b 100644
--- a/crypto/statetrie/nibbles/nibbles_test.go
+++ b/crypto/statetrie/nibbles/nibbles_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/util.go b/crypto/util.go
index aa957a408b..b51b8eefe2 100644
--- a/crypto/util.go
+++ b/crypto/util.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/util_test.go b/crypto/util_test.go
index 9c19053cec..7c5184ae4e 100644
--- a/crypto/util_test.go
+++ b/crypto/util_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/vrf.go b/crypto/vrf.go
index 5b89500d70..411eeef8f6 100644
--- a/crypto/vrf.go
+++ b/crypto/vrf.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/crypto/vrf_test.go b/crypto/vrf_test.go
index 55f781b98c..0109184e1b 100644
--- a/crypto/vrf_test.go
+++ b/crypto/vrf_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/algod.oas2.json b/daemon/algod/api/algod.oas2.json
index 813fcd0063..b775d6fe41 100644
--- a/daemon/algod/api/algod.oas2.json
+++ b/daemon/algod/api/algod.oas2.json
@@ -3123,6 +3123,11 @@
"description": "\\[v\\] the number of updates to the application programs",
"type": "integer",
"x-go-type": "uint64"
+ },
+ "size-sponsor": {
+ "description": "\\[ss\\] the account responsible for extra pages and global state MBR",
+ "type": "string",
+ "x-algorand-format": "Address"
}
}
},
@@ -3403,7 +3408,7 @@
"Box": {
"description": "Box name and its content.",
"type": "object",
- "required": ["round","name","value"],
+ "required": ["round", "name", "value"],
"properties": {
"round": {
"description": "The round for which this information is relevant",
@@ -3425,9 +3430,7 @@
"BoxDescriptor": {
"description": "Box descriptor describes a Box.",
"type": "object",
- "required": [
- "name"
- ],
+ "required": ["name"],
"properties": {
"name": {
"description": "Base64 encoded box name",
diff --git a/daemon/algod/api/algod.oas3.yml b/daemon/algod/api/algod.oas3.yml
index 9efe2415bc..7331a93cbd 100644
--- a/daemon/algod/api/algod.oas3.yml
+++ b/daemon/algod/api/algod.oas3.yml
@@ -1399,6 +1399,11 @@
"local-state-schema": {
"$ref": "#/components/schemas/ApplicationStateSchema"
},
+ "size-sponsor": {
+ "description": "\\[ss\\] the account responsible for extra pages and global state MBR",
+ "type": "string",
+ "x-algorand-format": "Address"
+ },
"version": {
"description": "\\[v\\] the number of updates to the application programs",
"type": "integer",
diff --git a/daemon/algod/api/client/encoding.go b/daemon/algod/api/client/encoding.go
index c13115abe8..43eff64963 100644
--- a/daemon/algod/api/client/encoding.go
+++ b/daemon/algod/api/client/encoding.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/client/restClient.go b/daemon/algod/api/client/restClient.go
index 484b2ba168..5dbfbdb28d 100644
--- a/daemon/algod/api/client/restClient.go
+++ b/daemon/algod/api/client/restClient.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/common/handlers.go b/daemon/algod/api/server/common/handlers.go
index 86718bb2f2..07383ae435 100644
--- a/daemon/algod/api/server/common/handlers.go
+++ b/daemon/algod/api/server/common/handlers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/common/metrics.go b/daemon/algod/api/server/common/metrics.go
index 9e17e108b3..4d70678340 100644
--- a/daemon/algod/api/server/common/metrics.go
+++ b/daemon/algod/api/server/common/metrics.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/common/responses.go b/daemon/algod/api/server/common/responses.go
index 497d80c567..be0355750e 100644
--- a/daemon/algod/api/server/common/responses.go
+++ b/daemon/algod/api/server/common/responses.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/common/routes.go b/daemon/algod/api/server/common/routes.go
index ba0dceffb6..927ddd67d1 100644
--- a/daemon/algod/api/server/common/routes.go
+++ b/daemon/algod/api/server/common/routes.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/common/test/handlers_test.go b/daemon/algod/api/server/common/test/handlers_test.go
index 170252260c..8b8e7713d7 100644
--- a/daemon/algod/api/server/common/test/handlers_test.go
+++ b/daemon/algod/api/server/common/test/handlers_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/common/test/helpers.go b/daemon/algod/api/server/common/test/helpers.go
index a78dfba427..abaa601cd4 100644
--- a/daemon/algod/api/server/common/test/helpers.go
+++ b/daemon/algod/api/server/common/test/helpers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/lib/common.go b/daemon/algod/api/server/lib/common.go
index 0e59768359..138f0c2c77 100644
--- a/daemon/algod/api/server/lib/common.go
+++ b/daemon/algod/api/server/lib/common.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/lib/middlewares/auth.go b/daemon/algod/api/server/lib/middlewares/auth.go
index efc9e3540c..92b8c939fd 100644
--- a/daemon/algod/api/server/lib/middlewares/auth.go
+++ b/daemon/algod/api/server/lib/middlewares/auth.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/lib/middlewares/auth_test.go b/daemon/algod/api/server/lib/middlewares/auth_test.go
index 984a0f1dc1..8ef7900376 100644
--- a/daemon/algod/api/server/lib/middlewares/auth_test.go
+++ b/daemon/algod/api/server/lib/middlewares/auth_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/lib/middlewares/connectionLimiter.go b/daemon/algod/api/server/lib/middlewares/connectionLimiter.go
index 4b0fc21385..a5f987aa11 100644
--- a/daemon/algod/api/server/lib/middlewares/connectionLimiter.go
+++ b/daemon/algod/api/server/lib/middlewares/connectionLimiter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/lib/middlewares/connectionLimiter_test.go b/daemon/algod/api/server/lib/middlewares/connectionLimiter_test.go
index fc56df2750..931f1e30f4 100644
--- a/daemon/algod/api/server/lib/middlewares/connectionLimiter_test.go
+++ b/daemon/algod/api/server/lib/middlewares/connectionLimiter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/lib/middlewares/cors.go b/daemon/algod/api/server/lib/middlewares/cors.go
index 5ac628c934..df8a6737ea 100644
--- a/daemon/algod/api/server/lib/middlewares/cors.go
+++ b/daemon/algod/api/server/lib/middlewares/cors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/lib/middlewares/cors_test.go b/daemon/algod/api/server/lib/middlewares/cors_test.go
index c317952b48..05ac524960 100644
--- a/daemon/algod/api/server/lib/middlewares/cors_test.go
+++ b/daemon/algod/api/server/lib/middlewares/cors_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/lib/middlewares/logger.go b/daemon/algod/api/server/lib/middlewares/logger.go
index fb74026f23..62bff42063 100644
--- a/daemon/algod/api/server/lib/middlewares/logger.go
+++ b/daemon/algod/api/server/lib/middlewares/logger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/router.go b/daemon/algod/api/server/router.go
index 20dd7bd2fd..acfc946dbb 100644
--- a/daemon/algod/api/server/router.go
+++ b/daemon/algod/api/server/router.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -65,7 +65,7 @@ func wrapCtx(ctx lib.ReqContext, handler func(lib.ReqContext, echo.Context)) ech
}
}
-// registerHandler registers a set of Routes to the given router.
+// registerHandlers registers a set of Routes to the given router.
func registerHandlers(router *echo.Echo, prefix string, routes lib.Routes, ctx lib.ReqContext, m ...echo.MiddlewareFunc) {
for _, route := range routes {
r := router.Add(route.Method, prefix+route.Path, wrapCtx(ctx, route.HandlerFunc), m...)
diff --git a/daemon/algod/api/server/router_test.go b/daemon/algod/api/server/router_test.go
index c67a97b506..6e770c9751 100644
--- a/daemon/algod/api/server/router_test.go
+++ b/daemon/algod/api/server/router_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/v1/handlers/errors.go b/daemon/algod/api/server/v1/handlers/errors.go
index f3f6e1b41c..749be96d77 100644
--- a/daemon/algod/api/server/v1/handlers/errors.go
+++ b/daemon/algod/api/server/v1/handlers/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/v1/handlers/handlers.go b/daemon/algod/api/server/v1/handlers/handlers.go
index 3e7a3cdcba..c1998bf215 100644
--- a/daemon/algod/api/server/v1/handlers/handlers.go
+++ b/daemon/algod/api/server/v1/handlers/handlers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/v1/routes/routes.go b/daemon/algod/api/server/v1/routes/routes.go
index 6bf85e2851..6d08ff476f 100644
--- a/daemon/algod/api/server/v1/routes/routes.go
+++ b/daemon/algod/api/server/v1/routes/routes.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/v2/account.go b/daemon/algod/api/server/v2/account.go
index e94f09767a..7089b19bf9 100644
--- a/daemon/algod/api/server/v2/account.go
+++ b/daemon/algod/api/server/v2/account.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -223,58 +223,35 @@ func AccountToAccountData(a *model.Account) (basics.AccountData, error) {
var assetParams map[basics.AssetIndex]basics.AssetParams
if a.CreatedAssets != nil && len(*a.CreatedAssets) > 0 {
assetParams = make(map[basics.AssetIndex]basics.AssetParams, len(*a.CreatedAssets))
- var err error
for _, ca := range *a.CreatedAssets {
var metadataHash [32]byte
if ca.Params.MetadataHash != nil {
copy(metadataHash[:], *ca.Params.MetadataHash)
}
- var manager, reserve, freeze, clawback basics.Address
- if ca.Params.Manager != nil {
- if manager, err = basics.UnmarshalChecksumAddress(*ca.Params.Manager); err != nil {
- return basics.AccountData{}, err
- }
- }
- if ca.Params.Reserve != nil {
- if reserve, err = basics.UnmarshalChecksumAddress(*ca.Params.Reserve); err != nil {
- return basics.AccountData{}, err
- }
- }
- if ca.Params.Freeze != nil {
- if freeze, err = basics.UnmarshalChecksumAddress(*ca.Params.Freeze); err != nil {
- return basics.AccountData{}, err
- }
- }
- if ca.Params.Clawback != nil {
- if clawback, err = basics.UnmarshalChecksumAddress(*ca.Params.Clawback); err != nil {
- return basics.AccountData{}, err
- }
- }
-
- var defaultFrozen bool
- if ca.Params.DefaultFrozen != nil {
- defaultFrozen = *ca.Params.DefaultFrozen
+ manager, err := nilToZeroAddr(ca.Params.Manager)
+ if err != nil {
+ return basics.AccountData{}, err
}
- var url string
- if ca.Params.Url != nil {
- url = *ca.Params.Url
+ reserve, err := nilToZeroAddr(ca.Params.Reserve)
+ if err != nil {
+ return basics.AccountData{}, err
}
- var unitName string
- if ca.Params.UnitName != nil {
- unitName = *ca.Params.UnitName
+ freeze, err := nilToZeroAddr(ca.Params.Freeze)
+ if err != nil {
+ return basics.AccountData{}, err
}
- var name string
- if ca.Params.Name != nil {
- name = *ca.Params.Name
+ clawback, err := nilToZeroAddr(ca.Params.Clawback)
+ if err != nil {
+ return basics.AccountData{}, err
}
- assetParams[basics.AssetIndex(ca.Index)] = basics.AssetParams{
+ assetParams[ca.Index] = basics.AssetParams{
Total: ca.Params.Total,
Decimals: uint32(ca.Params.Decimals),
- DefaultFrozen: defaultFrozen,
- UnitName: unitName,
- AssetName: name,
- URL: url,
+ DefaultFrozen: nilToZero(ca.Params.DefaultFrozen),
+ UnitName: nilToZero(ca.Params.UnitName),
+ AssetName: nilToZero(ca.Params.Name),
+ URL: nilToZero(ca.Params.Url),
MetadataHash: metadataHash,
Manager: manager,
Reserve: reserve,
@@ -366,12 +343,9 @@ func AccountToAccountData(a *model.Account) (basics.AccountData, error) {
LastHeartbeat: nilToZero(a.LastHeartbeat),
}
- if a.AuthAddr != nil {
- authAddr, err := basics.UnmarshalChecksumAddress(*a.AuthAddr)
- if err != nil {
- return basics.AccountData{}, err
- }
- ad.AuthAddr = authAddr
+ ad.AuthAddr, err = nilToZeroAddr(a.AuthAddr)
+ if err != nil {
+ return basics.AccountData{}, err
}
if len(assetParams) > 0 {
ad.AssetParams = assetParams
@@ -421,6 +395,10 @@ func ApplicationParamsToAppParams(gap *model.ApplicationParams) (basics.AppParam
}
ap.GlobalState = kv
+ ap.SizeSponsor, err = nilToZeroAddr(gap.SizeSponsor)
+ if err != nil {
+ return basics.AppParams{}, err
+ }
return ap, nil
}
@@ -444,7 +422,8 @@ func AppParamsToApplication(creator string, appIdx basics.AppIndex, appParams *b
NumByteSlice: appParams.GlobalStateSchema.NumByteSlice,
NumUint: appParams.GlobalStateSchema.NumUint,
},
- Version: omitEmpty(appParams.Version),
+ Version: omitEmpty(appParams.Version),
+ SizeSponsor: addrOrNil(appParams.SizeSponsor),
},
}
return app
diff --git a/daemon/algod/api/server/v2/account_test.go b/daemon/algod/api/server/v2/account_test.go
index e58990ada0..173a7cbf80 100644
--- a/daemon/algod/api/server/v2/account_test.go
+++ b/daemon/algod/api/server/v2/account_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/v2/dryrun.go b/daemon/algod/api/server/v2/dryrun.go
index acec949591..c940709296 100644
--- a/daemon/algod/api/server/v2/dryrun.go
+++ b/daemon/algod/api/server/v2/dryrun.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -628,10 +628,10 @@ func MergeAppParams(base *basics.AppParams, update *basics.AppParams) {
if len(base.GlobalState) == 0 && len(update.GlobalState) > 0 {
base.GlobalState = update.GlobalState
}
- if base.LocalStateSchema == (basics.StateSchema{}) && update.LocalStateSchema != (basics.StateSchema{}) {
+ if base.LocalStateSchema.Empty() && !update.LocalStateSchema.Empty() {
base.LocalStateSchema = update.LocalStateSchema
}
- if base.GlobalStateSchema == (basics.StateSchema{}) && update.GlobalStateSchema != (basics.StateSchema{}) {
+ if base.GlobalStateSchema.Empty() && !update.GlobalStateSchema.Empty() {
base.GlobalStateSchema = update.GlobalStateSchema
}
}
diff --git a/daemon/algod/api/server/v2/dryrun_test.go b/daemon/algod/api/server/v2/dryrun_test.go
index 8bd7addc92..f4f1d044b8 100644
--- a/daemon/algod/api/server/v2/dryrun_test.go
+++ b/daemon/algod/api/server/v2/dryrun_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/v2/errors.go b/daemon/algod/api/server/v2/errors.go
index 38233d097b..93b18c3237 100644
--- a/daemon/algod/api/server/v2/errors.go
+++ b/daemon/algod/api/server/v2/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/v2/generated/data/routes.go b/daemon/algod/api/server/v2/generated/data/routes.go
index 9ae261b61e..fdd7e23287 100644
--- a/daemon/algod/api/server/v2/generated/data/routes.go
+++ b/daemon/algod/api/server/v2/generated/data/routes.go
@@ -214,126 +214,127 @@ var swaggerSpec = []string{
"0PdtEcv3yz7REySeiqH3xjGXXMi0sde7DGjhCR8XO7obj+7n75G6J92Ie3bidbiak7uA3pjW/t9w+jpw",
"Q2hZSrGmxcT5yfQJHVKsndCBzb1bzUd+X6VPxdXX5y9fO/DvxqOsAConQdXRuypsV/5pVmVLcOy+hmw6",
"dqfbtaqwaPNDyuzYk+YWU6+3tGmdWje131R0UJ1nzTztKb6XbzoXL7vEHa5eUAZPr9oibR29ms5ddE1Z",
- "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",
+ "4Q2/HtqhWna73GHVlZJ8Ih7g3k5ikfffvcdS7DeYoIup6HHQUgG/7mZ0LqnM4BKD4Sy2LZbbtPHDl28O",
+ "3/ze4IXr67drD05t5LHeWyFPf8LBTx3pft1hgGkGUh/APWwbkf8K06umH4PcJV9Fbu284OjJhdNvhGzc",
+ "ni7UMulF9+GkVvPCsXhMewpcOdeAjqw6JVau/XXxq2FYjx7FFPfo0Zj8WrgPEYD4+8z9jo+7R4+S1uqk",
+ "/tHwUVQvcrqChyFYo3cjPq5uhMPtMBnmfL0KgrvoJ8NAodYdzqP71mHvVjKHz9z9kkMB5qfpEP1JvOkW",
+ "3TEwQ07QZV+oZPDIXtkao4oI3k4MgKG7hrTwPnRlRazxv3uEeLVCY/hEFSxLeyLxGXJIbv2MTWOCjQcb",
+ "ts0cFetxducVi0Y3zdRRdtjWQqJZkwhXyfTENX5nwrGAirN/VhDVGsYroCUx+PcZjtqR+tNKTzdwu5Tx",
+ "6JgqxPe3W3pV3y4t1k478Itgm/SISBW/OjAII56xw/x3BFA4ivLXJ0bbLZ0/817K2vn43F2Z2tmmPft0",
+ "ZuD+V5ur0Wk388WQnWZqMpfiN0jLDmi5TOQT8SZ3hlaB34CnHGfbjCy4M9RVtOvZ9xHIcIVHH6ncW8Hh",
+ "Fx1K+R1zhaf5xGEbfaAmI9rvfl2GSuc8d5vQ93qOvWGa0T09zAwPbOSrjgWGvA8e5faE2mQbjXC49DmP",
+ "o1fP7Pj1OXcwdyJ+C3o7o6nqS+YRa2CKtr/hLagF8Z39BqmQL8LOTqIAi9CW2QyEJcjapNXN33zkg9RO",
+ "O/gpWr88keLiN+fYOtAUSiSGqfgt5ejciP0sB3S9FVjnENPrVkjMOqrSjo05ZGyV1NBfX7/Ns647Ws4W",
+ "zNY5rxQQOtcu+aQbyFa6t1TkSoyHBCkONRdz8nhcn1m/GzlbM3yRYYsntsWMKrygg6NG6GKWB1wvFTZ/",
+ "OqD5suK5hFwvlUWsEiQoDVD0DO65M9C3AJw8xnZPviCfoBezYmt4mL5gnLA2ev7ki/Guct6Icaxcv4vJ",
+ "58jlfXRFmrLR1duOYdiqGzUdLjGXAL9B/32y43zZrkNOF7Z0V9D+07WinBqEpGBa7YHJ9sX9Rf+SFl64",
+ "NRmB0lJsCdPp+UFTw7F6QtwNQ7RgkEysVkyvnPuqEitDYXVtdDupHw6L/vnabB4u/xH9wsvEG/93eG7R",
+ "VU/YJbr6/4hOADFax4TaNLIFq4NCfNlccuHTZWOxulCjzuLGzGWWjvIqxojMSSkZ16jKqvR88lfzfJc0",
+ "Mwxx2gfuZPb5s0TRt2ZdJH4Y4B8d7xIUyHUa9bKH7L2U4/qST7jgk5XhKPnDOs9EdCp7HdjTTsd9vtA9",
+ "Q99bujbjTnoJsGoQII24+b1Ike8Y8J7EGdZzEIUevLKPTquVTBMMrcwO/fTmpZNEVkKmym/UDMBJJRK0",
+ "ZLDGoNf0Jpkx77kXshi0C/eB/vd1ufNiaSS6+dOdfCxEpu7EOy3kejKS/s8/1En70eJug4lb2kshE3pa",
+ "p3H8yL6yh+kL24Z966OI33owNxhtOEoXKz0xKDbIJPT5PZzQ2iDZPW+oSp/8SqR5x6Os/+gRAv3o0diJ",
+ "yr8+bX627P3Ro+F+vGl9ofk1gZrj7pp2Sk3TN7XVX4qE9s6XFg3ObC5/SkLDmrzLzJU6c2OMSbN+48eX",
+ "O04TRHmwb3T6AHnU4Oc2bn5n/oqbWYfl9POHZknbJPnk4XsU2EHJl2IzlIha15anpz8AinpQMlAriCvp",
+ "lOxNum/s9T2KyNaMOoNCmJdqXJVrsCvNn2gXDGrGO/aiYkX+c22Fbt1MkvJsmfR0n5mOv9hnQNQg0mBk",
+ "S8o5FMne9rX8i39VJ979/xA9w64YT39qV4e2sLcgrcFqAuGn9OMbXDFdmAliFDWzhIW8K8VC5ATnqcup",
+ "1KyxW2Y9Vd42kXgAh11V2rlKY0YHV+Vkzgr07U3bw7HlRFLdw1UlxgPP6xFhbeQUq5awo4MklK3w2lZ0",
+ "VRaAh3ANki6wq+DQ6o5p5HDkqFYKUaX5hC0xI40gupKciPk8WgZwzSQU2zEpqVJ2kMdmWbDBuUfPnzx+",
+ "/HiYkRHxNWDtFq9+4a/qxT05wyb2iytHZqs4HAT+MdDf1VR3yOZ3icvVhP1nBUqnWCx+sFHiaCE297qt",
+ "BxtqF0/Jt5g0zRB6o24BKkV92udmotKqLATNx5ip+urr85fEzmr7SEDUYT3aBWoAm0ckaeQZnrjVJ4Xr",
+ "Sag1fJzd+XzMqpWehEqxqfSOpkVd4Ja1XLJQNxhjZ0peWLVscOyxkxDMdy5XkEeFaa0aAInD/Edrmi1R",
+ "3zkd7VQp95QoGl5X2XPA2lwUBeOGKl7Iwc0yXGllW1l5TIRegrxlCjAZBqyhmUUypGB1CnmfVbK5Wllx",
+ "bglneoD0Gmp2HboLHjgr+nr/iiRkrX24t+2vTi+CldcPrUB9ib3SwUStctYtvwdbx2PjK4FMyQ/O2JFR",
+ "LjjLsAJGSgTH/JDDzKoDioWk7Z1q5M5y4hgmi2iHqHmHxd6y2p5lOsR1nRqir2a/LeHYPzVsXGXCBWjl",
+ "eCDkY1/T3hnoGFfgqrIZ+oo5qpAJ169krE5wITmhn/x4hCneenSt35hvPzrdPCayuWEcdW4Oqe4laA1s",
+ "hWJoZ+eEabIQoNxqm8Fq6q3pM73acATh3fSlWLDski1wDOuKaJBiXZO7Q517R2XnGGzafmXauoIK4eeG",
+ "S52d1K/7XZKFqLD/qULwvehP+X55R5oIuWH8eLQdxLgz/gDvZUOGsEbPPyjxPu+QTaip3xzla/NktfSG",
+ "LYgNJ07mMmY8AcZLxr3BN52cK0veJbgxeJp7+qlMUm0fHYM43hXQoidGByP9rcfAfYdql4cwKME1+jn6",
+ "t/Fqw11tix62EhrUrwvKt8QfCkPdkVDyFS2Ch36iuD9KZ04Ys87CrXL/KbZi2PrExws30LU3OjV0xxIt",
+ "h95TfSlQZ1W+AD2heZ5KhvclfiX41Uc5wgayKlQmC8GvzRzyXWpzE2WCq2q1Yy7f4J7T5UxRpWA1KxKu",
+ "ty/CR8jDDmN2rNkW/02V5erfGeeJf3BIune7zw8rnNANsU9Jz4amJ4otJsMxgXfK/dFRT30codf9T0rp",
+ "Phr9DxFs3uJy8R6l+NvX5uKIc4d3fPzt1RJSe6M/vcDvPklZSC/b5Ep4lXWKz6FHBm5eYstawPuGScDX",
+ "tOhJAxFbbez9ai0Zfckgst5cJ1S7lHqakponDFFh9Cclsx7YLctQ17zZ52NtXaw/pPHE4WMn0vstjd83",
+ "7IrW661mKL32xONMfjURHGrzc/UhuvpSWhQiG8wZ3DDnplN//mCxWrl0/AmvvPVK5PFZiL25ANKMzTos",
+ "J0Ir8GGb/IZPq+QXeZseraEfCUQzNJUaotEtYWyjRT14Hhg7dTxRpLJ1mCXfsAIrVv3n5asfR/0bGe1A",
+ "d0tdPu+kCrtvY0L4XJs8FqKBjx08QPAirf9WPSp1TFiVPg2uZHLywzdWQTgEJJu86ZDWL4cO3iGAhbCl",
+ "qlLFPLopc0b1dnjkR9RQb6/lKDF1pKiiXQIq8faxSs+6CQnVUQdVS23ISEMqTqWKG7mXgtfA2ovGJcmz",
+ "FZ86xaI6DPTFEOGwg4+78egiP0h8ShXIGtlRUgz2JVss9ZeFyG6+A5qDtEVOUs9JW+JkBeYZqpasxPdP",
+ "KRSrixQXZjCXXXyJw02HhuZcLcGlqvGZCzpjeQfqNWQai1bXbqASYLifQ5leooHAGxSxye/gCiIBcij1",
+ "cqewZJ27S72sa5mCizxjiszAmS7WwMeETWHaDlbL60xVpAA690pYKYQeUOw3hC0hGmOgU/TVKRy9Wwzs",
+ "JKKL8iza+r7T4ZVhzkNMgA20vKWqTmfVyu0wOIZ8PocMs/DvzAn49yXwKEnc2KvuEJZ5lCKQhXBBrCNx",
+ "Uo12Deuu7Hw7QY0KZX1ISPuydNzA9oEiDRpKlikOEbbHpKVH5Fg7rq900GfacI6RTAV6QgR5P3hXFaAu",
+ "/HRMZYIoZeaRYHgaN9dTnUbzOGi8RHMEGKbrgZP25uhDwbQv5WC35Hv/S/kFVthXzqmUhhz4sT6JXHRr",
+ "RN+6HPqY/TFYC302fVD+N5811s5SsBtXNgcRZm2zt1TmvsVJcvfZe5OlgZ6HmVkdGNX18jnUL8dGKGaF",
+ "MALQpC8wtBmpFFx4Hyjra11nUkOo5yAl5MEmWAgFEy18mNUBGUld+OQO7Fkv86Pw1vLoPyBk2K6ot7DD",
+ "m7q6BdaopFjIgTrn8xgrRMKKGuhlVHEirQbdt0Nf2e8+0YmvObhbvdqH93Au9pft9qF3THUwH5+uOXHC",
+ "wcHcq5Ed5QjNLOMc5MQbcdv1Jngzdycme86rzIoq8dkM2uvBudB2cLOkUjPrrrL1hIqyctzA9syqfXwp",
+ "dL/jMdBWhrSgR1muW0RxUl21SsG9OAl4v29O0VKIYtJjGbzoFsloH4Yblt0AZosNkSlGCn7QPDZmEvIJ",
+ "GqSCz8jtcutLQJQlcMgfTgk55zY60LuPNMuitibnD/Su+Tc4a17ZsjdOAz295ukwKyw/I+/J/fwwO3he",
+ "H29SYPjlPee3gxwxu97wPh+5W6xT0yxePB2q3uj6d7REqIj8LBQpAerSGoK/QpaQeEcRzM4SpRFC/wBK",
+ "nAGZqEKkvPCPySBjhkpjKp4MAdLABzxXayjc4EkEOCe7Pali3WefDFXMiYTaN+PYrLAu0apl4qpPNdKe",
+ "OczS5IxzISGeEf1MbfboENmGyZfxPzOmJZXbY3K3NlGVUkP1Ynmvt2RwlKwXUjtLdnFYFOJ2gmxtEko+",
+ "pdQBpp1qXtu+eGrdzxz1GURul1Q5EXFLljQnmZASsrhHOsTbQrUSEiaFQC/MlGPHXJtHwgrjOjkpxIKI",
+ "MhM52OpsaQrqm6vinKLsBZErWxIFlnYwZYDtE9HxwCnN7WvNsxOU1/ZW//Cbf2X62PQVdU4+u+iJdRHo",
+ "iS8A5bLCOQzZxl14bf44zMjUVsqmReQ52yDdgEwd+TnRsoIxcS2sQBKTEB58KoGsmFIWlEBLt6woMHsE",
+ "20QODcEfKI3aHtn5Av2g1wwd3pqZRKxIXZrbMaRfiXnAZZyRjeilFNViGRUtCHD6p7us3MM+HuUnVaFP",
+ "IoaImimekZVQ2j2L7Uj1kmsX0E8ywbUURdFU5Fk5f+GMvj/QzXmW6ZdC3MxodvMQH+Fc6LDSfOxTKrR9",
+ "d+uZZCsx5LCXgt7wCZKH2p/73bZDr1ZHz4N5Z4v7dQwP+zT5EZjv9jPX/XaN8+7C2utq8tn0W+icE6rF",
+ "imXp4/bn8n7t9VlNca9kpkVbGtlmocFmyAfieyy4MyH37KIZOE3Wdj0njkc4tw7kROa/KMa3xyVzcDyo",
+ "5w7t8h0nYE2yXjGwBQBCahMh6EraesqxkBYYjljYxCnolNIGdOCFg75/94PNjHByoDTcC6iON3IA8BOr",
+ "wRjbjJjWs3kmNv77wzpl5lHA3+2m8gbz6HOqvKxJS1q3Sp/IqocjpKsi7PRAvMIkGLOhfoihPv7Ayz8C",
+ "oN8zsQHDIP/EQ8GYU1ZAPkmVTr4IOrBx9Fx3MZbR6L7IpOXkGa18eWIzdiXBJVay0r9smhNLakhJhOZd",
+ "jTjPYQM2Rus3kMIWFx5H5iwobO3hlkZBlJMC1tBw2HTZniqUQtkafF8VOpMcoESLb1vRlvJEjEsXtrQv",
+ "bu2TyJdtCHaT6hiLWLtTZI+uJakZ2vCJPSZq6FEyEK1ZXtEG/tShIkdTl2iOcgJVnefDxD8xh07zkx3h",
+ "jR/g3PdPiTIeE++G8aGDWVAadbsY0F7P5Er1nXqedkyOU5kFQxHOlge7tiXxmm+okt7yfq1ml+Trl9jA",
+ "fWKCR4j9egMZSjXuKQS5ewz1WE5cDiSkdg6Q2weD6ZLQ5i+BEy6iQsy3VIVXTJ3V1f9gJ8ZGjLuH9hE2",
+ "+tp/+P47S3AwolrJFtN1UwNZ30/H/7ucxJ0HsXe8FI0ocKG8O1RjnrrdswMbiKrICTf7aWR/LFzsbjHH",
+ "xcdkVvmBikLc2srK8RP1BXh7rqU+b2JyYjkL17L3kx67hMNtLQiLIkRWdEuExH/Mg/SfFS3YfIt8xoLv",
+ "uxG1pIaEnAHZelE4v2sz8W7xauwB84oY4aey62ZDx4yG25pRIqDNRe5ryQmyojcQbwM6iFj+mWnDOFU1",
+ "Q6WGubJb29nFglu8T8+0onmsBMBEs9sGd/AJz03v/1mHrcZT+fyPZUEzX0fbVcRr8hkste+JSy9htTvM",
+ "ucvXPAmE8v010UqfJiM/Qpt6IOtKxfz0VexqgN2pS94pVnavZQxUCrcKL+0IEB+0lFPvwmliODtLiusP",
+ "71tcXI754+xOMkN03zKGgP8H2pWGe0Unsi1d1j1ej63g/hF2oZGIJwGrVYPPxGYiYa72OdJYPfhMbGqA",
+ "VdDdMp5JoMr6HV28cs/WOgEy4+YZbb12g1k1jJLDnPGa1TJeVjrxCsI8yHwbISy2JiBae2xzfTKGEUXX",
+ "tHi1BilZ3rdx5vTYesVx5SBvQXF9EwqQcCN3B2CqfgFiPHWtn4+bmevfVj20vrNKU55TmcfNGScZSCM1",
+ "kFu6VcebqoLVYZ+xikayUDNbSGS2QtK2gBRbZ22+pyEpAEhPaFEaYAlCJ+2EFcgqhrToMfx0YfhTWIJW",
+ "dDMpxAKjfnsOhMtzjaZD+4AUHJXoVrobtm4/j2K/we5psBSJY0Ra4KxDpth97l/hVuIj9CfO9M6TbzWc",
+ "7TBs6+lsD6ZHKl/U4RmWWLrnMRU57xIzxdHzXlT1aUo87UG0iUmX6I5WvWcX0b/CpV2IVejDK2g2XThS",
+ "8flWrzBBfYPaEYABqo4roJnzEOsq4jqKCouUsctucKCezmr3/b3UAx4qUpQ7681pg4OOGeeQsqO78xlM",
+ "SlFOsiG+rbZaUe6MDA7SJow99BGZEHrWHfxuVKjf1ciJ1ijkdWjl1d5CYvtsZWW2S2XQp2Tq4ehNA4aY",
+ "Iy/DI2xVaxhrFVQxY/8498buphItMAlCiYSskqhkvqXb/dUoe7LPX353/tmTp788/exzYhqQnC1A1TUN",
+ "WtUca9dExttao4/rjNhZnk5vgs8WYhHnrZc+7C1sijtrltuqOhlxp5blIdrpxAWQCs7tlsg7aq9wnDos",
+ "4o+1XalFnnzHUij48HsmRVGka8oEuSphfkntVmSAMS+QEqRiShtG2LSfMl07ZaslKhcxa/ja5oYSPAOv",
+ "fXZUwHSPL1dqIX0+vcjPMBeDszkR2JSF41XWTrRrXe6dZvV7KDSiu80MSClKJ9qzOUlBhDFbsoKgV3dq",
+ "U9SnR266gdlah90UITrn9zTpnXP3EhZzspvbN+uD6zSnN5uYEC/8oTyCNPusG/15Ro7hJLVh4A/DPxKJ",
+ "U07GNcJyPwSvSL4PdkSFn3e8JkLSkEGgdRNkJMgDAeiJh24ErUZBdlFucmltDGiN8ObntvjxQ22W3huZ",
+ "gpD4DnvAi2OZ63YhmMKB8zsn9v4hICVayrs+Smgsf194tGe94SKJtsgpTbQGZdmS6IqFUUC8+irEmfe8",
+ "Sjrh6FIITczLtCgSYexWj4NnKiYc8ySQa1p8fK7xDZNKnyM+IH/TH7gVhy3HSLaoVCdPyPmSDgIrClH+",
+ "KFDx1xhb/3cwO5u8Hd0szvDfuQNRJUQL6+09DxZw4OQWx7SOXU8+JzNX7qeUkDHVdii49SJNiLcFyebO",
+ "vxY2uh37e+8yQT8LfY/jMPf+QOTHyMgWPAcczPVR/52ZUw8HSJ6WFKl2CCWBvxSviyu977l27lka5rhU",
+ "TlHixgNTOXVr2A9dHq4DL69KQXedg2/9Bm4TF369tqG5ygZXmLm+fqtnQxKKpavBmO6Y4+wkZWHuXxTm",
+ "oyQ4s6h0YzhIkoRVi9z7ste0/CWjPA3NXTTifk8B+aVFvxkNHwXzitvxQgFUjBX3bF3Mx8GLQXDT7Tm5",
+ "5o+IWlL/tnB/Pv3s89F4BLxamcXX30fjkfv6LvVSyzfJuNI6kU7HR9RVE3igSEm3Q4LZ96bOSeK3zhT0",
+ "8UUapdks/ab7zuwZPlxdAMIFR1aP7MXeoC5/zr8SAO0khtZhDSfGkmSdHihsxb5MQT/3pcW3qd97qn20",
+ "uG/Fir1Oco1CLHfj0cImKcPqJL+4WnUfd9s9BD35At3S75MGzCImsdbG5NFUUVK3AQVZXLdEhQyMvM4q",
+ "yfT20uDfq93ZLzepZFDfhvRMLudXsMA72VeLG+Dex6xO5lQpL11/K2iB0qd1DOBG5hTFlHxtK4S4a/Fv",
+ "D2Z/gU//+ix//OmTv8z++vizxxk8++yLx4/pF8/oky8+fQJP//rZs8fwZP75F7On+dNnT2fPnj77/LMv",
+ "sk+fPZk9+/yLvzwwlG5AtoD6yj/PR/97cl4sxOT89cXkygBb44SW7Hswe4MatjkmKESkZnjFwoqyYvTc",
+ "//S//EU5zcSqHt7/OnL1IEdLrUv1/Ozs9vZ2Gnc5W2AOlIkWVbY88/NgLsvGe+X1RYgLsr5/uKO1zQk3",
+ "NeT3M9/efH15Rc5fX0xrghk9Hz2ePp4+wXyKJXBastHz0af4E56eJe77GWbRPlOuGM9ZCB29G3e+laUt",
+ "1WM+LUIaUPPXEmiBLNL8sQItWeY/SaD51v1f3dLFAuQUI8bsT+unZ/7tcfbe5ZW52/XtLPZGO3vfSM6T",
+ "7+np/an2NTl778v97x6wUcrd+blGHQYCuqvZ2Qzr7g1tCvHq+peC0oY6e49v9N7fz9x9nf6IahR70s68",
+ "ENLT0uYSSX9soPC93piF7B7OtInGy6jOllV59h7/g4cmWpHN432mN/wM3U7O3jcQ4T53ENH8ve4et8D0",
+ "sx44MZ8r9I7Z9fnsvf03mgg2JUhm3p6Y4sz9arNanmGZ22335y13ThIFpFKB/cQVWB2br0+05VkdiRv4",
+ "yEXuG19ueeYfyd4PG7nD08eP7fTP8D8jV9+xlRXrzJ3nkb3P96p6G5mzkfe2tPwBXhtvbARihOHJx4Ph",
+ "glvfa8OM7aVxNx599jGxcMGNfEMLgi3t9J9+xE0AuWYZkCtYlUJSyYot+YkH9/GoTH+KAm+4uOUeciNx",
+ "VKsVlVuUmldiDYq4ck0RcRIJRnaybxUUhmsaxiuPGj7ydlRWs4Jlo7HNk/4OpTWdEly86rk7k1e714M3",
+ "T8W3e8/E8F1oysM70nANgvP41H125kRK4c7We7Jo+3RYKB6k9m70Lx7xLx5xQh6hK8l7T290tWGmSyhd",
+ "xH1GsyXsYhXdizS6+0elSKXAudzBR1xdtD42ctlkI7Xv8uj5225ouqNm1ApM/VvGCOr1U0MGhuTPNTpq",
+ "RPs5uApe24rS/+3dH0Io+Ipyf9IbtGA9KKgsGMhAH5R3i9j9iz/8f8MfbHFOavd1TDQUhYq5ghbIFawC",
+ "zuVK5tYJYCCHaGS9riXwxs9nXtmRerg2W75v/Nl8jKllpXNxG82CZkJrGe8+TczHSrX/PrulTE/mQrq0",
+ "yXSuQXY7a6DFmSvN1/q1rnfT+YJFfKIf47j35K9n1L1RUt+QC/Z17DyiU1/dO7GnkQ+48J9rVV2s+kIO",
+ "HJReb98ZLqdArj1zrjU5z8/OMH5vKZQ+G92N37e0PPHHd4GwfLXyUSnZGssfvTM8Vki2YJwWE6cKqUuP",
+ "jp5OH4/u/l8AAAD//2Q3BRCzDQEA",
}
// 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 f2e2c342f2..41ab0d5c51 100644
--- a/daemon/algod/api/server/v2/generated/experimental/routes.go
+++ b/daemon/algod/api/server/v2/generated/experimental/routes.go
@@ -131,231 +131,231 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "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",
- "GYWbDgEA",
+ "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",
}
// 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 46a3d600e9..53bb1417ae 100644
--- a/daemon/algod/api/server/v2/generated/model/types.go
+++ b/daemon/algod/api/server/v2/generated/model/types.go
@@ -379,6 +379,9 @@ type ApplicationParams struct {
// LocalStateSchema Specifies maximums on the number of each type that may be stored.
LocalStateSchema *ApplicationStateSchema `json:"local-state-schema,omitempty"`
+ // SizeSponsor \[ss\] the account responsible for extra pages and global state MBR
+ SizeSponsor *string `json:"size-sponsor,omitempty"`
+
// Version \[v\] the number of updates to the application programs
Version *uint64 `json:"version,omitempty"`
}
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 20a728cccc..ce7f06a588 100644
--- a/daemon/algod/api/server/v2/generated/nonparticipating/private/routes.go
+++ b/daemon/algod/api/server/v2/generated/nonparticipating/private/routes.go
@@ -283,132 +283,132 @@ var swaggerSpec = []string{
"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",
- "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",
- "6hLWo6fT09Hd/w8AAP//E+Why2YTAQA=",
+ "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",
}
// 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 1739a5dd27..8ed5635845 100644
--- a/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go
+++ b/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go
@@ -754,305 +754,305 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "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",
- "a0PJAQA=",
+ "H4sIAAAAAAAC/+y9e3fbtrIo/lWwdM9aeRxRdtKkp81vde2f82p9mteK3e67d53TQCQkYZsCuAFQlprj",
+ "734XBg+CJChRsuwkrf9KLJLAYDCYGczz0yDl84IzwpQcPPk0KLDAc6KIgL9wlgki4b8ZkamghaKcDZ4M",
+ "jhjCacpLplBRjnOaonOyGg2GA6qfFljNBsMBw3MyeOIHGQ4E+XdJBckGT5QoyXAg0xmZYzOtUkTob387",
+ "Sv55mHz/4dPj7y4Hw4FaFXoMqQRl08FwsEymPLE/jrGkqRwd2fEvNz3FRZHTFOslJDSLL6p6BdGMMEUn",
+ "lIiuhdXHW7e+OWV0Xs4HTw79kihTZEpEx5qK4phlZNm1qOAxlpKozvXohz1W4sbY6xr0oGtXUXshxSqd",
+ "FZwyFVkJgqfIPI4uIfh83SImXMyxar4fkB/Q3oPhg8PL/+NJ8cHw8TdxYsT5lAvMssSP+8yPi07Me5db",
+ "vOieNhHwjLMJnZaCSHQxI2pGBFIzggSRBWeSID7+F0kVohL998nbN4gL9JpIiafkHU7PEWEpz0g2QscT",
+ "xLhCheALmpFsiDIywWWuJFIcvvT08e+SiFWFXQtXiEnCNC38NviX5GwwHMzltMDp+eBDE02Xl8NBTuc0",
+ "sqrXeKkpCrFyPiYC8YlekANHEFUK1gWQGTGEZy1JlpSpbx816bD6dY6XbfBORclSrEgWAKgEZhKn+g2A",
+ "MqOyyPEKUDvHyx8OhxZwiXCeo4KwjLIpUksmu5ai597bQhhZRhB9OiNIP0EFnpIAzyP0iyRASfBU8XPC",
+ "PHWg8QoeFYIsKC+l/6hjHTB1ZCEBHQheshijQvDAormDR5lv98mg3sOIl+ufSTq1j5pQn9Dp6aogaEJz",
+ "LS/Rv0qpPAGXErZ9RpAsSKp5b4b0MBr5kk4ZVqUgT87Yff0XStCJwizDItO/zM1Pr8tc0RM61T/l5qdX",
+ "fErTEzrt2AEPa+ycSvhsbv7R48WPqlpGZckrzs/LIlxQGp4FTSvHz7sow4zZTRpxBnnk9QbYHzvW6fL4",
+ "eRdLXf+FWvqN7ACyE3cF1i+ek5UgGlqcTuCf5QRIC0/EHwOjXuivVTGJoVaTv2XXoFAdGf3pqFIi3tvH",
+ "+mnKmSJGFAZqxgEw2yefQs1J8IIIRc2guCiSnKc4T6TCCkb6D0EmgyeD/3NQKXoH5nN5EEz+Sn91Ah9p",
+ "YSyIZnwJLootxninlUdQtToOuuZD5qhPuEAXM5rOkJpRiSgzmwh6l+Y0OVlgpkaDrU7yZcgdfrNAVFth",
+ "hKTZigYD6twLZF4cEwm0b5XeO7KmKQLGEWAcYZahac7H/oe7R0VRIReeHxWFQdUQ0QkiFOQ5WVKp5D3A",
+ "DK4OWTjP8fMR+jEc+4LmOeIsX6ExsXKHZHpMw7ctH7cKuEYsrKEa8Y5EsNNcjPSuOTRovWwfxAha5Yzn",
+ "WgRuJCP98k/23ZAC9e+9Pv7qqS9EezfdgUZvkQrUZH6pLm7oboOo2jQFX2hqOmp+uxtF6VHW0JI8rhC8",
+ "b7qCX6gic7mRSAKIAkKz24OFwCunQSWgCbUp6BdJDPEUeEoZQDvUCjlDc3xu9oMD3jUhEOk1bUNmRr26",
+ "oGpWqVwe9aPW/eLrJuTYniO94Zhq3RjlVCqtDMFmSjQjOSic2BsWQiraiWh60MKaRXiYLwQuDJnbJ0aP",
+ "owxhf/8ysF5RkvcUslGYQ7NFhXeAamdmvpHhRiExBoc6DE9znp7/hOVsD4d/7MZqHwuYBs0IzohAMyxn",
+ "kTPVoO1qtD70rV8EmkXjYKqRX+IrPpV7WGLOt+FqRfEM57meus3NGquFgXsd5DxH+mVE5lTpCzBlcAKm",
+ "dEGYYT0j9AKnM61MoBTn+bCyS/AiycmC5IgLRBkjYojUDKvq8MPI7qIE50gSzQcVQcFqrE1jhE5nRJAJ",
+ "F3BRFQTNMQinub4eFXn9G89cJZ6Thu4EwpKXSsMY3FyOn7vVkQVhwJP80AC+XyNc+MPBR3pu+whmZtws",
+ "DgsChhbK0rzMKvx5flEDWr9diVpWTcFFBoYerPRvVKCUCzOEEf52cv0fgkX1saHOu4UgiR1C4AUREud6",
+ "dY1F3fPku6/TueFkZljh4GRaKozf6AzngO9AKSQiYt14C//BOdKPtYKjKamiHgp6Cug0fj9AZmtUmZn0",
+ "C5pvKY7mxm6GCpyebwXls2ryOJvpdfJeGFOd3UK7CL9Dp0uayX1tEwzWtVf1E2JsPo4dtdSUtUwnmKsP",
+ "Ak55gQz7aIBgOAWMZhDCl3sXa0/5MgbTU75siTS+JHvZCT1Ob2b/lC+fW8i42Ix5GLsP0vUCGZ4TCdKt",
+ "5gbRs1Sm6qMxF7tpEy3XRGWAR1iPGihTwwaS4NWySOzZjJjHzQuNgZA3L61XAprDxzBWw8KJwteABalH",
+ "3QcW6gPtGwt8XtCc7IH0Z1Elbowl+eYhOvnp6PGDh78/fPytJslC8KnAczReKSLRXWvnQ1KtcnIvenEC",
+ "7SI++rePnEOkPm5sHMlLkZI5LtpDGUeLuRib15B+r421Opph1R7AXhyRaNFm0I7em+8uh4PnZFxOT4hS",
+ "+hL8TvDJ3rlha4YYdPDSu0JoxULWnVJWWzrI9CsHZKkEPijgTcIy43rT66BS3wHn470QVdfGZ9UsGbIY",
+ "zcjGQ7HtNlXTrMKtEitR7sPyQYTgIiqCC8EVT3meaD2P8ojt4p19A9k33HYVzd8NtOgCS6TnBgdYybIO",
+ "E4Vasv7yywx9umQVbtZKMLPeyOrsvH32pY786hZSEJGoJUNAnTXLyUTwOcIogw9B1/iRKKN/0Tk5UXhe",
+ "vJ1M9mMj5TBQxMRD50TqmZB5Q2s/kqScZXKjNcd5AxvItFP1wVkTW86Xpbqhsmg6WbEUzEj7OMvd1i/r",
+ "6kNyxdLAFKZhzEk2rdHqtZq8ujBloLgjI5BqTL2Cx+AReE5yhV9ycVqpuz8KXhZ7Z+fNOfsuB9vFWJ9D",
+ "pr91FmXKpjmpaepTDfsotsbPsqBn3uhg1gDQA7G+otOZCu6X7wS/BhkanSUGKDwwxqVcf9M2Mb3hmWY+",
+ "qpR7UD2rwSqOqOk25IN4zEuFMGI8I7D5pYwrpR1RO/qgpqUQhKlQzwV7BpVoTDR1pbjUqy0LpHhMvlQf",
+ "Jjg1JzQB1MiOMAcfqmHeMtPN8IIgnAuCsxUaE8IQH+tFV1EOsEgsUaF1Z6vWWZW4L7+tAVsInhIpSZZY",
+ "e/ZGeN17Rv6oNciD1cAq/CxIcjTB4npWcL7YCPw5WSULnJdaPf/5V3nvS1mE4grnG7YA3oltRNN8117K",
+ "FWBaR8RNiEJSNtZCcxK0iq2ZTk4U6UL21bHXuf1NMFtEcE0IXBABETXXerTcJNdAlB7+az5Y17KEski0",
+ "GthpftCaq95vhhl3uuGGGfwEOZYq2SRS9Es1u4leasDFY1IEBu7QJ19hqUANRJRlYL81ohDmMbqlnmKw",
+ "ZVAZTNl5G9OT/uouYu1pUy3emSylv5XJsii4UCSLLQ981p1zvSFLPxefBGP7q5/iqJRk08hdCAzGt3i0",
+ "hgD4AyvvobY+7/biIOpAqy+rbbFcg6/C0ToYT9xbAeLDoNoOGKms9sCQG5UNehtznhMMJlOpeFFoDqWS",
+ "kvnvujB4Yt4+Ur9U77ZJ0riBjKaScSLBxWTft5BfGKRL8HXNsEQWDhefAAYvEyLXhlkf60RSlpJk3XmB",
+ "S7B+Kzw4Ox33spgKnJEkIzleRaItzGNkHm9JGG5sIJDKfsAVScbgTYzTSHUmXLzpbrNymErGFG8ET1Cq",
+ "z7m+RlWkZr/efdKMwLQxvmmJ9Y6fBcCI0oEbD5Bl6CkyIsj+BVearCzRwWqsVLriWjqw52e9FgTCuEll",
+ "CGjO/g8i7dxeAdvr/CsiuxZeTb2vZXeY/0G21wRmQ5Q1pE1URHTy5Q2MsYsHdfgi3mGhaEoLuK7+TFZ7",
+ "v703J4jGSqCMKExzkqHggbnJF+H3yIQhN8fc7Tbfy9zaBr9lb40sx0Vm1YE/Jyswm7wzGQ2BtWof5ojI",
+ "qFrgYoYAUBc1r2884StkiVOVr7Riq2ZkhS6IIEiWYxO10nahKV4k4QDxnKnuGa1DPuoOXxshcAJDBcuL",
+ "RR6a29Z6+E4bV64aOuwtq+A8j9g/mye+hYwoBL3ChVDB9a5TnOcrpHzajKOkGpBWQEA0htdn7sgammEF",
+ "6B+8RClmcMMtFfFKGheg+YCyrGfQ6qaf04aqVhgiOZkTc5uHJ/fvNxd+/77dcyrRhFyYkBsGLzbRcf8+",
+ "mOLecalqh2sP1m593I4jQgd8lVrI2ltbk6dsDnKzI/fZyXeNwb2DU58pKS3h6uVfmQE0Tuayz9pDGukX",
+ "4Afj9nLf1UPCWuuGfT+h8zLHah+OSrLAecIXRAiakY2c3E5MOXuxwPlb/9nlcECWJNU0mpIkhSzBnmOR",
+ "U/2NSSzU41BG9QE2iSN9ASLH5qsT89GGm3YVt0znc5JRrEi+QoUgKTFZclpLlX6pI2RSJtIZZlO4AQle",
+ "Tm2osxkHGH4pjSVMlKw1xLaqmFqyBFwYMpqmBm5Ll22plTCC9c226f8wl7UL7EExwqiX0A62p+kPirpM",
+ "h4POi7/G96K6+Bu81VNGd3Um1vTDAGkVND29Z4BPrSu1kRhuoz58mhiux0tTDR2Dsj1xEBRePeyKCz8p",
+ "iyJf7UFJMgMhQQpBJIi00AwozVM+Qa9pKvhRPuVe5smVVGTedt6YT3/vOK7vd7kBc5ZTRpI5ZyRypX8L",
+ "T1/Dw95mRyOGO0YEhWirAZsXnxoSGguoT96HpK+6SUAyzbPf9HTKl1zsy8tuBux9p+jhud4Y1mGn3NW/",
+ "jvM84pI25ocWF5FDHxROBcJS8pSConicyaGNPjdebBPW3kD/O58atYcD3By34XsN0rCMIZ/kBcIozSmY",
+ "+TmTSpSpOmMYLH3BUiPBgs440G0WfuZeiduhI2ZiO9QZwxAo6u1/0cCgCYnYoV4S4qzDspxOiVSNC9aE",
+ "kDNm36IMlYwqmGuuj0tizktBBETsjcybc7xCE00TiqM/iOBoXKr6lWNeSoWkonluHcF6GsQnZwwrlBMs",
+ "FXpN2ekShnNxJO7IMqIuuDj3WBj1Z1xTwoikMolHOv5onkJSicXJzCaYQK6FeewinqvaEAO99lrRiv+5",
+ "+7cnvx0l/8TJH4fJ9/958OHTo8t791s/Prz84Yf/rf/0zeUP9/72H7Htc7DHksEt5MfP7R39+DlcxII8",
+ "kSbsX4JDZk5ZEiXKMKCoQYvoLtTLsAR3r273UzNyxtSSacJb4JxmmhftjXyaYqp1oM0Ra1BZbeMaZjyH",
+ "gC2vQ1dgVSjCqRr89Vr0ueYEawNuwi1v5BhYzij3DqAdOAZXc85YWO2dH1+cogNLCPIOEIsdOigtELnB",
+ "2AzGWpSP3qUwseuMnbHnZAL3Qc6enLEMK3xgTtNBKYl4inPMUjKacvTEJUU+xwqfsZYY6iwgFSQ1BxWk",
+ "YpwCz+NrOTv7DedTfnb2oRWH0Nat7FQhF7XnrG0mc1MmWm/gpUpsEZdEkAssYr4QV+LDZkPD12vhMDoJ",
+ "L40RyxWJseOP+kJZFLJZ7KGNoqLINYoCUpW2XoHeViQV94ljmpnb3FtNA2+4DSoR+MJdeUtJJPo4x8Vv",
+ "lKkPKDkrDw+/gRS8qsTBR8sDNd2uCtL74ttZjKJ534WFG70cgsqTAk9jPpOzs98UwQVQCCgcc7hp5jmC",
+ "z2rpgS4TAIaqFuBzkbfYEgPZ1nm9sNwT85Ur6xVfFDyCTa3nTl9pB4Os+J03cENmPS7VLNEcIboqqY+B",
+ "2ytXYABPtchxEQSSTuECIGe81EsmKJ2R9NxWtiLzQq2Gtc9doIuVxY7hUAk2I5scOKEafylmesCyyLBV",
+ "ZDBbNUvcSJMMAYO+J+dkdcrN56Oe1cGCanRBiRXZdXSBdgNZq8k3PMh2jObm27grlyNqy5FA3qUjiyee",
+ "Ltw33UfbKAB7ONYxoqjV+ehCBBYRRBji70DBDgvV412J9GPLoywlTNEFSUhOp3ScR9j039t+DQerpkpB",
+ "UkIXLqvXDygRnSB9OxobcWxvTAKzKdFCXQtiLnEOQfujqKMftMMZwUKNCVZr7bUsLDPhoAOF/AKSpsFo",
+ "MtRLIEu931SBEYSRC33Bg7u3eccGEo92CqcyayLZjqC6z6sk6dEulwiL8Eg9Oyfv/Z74+4KNTwupE0A2",
+ "z+cah1PBL/RuagC5K90IBV4COVVKPCV9xVHNVdSzJEbNAwSDbNJ+ovoOnzTVmpaO0XMR5vNE4yXKHYh+",
+ "otkDuAEaIY5ubuNCtF6FtyxfOaSOc1CofYCoIR0san42Nt0O2DgbI4JVyqoDrI618OjPsHRHPxsGHH1H",
+ "bfHzlJJZVz/vOIi+w6pdHc+J6SZrHxp7zpggzvQXroqeK53n6uUNhlvVvhsObIpDbO84Ay06IzmZGpyY",
+ "lx2dVfWZqt3UcLydTIDpJbFAvsAYGWgmdg6iL2L3ETIWc9R7hNgpCMAGzzoMjN7w8LCz6TZAMltfCrux",
+ "QXYFf5N4sqCJxtdaMi+01KcdXqvUsRRb3qJSeRohzjAMomyINCdd4FxzUpt4Wg3SqtUGd59GZTYb23Gv",
+ "607U86DZNYJ2stUqjT6zy/pCxdstI34r2GoNY75MTGZ09Go1Xo71mYjmK0Ceduzwmsp5dyQa8yXEFIGE",
+ "MwHuW0PXDZkDLAgDWVIJVA7fdamNBrztAFmvyMeoWQLpWbuaJ7suTXY3YDrU6S6yuxuU0NsTSA0DZlUG",
+ "3Fp0NtpZ6tpWWxOpxO3QV4f1aWoxVtN1OKM72YHRtvG0Xuvup6rcYXdxNHdWb6TIX9sod5W6jObjwtRa",
+ "3KYsY5McakCsweq7phIbRWs9cKmO1wBrMZakGX3b2dVGmyQ5AUtAUtOrk/OYW/rs7DdJQGc4cZ8Fdk7Y",
+ "PcxW94JoOEGmVCpSORdckMvN+37AnKgvW3zSvTpViIle33vOvaJh3LHwYW2ZN74CCF2fUCFVAp6Z6BL0",
+ "Sy8lWNJe6lfjinA93o5K4+rZWg8GiM7JKsloXsZJ2YL083MN0RsvuWQ5BkFJmYk2GkMp/GiA7ha+SYDH",
+ "BHavRdArg6BX+Cbw0+9g6Vc1TEJTXn36r+SINXjhOs4SoeUYMbU3tBOla3htkEvfZrSBEh2EXYzW+Xxa",
+ "5zJzY2+MxnIZ/V1KhBkpupagImI8gZBPpyRzld5sUqipemXr6eWcTatagvr3NeUDR8hU8YMifGvq99nw",
+ "dNIVnF5rJwJdMaLQh5cZgLzKroPagzDJlDBTuWWwfb+RPIq4MDAe3ggsozfL21th89HQ4dNGuHAV02v2",
+ "0G82bE9OcGavVZK49a0/tO3tsqgbdgUd10rErj9gMCBQHFUyUGBaRNPBuXFR0GzZcPyZUUc7kERPda9d",
+ "Cb6BM2BLdrAN+KkHFm/o1XNHS0d43zo7DuCaf6AvmSae2Ubk6rOBU1ttICsFeJNq0cLtevr+otlz7T//",
+ "eqK4wFNiPYKJAelKQ8BytkFDUJJeIkVNgHRGJxMSesLkLl6cGnAtf0fWg7A7SLDtLvN3y7X02SayDbRV",
+ "rWAzQuP0FKGUrpiL07Y/0l08AtuaFzbBxu3gVIwWFPiZrJJfcV7qmxAVsopNtQ7CuljfgiYW85/JCkbe",
+ "GPKpAduwK2CKe0+AQmPeFf9IBlXC78ha9wW4A9e2cIudOorv0p62xrbS6D4alYSq9ZOoL+X6jk0VIqMh",
+ "7bNXJ/GoE322SH1bmoS+aYtotln3Ca4g4VQUojd2EXK+0sbG6DKCc0f4sNjB5XBwtXiPmJy0I27YiXde",
+ "NEd3AaIxjf+/FvS15YbgohB8gfPExsl0KR2CL6zSAa+7sJobvl/FT8Xpi6NX7yz4l8NBmhMsEm/q6FwV",
+ "vFd8NasyLTjWiyFTjt3ado0pLNh8XzI7jKS5gNLrDWtaq9dNFTcVHFQbWTOJR4pv5Js2xMsscU2oFyl8",
+ "pFflkTaBXvXgLrzANHeOXwdtXyu7WW6/7kpRPhEOcOUgsSD678pjSfoHSSDElHcEaEmPXysZbUgq1biE",
+ "ZDiDbYPlJm28fvp++83vTF44O/tt4cCpnDwmesvX6Y8E+Mkdw69bDDDOQKoDuIFtA/LfQnnV+GWQ2eKr",
+ "wK1tFBzeu3L6koua9LSpltEouuvTWvUNx+AxHilwakMDWrrqCBm99uP0o2ZY9++HFHf//hB9zO2DAED4",
+ "fWx/h8vd/ftRb3XU/qj5KJgXGZ6Tez5Zo3MjbtY2wshFPx3maDH3ijvvJkNPoSYczqH7wmLvQlCLz8z+",
+ "kpGc6J9Gfewn4aYbdIfA9DlBJ12pkj4ie256jErEWbMwAKTuatICeWjbihjnf/sIsXIOzvBE5jSNRyKx",
+ "MXBIZuKM9csIXu7t2NZzlLQj2J2VNBhdvyZ38sM2FhLMGkW4jJYnrvA75pYFlIz+uyRBr2EQAQ2Nwd3P",
+ "YNSW1h83etqBm62MB7t0Ib6639KZ+tZZsdb6gZ9736RDRKz51ZZJGOGMLea/JoHCUpQTn5BtN7PxzBsp",
+ "a+3lc31nauubduzTuoG7b222R6fZzOd9dprKZCL4HySuO4DnMlJPxLncKXgF/iAsFjjbZGQ+nKHqol3N",
+ "volA+hs8ukjlygYOt2jfym8XER7nE9tt9JaWjGC/u20ZMl7z3G5C1+05jIapZ/d0MDM4sEGsOjQYcjF4",
+ "mJkTaopt1NLh4uc8zF49MONX59zC3Mr4zfHFGMe6L+lLrIYp2P5atKDiyH3sNkj6ehFmdhQkWPh3qalA",
+ "WBBRubTa9Zt3vJCaaXtfRaubJ1BceOccmgCaXPLIMCW7wAyCG+E7wwHt15KY4BD91QUXUHVUxgMbM5LS",
+ "edRCf3b2W5a2w9EyOqWmz3kpCcITZYtP2oFMp3tDRbbFuC+QYlFzPEGHw+rMut3I6ILCjQzeeGDeGGMJ",
+ "AtoHavhP9PIIUzMJrz/s8fqsZJkgmZpJg1jJkTcagOrpw3PHRF0QwtAhvPfge3QXopglXZB7cQFjlbXB",
+ "kwffD9e18waMQ+f6dUw+Ay7vsivilA2h3mYMzVbtqPF0iYkg5A/SLU/WnC/zaZ/TBW9aEbT5dM0xwxoh",
+ "MZjmG2Ay38L+QnxJAy/MuIyIVIKvEFXx+YnCmmN1pLhrhmjAQCmfz6ma2/BVyeeawqre6GZSNxw0/XO9",
+ "2Rxc7iHEhReRO/5nuG7heUfaJYT6v4EggBCtQ4RNGdmcVkkhrm0uOnblsqFZne9RZ3Cj59JLB30VckQm",
+ "qBCUKTBllWqSfKev7wKnmiGOusBNxt8+ijR9q/dFYtsBfuN4F0QSsYijXnSQvdNy7LfoLuMsmWuOkt2r",
+ "6kwEp7IzgD0edNwVC90x9JW1az1u0kmAZY0AccDNr0SKbM2AVyROv56tKHTrld04rZYiTjC41Dv0y/tX",
+ "VhOZcxFrv1ExAKuVCKIEJQtIeo1vkh7zinsh8l67cBXoP2/InVNLA9XNne7oZSFwdUfuab7Wk9b0f31d",
+ "Fe0Hj7tJJm5YL7mI2GmtxfGGY2W3sxc2HfsmRhGedWCuN9pglDZWOnJQTJKJ/+ZzBKE1QTJ7XjOVPviI",
+ "hL7Hg65//z4Aff/+0KrKHx/WHxv2fv9+/zjeuL1Q/xpBzW6ypllSU38b2+qnPGK9c61FfTCbrZ8SsbBG",
+ "ZZkWqWM7xhDV+zfevN6xnyTKrWOj4wfIoQYeN3HzmfkrbGaVltPNH+otbaPkk/nnQWIHRk/5si8RNcSW",
+ "o6cvAEUdKOlpFYSVtFr2RsM3NsYeBWSrRx2TnOubatiVq3cozVe0Cxo1wzV7UdI8+7XyQjckk8AsnUUj",
+ "3cf6w9/NNSB4IbBgpDPMGMmjX5vb8u/uVh259/+Ldww7pyz+qNkd2sDegLQCqw6Em9KNr3FFVa4nCFFU",
+ "rxLm667kU54hmKdqp1Kxxnab9Vh720jhARh2XiobKg0VHWyXkwnNIbY37g+HNxOBVQdXFZAPPKlGJAut",
+ "pxizhBmdCITpHMS2xPMiJ3AIF0TgKXzKGWl8DmXkYOSgVwqShX4Eb0JFGo5UKRjik0mwDMIUFSRfDVGB",
+ "pTSDHOplkSXMPXjy4PDwsJ+TEfDVY+0Gr27hb6vFPTiAV8wT247MdHHYCvxdoL+sqG6bzW8Tl+0J+++S",
+ "SBVjsfDAZImDh1jLddMP1vcuHqEfoWiaJvRa3wIwirqyz/VCpWWRc5wNoVL16YujV8jMar4RBFAH/Win",
+ "YAGsH5Gok6d/4VZXFK6joFb/cdbX89GrlirxnWJj5R31G1WDW9oIyQLbYIidEXpuzLI+sMdMgqDeuZiT",
+ "LGhMa8wAQBz6P0rhdAb2ztFgrUm5o0VR/77KjgNW7qIgGdd38QIOrpdhWyubzspDxNWMiAsqCRTDIAtS",
+ "ryLpS7Bag7yrKllfrSgZM4Qz2kJ79T27tt0FB5xRfV18RRSyxj5c2fdXlReBzuvbdqA+ga/iyUSNdtaN",
+ "uAfTx2PpOoGM0Gvr7Egx44ym0AEjpoJDfch+btUezULi/k45sGc5cgyjTbR91rzFYmdbbccyLeLaQQ3B",
+ "U73fhnDMn4osbWfCKVHS8kCSDV1Pe+ugo0wS25VN01fIUbmIhH5Fc3V8CMke4+SHAyjx1mFrfamfvbG2",
+ "eShkc04Z2NwsUu1N0DjYcknBz84QVWjKibSrrSeryd/0N6PTJQMQPoxe8SlNT+gUxjChiBopJjS5PdSR",
+ "C1S2gcH63Wf6XdtQwf9cC6kzk7p1f4iyEOn3P9YIvhP9sdgvF0gTINePH462hhjX5h+AXNZkSBYQ+UcK",
+ "kOctsvE99eujvNBXVkNv8AYy6cTRWsaURcB4RZlz+MaLc6VRWQIbA6e54zuZCqzMpaMXxzslOO/I0YFM",
+ "fxMxcNWhmu0hNEpgjW6O7m08XTLb26KDrfgXqtsFZivkDoWm7kApeYZzH6Efae4P2plVxkywcKPdf4yt",
+ "aLaeuHzhGro2Zqf6z6FFy7ZyqqsE6rjMpkQlOMtixfCewlMET12WI1mStPSdyXzya72GfJva7EQpZ7Kc",
+ "r5nLvXDF6TIqsZRkPs4jobfP/UOS+R2G6ljjFfwba8vVvTM2En/rlHQXdp9t1zihnWIf0541TSeSTpP+",
+ "mACZcnV0VFPvRujV93uldJeN/kUkmze4XLhHMf72QguOsHZ4K8bfiBZf2hvi6Tk8d0XKfHnZOlcCUdZq",
+ "PgcRGbB5kS1rAO9ejAK+wHlHGYjQa2Pkq/FkdBWDSDtrnWBlS+opjCqe0MeE0V2UzERgNzxDbfdmV4y1",
+ "CbG+TueJxcdapHd7Gn+u+RVN1FvFUDr9ibu5/Coi2NbnZ/tDtO2lOM952psz2GGO9Efd9YP5fG7L8Uei",
+ "8hZznoVnIYzmIiTO2EzAciS1Ai620WdwtYo+ERfx0Wr2EU80fUupARrtEoYmW9SB54AxU4cTBSZbi1n0",
+ "kubQseq/T96+GXRvZLAD7S219byjJuyujfHpc03ymPIaPtbwAM7yuP1bdpjUoWBV/DTYlsnRBy+NgbAP",
+ "SKZ40zZvv+o7eIsApty0qoo182iXzBlU2+GQH1BDtb2Go4TUEaOKZguoyN3HGD2rV5DvjtqrW2pNR+rT",
+ "cSrW3MjeFJwF1ggaWyTPdHxqNYtqMdDnfZTDFj4uh4PjbCv1KdYga2BGiTHYV3Q6U09znp7/RHBGhGly",
+ "ErtOmhYnc6KvoXJGC7j/FFzSqklxrgez1cVnMNyob2rO6YzYUjWuckFrLBdAvSCpgqbVVRioIKR/nEMR",
+ "X6KGwDkU4ZXPEAoiCMlIoWZrlSUT3F2oWdXLlNjMMyrRmFjXxYKwIaIjMmomq2VVpSqUEzxxRljBuerR",
+ "7NenLQEaQ6Bj9NVqHL1eDWwVogvqLJr+vqP+nWGOfE6ASbS8wLIqZ9Wo7dA7h3wyISlU4V9bE/DvM8KC",
+ "InFDZ7oDWCZBiUDq0wWhj8ReLdoVrOuq860FNWiUdZ2QdlXpOCerOxLVaCjapthn2O5Slh6QY/y4rtNB",
+ "l2vDBkZS6ekJEOTi4G1XgKrx0y6dCYKSmTuC4Whci6eqjOZu0DiNZgcw9KdbTtpZow8U066Sg+2W7903",
+ "5efQYV/aoFLsa+CH9iR03O4RfWFr6EP1R+8tdNX0iXS/uaqxZpacntu2OYAw45u9wCJzb+yldp+RmzQO",
+ "9MTPTKvEqHaUz7ZxOSZDMc25VoCSrsTQeqaSD+G9I02sdVVJDaCeECFI5n2COZckUdylWW1RkdSmT67B",
+ "noky3wlvjYj+LVKGzYo6Gzu8r7pbQI9KDI0csA0+D7GCBJljDb0IOk7EzaCbduiZee4Knbieg+vNq114",
+ "9+dic9tul3pHZQvz4emaIKscbM29atVRdrDMUsaISJwTt9lvgtVrd0Kx56xMjaoSnk1vve5dC20NN4sa",
+ "NdP2KhtXqKAqxzlZHRizj2uF7nY8BNrokAb0oMp1gyj2aquWMbinewHv89YULTjPkw7P4HG7SUbzMJzT",
+ "9JxAtVifmaK14Dv1Y6MnQXfBIeVjRi5mK9cCoigII9m9EUJHzGQHuvCRelvUxuTsjlo3/xJmzUrT9sZa",
+ "oEdnLJ5mBe1nxBW5nxtmDc/r4k2SaH55xfnNIDvMrpasK0buAvrU1JsXj/qaN9rxHQ0VKiA/A0VMgTox",
+ "juBnwBIi9ygE1VmCMkIQH4CRdSAjmfNYFP4uFWT0UHFMhZMBQIqwHtfVCgo7eBQBNshuQ6lY+9gVQ+UT",
+ "JEgVm7FrVVhbaNUwcdllGmnO7Gepc8YJFyScEeJMTfVon9kGxZfhP2OqBBarXWq31lEVM0N1YnljtKQP",
+ "lKwWUgVLtnGY5/wiAbaW+JZPMXOAfk/WxbZrnlp9p4/6mARhl1haFXGFZjhDKReCpOEX8RRvA9WcC5Lk",
+ "HKIwY4EdE6UvCXPI62Qo51PEi5RnxHRni1NQ11wlYxh0LxKEskVRYGgHSgaYbwI67jmllr7GPZuAvrax",
+ "+4fb/FP9jSlfUdXkM4tOTIhAR34BkbYqnMWQebkNr6kfBxWZmkbZuIo8oUugGyJiR36ClCjJENk3jEIS",
+ "khAcfCwImlMpDSieli5onkP1CLoMAhp8PFActR268zHEQS8oBLzVK4kYlbrQ0tGXXwl5wElYkQ2pmeDl",
+ "dBY0LfBwuqu7KO3FPhzlF1lCTCKkiOopHqE5l8pei81I1ZKrENC7KWdK8DyvG/KMnj+1Tt/XeHmUpuoV",
+ "5+djnJ7fg0s448qvNBu6kgrN2N1qJtEoDNnvpqCWLAHykJtrv5v3IKrV0nNv3tngfi3HwyZLfgDmh83M",
+ "dbNf46i9sOa66nw2fhc6YggrPqdp/Lh9XdGvnTGrMe4VrbRoWiObKjTwGvCBUI75cCbgnm00E4ajvV2P",
+ "kOURNqwDOJH+L6jxzXHRhFge1CFD23zHKlhJ2qkGNgAASE0hBFUK0085VNI8w+FTUzgFglKagPYUOBD7",
+ "dzXY9Ah7B0qRKwHVikb2AN41FoyhqYhpIpvHfOme36tKZu4E/OV6Kq8xj66gypOKtIQJq3SFrDo4Qrwr",
+ "wtoIxFMogjHuG4fo++P3FP4BAN2RiTUYesUnbgvGBNOcZEmsdfKxt4ENg+u6zbEMRndNJg0nT3Hp2hPr",
+ "sUtBbGElo/2LujuxwJqUuH+9bRFnGVkSk6P1BxHcNBceBu4skpveww2LAi+SnCxILWDTVnsqQQulC+K+",
+ "lf5jlBFSgMe3aWiLRSKGrQsb1he79iSIZeuD3ag5xiDW7BTaYGuJWoaWLDHHRPY9ShqiBc1KXMOf3Fbl",
+ "qNsS9VGOoKp1fUjcFbPvNL+YEd67AY7c9zFVxmHiQz8+tDULiqNuHQPaGJlcyq5Tz+KByWEpM+8ogtky",
+ "79c2JF7xDVngC9Zt1WyTfHUT67lPlLMAsS+WJAWtxl6FSGYvQx2eE1sDCaidEZKZC4P+JGLNnxGGGA8a",
+ "MV9g6W8xVVVX94OZGF6izF60d/DRV/HDV99ZBIMh2Si2GO+b6sn6ajb+z3IS1x7EzvFiNCKJTeVdYxpz",
+ "1G2vHfACL/MMMb2fWveHxsVWilkuPkTj0g2U5/zCdFYOr6jPifPnGupzLiarllMvll2c9NAWHG5aQWiQ",
+ "ITLHK8QF/KMvpP8ucU4nK+AzBnz3GZIzrEnIOpBNFIWNu9YTr1evhg4wZ4jhbiqzbtp3zGC4lR4lAFoL",
+ "ctdLjqM5PifhNkCAiOGfqdKMU5ZjMGpokd3YzjYW7OJdeaY5zkIjABSaXdW4gyt4rr/+/6q01XAqV/+x",
+ "yHHq+mjbjnh1PgOt9h1xqRmZr09zbvM1RwK+fX9FtMKVych2sKZuybpiOT9dHbtqYLf6krealV1pGT2N",
+ "wo3GS2sSxHstZd+7sJ8cztaSwv7DmxYXtmO+md2JVojuWkYf8L+gXamFV7Qy2+Jt3cP1mA7uN7ALtUI8",
+ "EViNGXzMl4kgE7kpkMbYwcd8WQEsve2WslQQLE3c0fFbe22tCiBTpq/RJmrXu1X9KBmZUFaxWsqKUkVu",
+ "QVAHma0ChIXeBEBrh2+uS8fQqugC528XRAiadW2cPj2mX3HYOch5UOy3EQOIl8jtAaisboCQT13Z58PX",
+ "tPg3XQ9N7KxUmGVYZOHrlKGUCK01oAu8kru7qrzXYZOzCge6UL1aSOC2AtI2gOQr622+oiPJA4j36FHq",
+ "4QmCIO2IF8gYhhTvcPy0YfgqPEFzvExyPoWs344DYetcg+vQXCA5AyO60e76rdvNI+kfZP000IrEMiLF",
+ "YdY+U6w/929hK+ES+gujau3JNxbOZhq2iXQ2B9MhlU2r9AxDLO3zGMuct4WZwux5p6q6MiWO9kiwidGQ",
+ "6JZVvWMXIb7Cll0ITej9O2jWQzhi+fnGrpCAvUGuScAgssorwKmNEGsb4lqGCoOUoa1usKWdzlj3nVzq",
+ "AA8MKdKe9fq0PkBHj7NN29H19QySghdJ2ie21XQryqyTwUJah7GDPgIXQse6fdyN9P27ajXRao28tu28",
+ "2tlIbJOvrEjXmQy6jEwdHL3uwOAT4GVwhI1pDXKtvClm6C7nztldN6J5JoEwEiQtBRiZL/BqczfKjurz",
+ "Jz8dPX7w8PeHj79F+gWU0SmRVU+DRjfHKjSRsqbV6GaDEVvLU/FNcNVCDOKc99KlvflNsWfNcFtZFSNu",
+ "9bLcxjodEQCx5Nx2i7yd9grGqdIivqztii1y7zsWQ8H175ngeR7vKeP1qoj7JbZbgQNG30AKIiSVSjPC",
+ "uv+UqiooW87AuAhVwxemNhRnKXHWZ0sFVHXEcsUW0hXTC/wMajFYnxMiyyK3vMr4idaty97TjH0PlEYI",
+ "txkTVPDCqvZ0gmIQQc6WKIm3q1uzKdjTgzBdz2xNwG6MEG3we5z0jpi9CfMJWs/t6/3BVZzT602MqBfu",
+ "UO5Aml3eje46I7twksox8MXwj0jhlL1xDb/c6+AV0fvBmqzwo1bUhC8a0gu0doGMCHkAAB350LWk1SDJ",
+ "LqhNLoyPAbwRzv3cVD9eV27pjZkpAIn7YAN4YS5z9Z5PprDgfObC3q89UoKlfOiihNryN6VHO9brBUmw",
+ "RdZoohSRhi3xtloYJMTLZz7PvONW0kpHF5wrpG+meR5JYzd2HDhTIeHoK4FY4PzmucZLKqQ6AnyQ7H13",
+ "4laYthwi2aBS7r0g5yvcC6wgRflGoGLvILf+70TvbFQ62lms478lA8EkhHMT7T3xHnDC0AWMaQK7HnyL",
+ "xrbdTyFISmUzoODCqTQ+35YIOrHxtWSpmrm/V24T9CtXVzgOExcPhN4ETjYfOWBhro76Z2ZOHRwgelpi",
+ "pNoilAj+Yrwu7PS+QexcsTXMbqWcgsKNW5Zyavew77s8WAcIr1KS9jp7S/0abiMCv1pb31plvTvMnJ39",
+ "psZ9CorFu8Hoz6HG2V7awly9KcyNFDgzqLRjWEiihFWp3Juq1zTiJYM6DfVd1Op+RwP5mUG/Hg0uBZOS",
+ "mfF8A1TIFXdsnU+GPoqBM/3ZE3TG7iM5w+5uYf98+PjbwXBAWDnXi6+eD4YD+/RD7KaWLaN5pVUhnVaM",
+ "qO0mcEeiAq/6JLNvLJ0TxW9VKejmVRqp6Dh+p/tJ7xlcXG0CwjEDVg/sxUhQWz/ntgDQWmJoHFZ/YgxJ",
+ "VuWB/FZsqhT0a1dZfFP6vaPbR4P7ljTfGCRXa8RyORxMTZEy6E7yu+1Vd7Pb7iDoqBdol36VMmAGMZG1",
+ "1iYPpgqKuvVoyGI/i3TIgMzrtBRUrU40/p3Znf5+HisG9aMvz2RrfnkPvNV9FT8nzMWYVcWcSum06x85",
+ "zkH7NIEBTOucPB+hF6ZDiBWLP9wZ/xf55rtH2eE3D/5r/N3h48OUPHr8/eEh/v4RfvD9Nw/Iw+8ePzok",
+ "Dybffj9+mD189HD86OGjbx9/n37z6MH40bff/9cdTekaZAOo6/zzZPB/k6N8ypOjd8fJqQa2wgku6M9E",
+ "7w1Y2CZQoBCQmoKIJXNM88ET99P/7wTlKOXzanj368D2gxzMlCrkk4ODi4uLUfjJwRRqoCSKl+nswM0D",
+ "tSxr95V3xz4vyMT+wY5WPifYVF/fTz97/+LkFB29Ox5VBDN4MjgcHY4eQD3FgjBc0MGTwTfwE5yeGez7",
+ "AVTRPpC2Gc+BTx29HLaeFYVp1aMfTX0ZUP3XjOAcWKT+Y06UoKl7JAjOVvb/8gJPp0SMIGPM/LR4eODu",
+ "HgefbF2ZSw1YNNjAdGUJem+44OeiHOc01RqqrZYFXieT1CPDhvjWH1fKIRrjHLOUuMQBlkFYpCm7orUc",
+ "j/DjTCPafH9cMTtAo4tGGTz5LWaVbYE3ckSqdyCgIV9XqeIRYIMfGB4JrnHP8TQXO0y+//Dp8XeX0WDs",
+ "dlxWFdC49mm0FJkk0Nf5I87zj8YCTpYQOt8Inht2BT0Oq3I98EGFtiEYm/3T4PPqnXpzko+MM/LRo/Hf",
+ "JRGrCo8WsEGIN6fA4TzXL3JGInpbe+nPqmTBC9tmPIxTDiKY//vk7RvEBbK2sHc4PfeJki5ptkoUDnNm",
+ "9ZddS7ECL7YSm3E5l9OiXn7fr+YD9FEGQOGYPzw8dLzN2gkCXB/Y8xjM1KvZkHFn+lEcODsM1OaB5tF7",
+ "Xzxb4MKc4yOX7qBVfutQNi+NNHU/2uNC6yW+r7zc5nCtRT/FGRK2EgMs5cFXu5RjZkLXtSwzMvdyOHj8",
+ "Fe/NMdO8F+cI3jRCG85xW0j9ws4Zv2DuTa1vlfM5FivQppQXCs0ueXgqIYoDZIXhVEHxTTYdfLjslJgH",
+ "YYz2wadaybrsSvLUuHVr7SQ3i9gOOQBjmSRa+8Pdo6KAEPUT//yoKN5p3i8hcIlQ4LxkSaWS90box/Dr",
+ "mjfWQGKcsbUcJosjV0CzHpwTtA6PyvtafZW/lOg/qpsuaUaYohNqKgjH1lGjubXL6d2qLRLrv/7xrRAP",
+ "qaaVVxnUpts2h8Q38bDKWmL7zvYcwxzpPfZZvlodUwNEtL76Rjlyi9bt0dql4AVL8bpe1Qf6ZoSKqxvv",
+ "ZWBN2F2jyPnK1dXXONckFCy30cvv+PmtGvuXUmN9Deep0SuLYg+KrUuC2/TKwSdbZHgf+i6YKXppuqEF",
+ "JPg2yFO62+A490boqPnObmzFVm7eqMOapLy/nPZqSkpv1Fst1exXY63lQW564VZr7VavwlTebTJrazqV",
+ "/r3Xx39eNfUWj1vppXoRmzXSHZh/S9u0oubahMKfUsu0SLvVL//S+qVv/HAlDTNMcjiw1WoCffNKhtWm",
+ "4ZQqr0fW+4UETA/KUkHdFnOEh1VCl2YxJlPF5qjIobv6gnPd3IrNZg1bF+O2gvgjCW/gT1fHz/vohl+b",
+ "VfBanWHVl1FxEt/k62bKUdfS+5txLfVjco8OH90cBOEuvOEKvXSh449vcg/2yRvjZLUtL1zH2g7GfLmJ",
+ "vbEGf/MVUfXhrzE7XxN7GDzXb5vgn7tQJGKMJfn2kbu/3Buhp/bVquyUDZeccs3xXHIxFlPzkWaaGhno",
+ "jvvzCYx/Z4ReQsq8kkOIWIZcPHiRMvXkwcNvHtlXBL4wAcHN98bfPnpy9MMP9rVCUKYgXMRce1qvSyWe",
+ "zEiec/uBFTbtcfWDJ//3H/8cjUZ3NvJnvny6eqP56p+QSQ9jtXo9JXVt+1e+27HLNzMb3L0FNxnr8ZQv",
+ "o+KEL2/F2WcTZxr7fwoxNq6Tkb0ae+NxrRveHsWaOSbbCLahFWSQQOil0gi94bY/apljYWqTQfF3iaYl",
+ "FpgpQrKRo1TI/pamBGuaUyhbI5AkYkFEIqnvv1AK4gtoFYIsIGOrKk9eg2CzxICEjT+/tHiNl0FA/dgr",
+ "Dopb3IE5dI6XCPplKSSJGpoiokv0ww/ocFhdzPJcD5B4DMe49BwvBxGmvCldI/brfg2mnr77VsF7bvHI",
+ "xeaYdRi7jxmt0tx8MebqmvRXFxZf7a3DHAy7sXti1lv77irfXGhMse1D15pRjC6poHWALIsiX1VF47Vi",
+ "6bS2OFfVM/S1kHwtnqdrtYyAsyB2G2/u1S1HuLWGXIkvNQlqSx4EyZfy4BMYKEIG1GICkJi4kQFYx5ZR",
+ "RzrOvrA56fs7+L4ewppnnZWefAexsC4GugvpFFCrDSq0rqDko4CSqnQCpaHuuRb0tpsClNypIvLjypMZ",
+ "PtGTxpSooCPOrWe8W9EDWmz3Twg3MMOmBE+fzqVBfQXw+RIROYpv4T84D0nANwxz9YyBmDw92J70xgRi",
+ "EmJtQpErDFLgWmf+zVA+qyZv66iAln24zG8RvB2CWyz+ha13ZHiKXcSfIUnHXegT9IZXxWUMv/9TuqSv",
+ "Uz+57gW94YyY2At9GTC0eOtm98pTJfRdLTJzpas6d+6qSB24eg9rtamfTCWCr1SjugaR/lO0SkZN6mjE",
+ "jjYWTKpG68OsXRkOXFMBR5/zbvZZ+OsXeGH7HBzsZliOqddj+Y5VE9h+mRCU+zPEfOCL5XRxpFf65UBP",
+ "e2dLpvxFudM6gomjKkI4vhQRjpReHP0Fj/Mz21ZNucJUptykpCwlSPI5gVuFVuNt1woD4Xc3B6Gic5Ih",
+ "XkLNzCAj/TMznMeH39zc9CdELGhK0CmZF1xgQfMV+oX59mlXYYASYbvnoQ29fTgQZeAWrJclTcPah1fg",
+ "i3y6xg1qrf1VYWVbnoqXighTUrfRJZO2+HbMig4M45We+lblg6/dNvRtDfEM5zngb5OvDgbuFfGe52aD",
+ "yZwqVTWaCiUweoHTmd/sYWV7882EXUeSYaOGNYxsO8uach2S6I1XBAWrCSwcRJAJhy6RRBBnXJyXuaJF",
+ "Xv/Gd9uG7oORSDRDrGEFvOPnbnXGrc4n1dBNgnb9S+zgIz23fQQzM24WhwUBZh4aQEOb5KgGtOnD6UL5",
+ "g+6JtgekLY9MRaNedRX1VBQEi+pjwzDuFoIkdgiBF0RIDKe3sah7t+r8l6HOL22DhC9EmY+6eq/K/HeX",
+ "TbWI/E9qSbPLzbp7q+jon8dNc9ooGnr8PMya4r7qntMrOhajEbllouZ/DnpUyrruCqxRF1JV3bLtiulX",
+ "qvXWu9SbobTO1rp7XldJ35sWPVXmWHjQEW+qBJ9VBKnPJYKShgyqo+XzSSRogTMMwncKwRVPeW6i9sqi",
+ "4EL5gsBy1OsiRrrEXO0e1l2L+gqibEkzudEIfgpv3V6JKiv4qcNbzAxeP79yTXvvjRGN1Vx97kqnvEDm",
+ "vtMA4bMyulsdO8bgGhbzr91grjpJb8/28xSrdFYWB5/gP1CF+LJKh4WuTvJALdkB9PE9+LQ2ZhN4bE4y",
+ "TYzwac3k1eoKHI28fAWfV82nXnIR6CM/6u82s8460oZNLcD0JIbgzghTvR61+Vbb7HItNDb86g71yIit",
+ "8+qrPQSdTD3tBi3NXAEH08c4QsK3ASBf1oIqf8uEsgzhYBsbl2ouKkZwzT6X617053Dh3HzUy+Ov+Jy9",
+ "4Qodz4uczAlTJLtaBDRqcjgnPdaK2+0UAyv622HSbZkfSnyXKeJ1kY0C/k9kubuV8V+UjH/m3VIhgd5K",
+ "7K9HYgt3CG+F85cvnL/5aldzjdEfPYX1Dl60uoCu7uhbiuqWmmCtWw2TwjoHHFzKm6uUL7lwrThv5fuf",
+ "Lh/J7HHvWJY+Vp1N1ls75T6Sfb4o6PvZJvI8Yp3oOsJDHy5DoXwiTym0XDrO5NDG5RiDhj3ftyrRF60S",
+ "BXt9qxHdmiu+MnNFh/5jLQV53kcF2VY1Wsx5Rpx3lk8mtpJxl15U76mpyVMqPC+Q+XLUGdt6SufkRL/5",
+ "1kyxVxFbgd1wSzbA08iSJOUsk7t2j7VT7SqcwGPVDdWNu0j9tjhYbAmg0c50/D6obNgiD9TcEQkNUl0t",
+ "Z4uMjCyQpsrRHmj54JP5F+xyBZeR1Zw4qm5tzF27LaY4tRm3BiB6B5qpqXLtvuITdGhqVJcMEo5n1PZR",
+ "hxhBJVZae3UF8ATBOUpriYYejvZxOuk8TmtvDqex1XWsKX6t4NWxvfK9YqeyT4108J9v/Kg8w8wejjYq",
+ "FUcYMTLFii6IizIY3VZV2lkY2ppGa1jlEOEsM+e22gSyIGKFZDmWWlVi9bSRO7J+srZgLWRZEEG1hMd5",
+ "5fM3t4wDUzJpXSzTiXnjijKvwbVMoSZRb7buBLMt48Qn6DVNBT/Kp9xHI8uVVGTe6khuP/29ozGBs1Bs",
+ "ZTHgLKeMJHPOYi2038LT1/CwN8uAMlVdI57qh1sN2BDvdSQ0FlCfvI8KcNVN+kJYyJUCdBqrFaTgQt+w",
+ "x6awjjlEW55Hd/JWLG0fxxVLA2ecfRgMFPbYrv184OLFax23o29+qv1p67PZN+WsVBm/CGYBO4SJy+xT",
+ "TQkuALcptp1EHOAndub800iX5Ophd6Pkv2jSrXUphSmVNmVtQYRsXDJvM2//VJm3vfd9Ky6thyzlJk5X",
+ "yv0qRm94Rsy4VbalPvqxfimMZwRJB0RDH/JhnvEuTU6uVe8ZvFGJxgTqa+JyOlOoLJDi7bjHYTBBglPD",
+ "mhNzH4tPGJTxNbc2mG6GFwThXBCc6Ts0YYiP9aIrCQuLxBIqMrvkNRvM2l/tCoAtBE+JlCRLXNOYTfC6",
+ "90y6nFqDPFgNrMLPgiRHEyyuZwXni43An5NVArd3ie7+/Ku896Uswuii67fA1HSNbEQzKbe9lCvAtI6I",
+ "mxCFpGxygM1JgOw4Pi9yYvPjIsi+OvY6t78JZosIrgmBCyLohF7z0XKTXANReviv+WBdyxLKItF6Rhvu",
+ "Z+bpKZ2Dxsgw485gu2EGP0GOpUo2iRT9UrhoqZcacPGYFIGBO+7sr7BUoI8jyjKoWmhEIcxjbg56im1v",
+ "9TClVg7MVSoy6a/mYWzaVIt5JkuJ7Agud41kseUxslwz1xuy9HNBCRA3tk+OM5bWTSN3ITAY3+IxaNmD",
+ "sPINGgnSw0UWB3ZgbM0/W2G5Bl+Fo3Uwnri3AsSH4RcdMFJZ7YEhN+gFENKbLz07HEjFi0JzKJWUzH/X",
+ "hcET8/aR+qV6t02SpriD0VQyTmSY02ghvzBIl2BDn2GJLBxojs9t2uPUdtxtw6yPdQKFhJJ15wWs6vqt",
+ "8ODsdNzLYipwRpKM5Dhip/rFPEbm8ZaE4cYGAnGEniy4IskYaoTEaaQ6E2IXU56flcNUMqZ4I3iCUn3O",
+ "J1wEpGa/3n3SjMC0Mb5pifWOnwXAiNKBGw+QZeipw4iox9BkZYkOVmOl0hXX0oE9P+u1IBDGTSoLUHP2",
+ "fxBp5/YK2F7nXxHZtfBq6n0tu2nTDWV7TWA2RFlD2kRFRCdf3sAYu3hQzIr8VbqNmkF015j3WbeiB3f4",
+ "0S72iYMLTFUy4cLcWxI8UURszOb4O6YuLsM6mRS3NYgQjGB1BDsOSK2w6Z/lWAYEZOWfJhFb60kLZYwe",
+ "oDllpTJPeKmGpqi1IDid6TtSaF43I0FraFtGSZApFlkOvYEnXhHgwpRlUg1lBoCOpMjWjTZ63S+5+MoL",
+ "/n+4tTjdWpxuLU63Fqdbi9OtxenW4nRrcbq1ON1anG4tTrcWp1uL063F6a9qcfpcldkSp6G52qeMs6QZ",
+ "TH0bS/2nKvTvZa8zgIH16QJTYIFBYZRuu9QWhj5FcA44oDnpzgMxQeenL45eIclLkRKUaggpQ0WO9aWL",
+ "LJVveD7Gknz7yGUqG10Az9F4pdmKVhj0C988RCc/HbnavTPbSaj+7t0jE2qKpFrl5J5tZkdYZhRy19WO",
+ "MI1029QOO/HjGqPbNvE0hxwaiV7A28/JguS8IMIUVIWWlm2L3inB+TOLmw0Gvb/ryW2o/Uc92sdhzahp",
+ "0TbHhbsWubViibBJ2EbPgxTujxOcS/KxK4vbjDfHxfpumB8M9yVSPeXZqnFC9K4dwAbWz4Zv7DemDItV",
+ "pDBdO1mqSRqKa3ZlCattxLzca5LbLNr/qk1mmygsdjMxjQjio3dReWycasNaQ5k8/0mDTgaxFPVQlM5M",
+ "GzQLYK9apJBQZfYEvTfffd7KowCRPWIVM/9iAo3rb3qmAe/qW5FlPV9rLpFDfPT0wtkfasLOypQgqiSy",
+ "FNdDvGiNUI80JSyxDCgZ82yV1NjXoCaFMiqxlGQ+3iyJQv4JJ84LH/1kvZz6PGLkebC4dTw5JJplYhlw",
+ "B3deKdKbN3tswYiWPQcYv24W3cVGQxCQ5U8x21qD923L9KppVreM75bxBaexoRFQZpv4NJnI6BoZn1iJ",
+ "knXzvBdLkpYauPAk3wW/B3hVyVLVnOgZGZfTqb4ttN2s0MgIxqOcfSZWaJbblwtuR0Fm8PcuDeaqNS6a",
+ "w7W5S1B24q4rBnsPtgOzFXiE5gVmK70bkEeSSDovc4ND0wp8v4zW9C2IVbWvrJNdFvx3zigZGKOtqK3/",
+ "btCCLrBEZn9JhkqW2WTFVjn9JetfJskMfbpkFZteWxLJrDeyOjtvHxHhdrlelEKigohELZk5ULXDBN4x",
+ "jMzJ/azl+2/Fxs2JDVPSgnQw2HZHkIoh7El6iICvgfgIul5VObW1Xli4nglcewYWje4stLCFj3lzr7FB",
+ "reHrIUKVucX6m0leIIzSnII3mjOpRJmqM4bBIRUsbNQOH3I27G7e98y9EneXRryZdqgzhiGIzLupojxw",
+ "QiLukpeEOBYry+mUSM1HQwKaEHLG7FuUoZLpWxifoDlNBU9MVrw+X1p3GZk353iFJlAQiaM/iOBorKV+",
+ "sOvGliwVzXMbr6SnQXxyxrBCOcFSoddUc2A9nCu84kMKibrg4txjYdTfrT8ljEgqk7i15kfzFHqKW5w4",
+ "qyBYOM3jqr9O8xpUdVT4n7t/e/LbUfJPnPxxmHz/nwcfPj26vHe/9ePDyx9++N/6T99c/nDvb/8R2z4H",
+ "O806IT9+DoGJUBU+pzJsi9mE/UuIG5hTlkSJ8nRGkI0rbNIiugslJy3B3au7p9SMnDEtLRVHICGw2iP5",
+ "NN1IrQNtjliDymob1/A2OQT0ukPuhVWhCKe69d38iVLFAzpwnlPYeNMXpLH3W/ppanKbQIfXLqluntou",
+ "mB0v2VtIzdLWqKdl3zitgbzWCfL1l7bd/4XUoXFvV9L2gG12VW/+CXhzGz5EOOdsamq76isqh32irCgV",
+ "ZAlcpxWQLHCe8AURgmZE9lwp5ezFAudv/WeXwwFZkjRRAqckMWaJvlg71d8YOtXjUEYVxXkCV/O+AJFj",
+ "89WJ+WiD/D71IWp0PicZxYrkK1QIkpLM1D2kElVGgZEpxILSGWZTEPWCl9OZec2Mc0EE8X1S9T28OcS2",
+ "uoBassTUzGyDf2RbcYcFxwlOZ5FeWCD7LrAHhWS1Nns9t6dWEbnLCDAcdCryGt+LKgzR4K3OgXbVOmr6",
+ "Q4C0Cpp91JW+PSS3h+SvdkhiFWIBn5OGScUgMdzGa7a9XXeR5Bs05X2WCuq3DUr+7A1KHFuSCCOBa3ec",
+ "eM9MLBFV6ALKq40J0vKuBBeCbURqjQSQ7hkcdVs4WNq2pekMU2Zrc/lkFYBDX7nnc6qU6+N9LdZXw8zA",
+ "7KrRQdJSULWCWxEu6O/nRP//g75WSCIW7sJUinzwZDBTqnhycJDzFOczLtUB9AmpnsnGww8e/k/urlMI",
+ "utD3t0sAmws6pUzL6As8nRJR2TkHD0eHg8v/FwAA//9Jl/HT2MkBAA==",
}
// 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 db801f0c31..6110d048f0 100644
--- a/daemon/algod/api/server/v2/generated/participating/private/routes.go
+++ b/daemon/algod/api/server/v2/generated/participating/private/routes.go
@@ -249,235 +249,235 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "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",
- "vwEAAP//CeiNZR0iAQA=",
+ "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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 59328e33b2..2ba1687f18 100644
--- a/daemon/algod/api/server/v2/generated/participating/public/routes.go
+++ b/daemon/algod/api/server/v2/generated/participating/public/routes.go
@@ -178,237 +178,238 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{
- "H4sIAAAAAAAC/+y9e3Mbt5Io/lXw426VYy1JyY6TPfGvUnuVOA9t7NgVKdmH5ZuAM00SR0NgDoChyPj6",
- "u99C4zGYGQw5lGg72Zu/bHHwaDQajUY/344ysSoFB67V6OnbUUklXYEGiX/RPJeg8L85qEyyUjPBR09H",
- "55zQLBMV16SsZgXLyA1sp6PxiJmvJdXL0XjE6QpGT8Mg45GEf1RMQj56qmUF45HKlrCidlqtQZq+r88n",
- "/302+eLN28/+9m40HultacZQWjK+GI1Hm8lCTNyPM6pYpqbnbvx3+77SsixYRs0SJixPL6puQlgOXLM5",
- "A9m3sOZ4u9a3YpytqtXo6VlYEuMaFiB71lSWFzyHTd+ios9UKdC96zEfB6zEj3HUNZhBd66i0SCjOluW",
- "gnGdWAnBr8R+Ti4h6r5rEXMhV1S320fkh7T3aPzo7N0/BVJ8NP7s0zQx0mIhJOX5JIz7dRiXXNp27w5o",
- "6L+2EfC14HO2qCQocrsEvQRJ9BKIBFUKroCI2d8h04Qp8u+XL38kQpIXoBRdwCua3RDgmcghn5KLOeFC",
- "k1KKNcshH5Mc5rQqtCJaYM9AH/+oQG5r7Dq4YkwCN7TwevR3JfhoPFqpRUmzm9GbNprevRuPCrZiiVW9",
- "oBtDUYRXqxlIIuZmQR4cCbqSvA8gO2IMz06SrBjXnz9p02H964puuuBdyYpnVEMeAagl5YpmpgVCmTNV",
- "FnSLqF3RzZdnYwe4IrQoSAk8Z3xB9IarvqWYuY+2EA6bBKKvlkDMF1LSBUR4npKfFSAl4VctboAH6iCz",
- "LX4qJayZqFTo1LMOnDqxkIgOpKh4ilER/ODQ3MOjbN9jMqifcMR3u78ptnCf2lBfssXVtgQyZ4W5L8nf",
- "K6UDAVcKt30JRJWQGd6bEzOMQb5iC051JeHpNT8xf5EJudSU51Tm5peV/elFVWh2yRbmp8L+9FwsWHbJ",
- "Fj07EGBNnVOF3Vb2HzNe+qjqTfIueS7ETVXGC8ris2Bo5eJZH2XYMftJI80gz4PcgPvjxrraXDzrY6m7",
- "e+hN2MgeIHtxV1LT8Aa2Egy0NJvjP5s5khady99HVrwwvXU5T6HWkL9j1yhQnVv56bwWIn5yn83XTHAN",
- "9iqMxIxTZLZP38aSkxQlSM3soLQsJ4XIaDFRmmoc6Z8lzEdPR/90Wgt6p7a7Oo0mf256XWIncxlLMIxv",
- "QsvygDFeGeERRa2eg274kD3qcyHJ7ZJlS6KXTBHG7Sai3GU4TQFryvV0dNBJfhdzh9cOiHor7CVpt6LF",
- "gHr3gtiGM1BI+07ofaAakiJinCDGCeU5WRRiFn745Lwsa+Ti9/OytKgaEzYnwPA+hw1TWj1EzND6kMXz",
- "XDybku/isW9ZURDBiy2Zgbt3IDdjWr7t+LgTwA1icQ31iA8UwZ0Wcmp2zaPByGXHIEaUKpeiMFfgXjIy",
- "jb93bWMKNL8P6vynp74Y7f10hxK9QypSk/2lfriRT1pE1aUp7GGo6bzd924UZUbZQUvqokbwsekKf2Ea",
- "VmovkUQQRYTmtodKSbdegpqgJNSloJ8VWOIp6YJxhHZsBHJOVvTG7odAvBtCABUkbUtmVry6ZXpZi1wB",
- "9dPO++LPTcipPSdmwykzsjEpmNJGGMLNVGQJBQqcNCgWYiq6E9EMoIUdiwgw30paWjJ3X6wcxzih4f1l",
- "Yb3nTT7wkk3CHKstarwjVHdm5nsZbhISq3BowvBVIbKb76laHuHwz/xY3WOB05Al0BwkWVK1TJypFm3X",
- "ow2hb9MQaZbMoqmmYYnPxUIdYYmFOISrleXXtCjM1F1u1lotDjzoIBcFMY0JrJg2D2DG8QQs2Bq4ZT1T",
- "8g3NlkaYIBktinGtlxDlpIA1FERIwjgHOSZ6SXV9+HFk/1DCc6TA8EENJFqN02lMydUSJMyFxIeqBLKi",
- "eDmtzPOoLJp9AnNVdAUt2QkvS1FpA2P0crl45lcHa+DIk8LQCH5YIz7448GnZm73CWfmwi6OSkBFC+NZ",
- "UeU1/gK/aABtWtdXLa+nEDJHRQ/V5jcmSSakHcJe/m5y8x+gsu5sqfOTUsLEDSHpGqSihVlda1EPA/ke",
- "63TuOZk51TQ6mY4K0y86yzmwHwqFIBPajZf4H1oQ89kIOIaSauphKKegTBP2A+9sgyo7k2lg+JYWZGX1",
- "ZqSk2c1BUH5dT55mM4NO3jdWVee20C0i7NDVhuXqWNuEg/XtVfOEWJ2PZ0cdMWUn04nmGoKAK1ESyz5a",
- "IFhOgaNZhIjN0a+1r8QmBdNXYtO50sQGjrITZpzBzP4rsXnmIBNyP+Zx7CFINwvkdAUKb7eGGcTMUquq",
- "z2dC3k2a6JgmagU8oWbUSJgat5CETaty4s5mQj1uG7QGIkG9tFsIaA+fwlgDC5eavgcsKDPqMbDQHOjY",
- "WBCrkhVwBNJfJoW4GVXw6WNy+f35Z48e//r4s88NSZZSLCRdkdlWgyKfOD0fUXpbwMPkwwmli/Tonz/x",
- "BpHmuKlxlKhkBitadoeyhhb7MLbNiGnXxVoTzbjqAOAgjgjmarNoJz/Zfu/Go2cwqxaXoLV5BL+SYn50",
- "btiZIQUdNnpVSiNYqKZRyklLp7lpcgobLelpiS2B59b0ZtbBlHkDrmZHIaq+jc/rWXLiMJrD3kNx6DbV",
- "02zjrZJbWR1D8wFSCpm8gksptMhEMTFyHhMJ3cUr14K4Fn67yvbvFlpySxUxc6MBrOJ5j4pCb/jw+8sO",
- "fbXhNW523mB2vYnVuXmH7EsT+fUrpAQ50RtOkDobmpO5FCtCSY4dUdb4DrSVv9gKLjVdlS/n8+PoSAUO",
- "lFDxsBUoMxOxLYz0oyATPFd7tTneGthCpptqCM7a2PK2LN0PlUPT5ZZnqEY6xlnu1345Ux9RW55FqjAD",
- "YwH5okGr71Xl1YcpC8UDlYDUYOo5fkaLwDMoNP1WyKta3P1Oiqo8Ojtvzzl0OdQtxtkcctPXa5QZXxTQ",
- "kNQXBvZpao0fZUFfB6WDXQNCj8T6nC2WOnpfvpLiPdyhyVlSgOIHq1wqTJ+uiulHkRvmoyt1BNGzHqzm",
- "iIZuYz5IZ6LShBIucsDNr1RaKO3x2jEHNaukBK5jORf1GUyRGRjqymhlVluVRIvU/VJ3nNDMntAJokb1",
- "uDkEVw3byk63pGsgtJBA8y2ZAXAiZmbRtZcDLpIqUhrZ2Yl1TiQeym8bwJZSZKAU5BOnz94Lr29n7x+9",
- "A3m4GlxFmIUoQeZUvp8V3Kz3An8D28maFpURz3/4RT38oyxCC02LPVuAbVIb0VbfdZdyD5h2EXEbopiU",
- "rbbQngQjYhumU4CGPmTfH3u9298Gs0ME7wmBa5DoUfNej5af5D0QZYD/PR+s97KEqpwYMbBX/WAkV7Pf",
- "nHLhZcM9M4QJCqr0ZN+VYho19CZmqREXT90iOHCPPPmcKo1iIGE8R/2tvQpxHitbmilGBzqV4ZS9rzEz",
- "6S/+IdadNjPXO1eVCq8yVZWlkBry1PLQZt0714+wCXOJeTR2ePppQSoF+0buQ2A0vsOjUwTgH1QHC7Wz",
- "eXcXh14HRnzZHorlBnw1jnbBeOlbRYiPnWp7YGSq3gNLbky16G0mRAEUVaZKi7I0HEpPKh769WHw0rY+",
- "1z/Xbbskac1AVlLJBSg0Mbn2DvJbi3SFtq4lVcTB4f0TUOFlXeS6MJtjPVGMZzDZdV7wEWxaxQfnTse9",
- "KheS5jDJoaDbhLeF/Uzs5wMJw4+NBFLrD4SGyQytiWkaqc+E9ze926wCp1IpwZvgF5KZc26eUTWpud53",
- "nzQHnDbFNx2xPgizIBhJOvDjIbIsPSVGxLt/LbQhK0d0uBp3K91zLT3YC7O+FwTiuJNaEdCe/b9AubmD",
- "AHbU+beg+hZeT32sZfeo//Fub1yYrausddskr4hevryHMfbxoB5bxCsqNctYic/VH2B79Nd7e4KkrwTJ",
- "QVNWQE6iD/YlX8b9iXVDbo95t9f8IHVrF/yOvjWxHO+Z1QT+BraoNnllIxoibdUx1BGJUc2FSzlBQL3X",
- "vHnxxE1gQzNdbI1gq5ewJbcggahqZr1WuiY0LcpJPEA6Zqp/RmeQT5rDd3oIXOJQ0fJSnof2tbUbvqvW",
- "k6uBDvfKKoUoEvrP9onvICMJwSB3IVIKs+uMFsWW6BA24ympAaS7INAbI8gzD1QDzbgC8l+iIhnl+MKt",
- "NAQhTUiUfFBYNjMYcTPM6VxVawxBASuwr3n8cnLSXvjJidtzpsgcbq3LDceGbXScnKAq7pVQunG4jqDt",
- "NsftInHpoK3SXLLu1dbmKfud3NzIQ3byVWvwYOA0Z0opR7hm+fdmAK2TuRmy9phGhjn44biDzHdNl7DO",
- "unHfL9mqKqg+hqES1rSYiDVIyXLYy8ndxEzwb9a0eBm6vRuPYAOZodEMJhlGCQ4cC65MHxtYaMZhnJkD",
- "bANHhgIEF7bXpe2056Vd+y2z1QpyRjUUW1JKyMBGyRkpVYWlTokNmciWlC/wBSRFtXCuznYcZPiVspow",
- "WfHOEIeKYnrDJ2jCUMkwNTRb+mhLI4QBNS/btv3DPtZuaQDFXkaDLu1oe9r2oKTJdDzqffgbfK/rh7/F",
- "WzNk9K7GxIZ8GCGthmag9QzxaWSlLhLjbTSHzxDD+7HS1EOnoOxOHDmF1x/7/MIvq7IstkcQkuxAREIp",
- "QeGVFqsBlf0q5uQFy6Q4LxYi3HlqqzSsusYb2/XXnuP6011ewIIXjMNkJTgknvQv8esL/DhY7Wiv4Z4R",
- "USA6aMD2w6eBhNYCmpMPIen7bhKSTPvsty2d6lshj2VltwMOflMMsFzvdetwU97Vvk6LImGStuqHDhdR",
- "4+AUziShSomMoaB4kaux8z63Vmzr1t5C/6sQGnWEA9wet2V7jcKwrCIfipJQkhUM1fyCKy2rTF9zipq+",
- "aKkJZ0GvHOhXC3/tm6T10Ak1sRvqmlN0FA36v6Rj0BwSeqhvAbx2WFWLBSjdemDNAa65a8U4qTjTONfK",
- "HJeJPS8lSPTYm9qWK7olc0MTWpDfQQoyq3TzybGqlCZKs6JwhmAzDRHza041KYAqTV4wfrXB4bwfiT+y",
- "HPStkDcBC9PhjGsBHBRTk7Sn43f2KwaVOJwsXYAJxlrYz97juc4NMTJrbySt+N+f/NvT1+eT/6aT388m",
- "X/zL6Zu3T949POn8+Pjdl1/+n+ZPn7778uG//XNq+zzsqWBwB/nFM/dGv3iGD7EoTqQN+x/BILNifJIk",
- "ytihqEWL5BPMl+EI7mFT76eXcM31hhvCW9OC5YYXHY182tdU50DbI9aissbGtdR4HgEHPofuwapIglO1",
- "+Ot7kefaE+x0uIm3vBVj4DijOjqAbuAUXO05U261D7775oqcOkJQD5BY3NBRaoHEC8ZFMDa8fMwuxYFd",
- "1/yaP4M5vgcFf3rNc6rpqT1Np5UC+RUtKM9guhDkqQ+KfEY1veada6g3gVQU1BxlkEpxCrpKr+X6+jUt",
- "FuL6+k3HD6ErW7mpYi7qzllXTeannBi5QVR64pK4TCTcUpmyhfgUHy4aGnvvhMPKJKKySiyfJMaNPx0K",
- "ZVmqdrKHLorKsjAoikhVuXwFZluJ0iIEjhlm7mJvDQ38KJxTiaS3/slbKVDktxUtXzOu35DJdXV29imG",
- "4NUpDn5zPNDQ7baEwQ/f3mQU7fcuLtzK5ehUPinpImUzub5+rYGWSCEocKzwpVkUBLs1wgN9JAAOVS8g",
- "xCIfsCUWsoPjenG5l7aXT+uVXhR+wk1txk7fawejqPg7b+CeyHpa6eXEcITkqpQ5Bn6vfIIBujBXjvcg",
- "UGyBDwC1FJVZMpBsCdmNy2wFq1Jvx43u3tHF3cWe4TCFOiMXHDhnBn8Z5WbAqsypE2Qo37ZT3CgbDIGD",
- "/gQ3sL0Stvt0YHawKBtdlGJF9R1dpN3orjXkGx9kN0Z7853flY8RdelIMO7Sk8XTQBe+T//RtgLAEY51",
- "iigaeT76EEFlAhGW+HtQcIeFmvHuRfqp5TGeAddsDRMo2ILNigSb/o+uXcPDaqhSQgZs7aN6w4CKsDkx",
- "r6OZvY7di0lSvgBzqZuLWChaoNP+NGnoR+lwCVTqGVC9U1/L4zQTHjoUyG8xaBqVJmOzBNiY/WYalSAc",
- "bs0DD9/eto1zJJ7eyZ3KrgnyO4Lqu9dB0tO7PCIcwhP57Px9H/YkvBecf1pMnQiy/b4yOFxIcWt20wAo",
- "fOpGTPAS3VOVogsYeh01TEUDU2I0LEA4yD7pJynviHlbrOnIGAMXYbtPDF6S3AHMF8Me0AzQcnH0c1sT",
- "orMqvOTF1iN1VqBAHRxELelQ2bCz8cVhwKbZGEheC6sesCbW4qO/pMof/XwccfQ7SosfJ5XMrvx5F5H3",
- "HdXd7Hj+mm6z9rHV58yACG56+Cx6PnWez5c3Gh+U+248ciEOqb0THKXoHApYWJzYxp7O6vxM9W4aOF7O",
- "58j0JilHvkgZGUkmbg4wD7ETQqzGnAweIXUKIrDRso4Dkx9FfNj54hAgucsvRf3YeHdFf0M6WNB64xsp",
- "WZTm1mc9VqvMsxSX3qIWeVouzjgMYXxMDCdd08JwUhd4Wg/SydWGb59WZjbn2/Gw70008KC5NaJ0ctAq",
- "rTxzl/XFgrdfRvpVcNAaZmIzsZHRyafVbDMzZyIZr4Bx2qnDazPnPVBkJjboU4Q3nHVwPxi6fsg8YJEb",
- "yIYppHLs1yc2WvAOA2S3IJ+iZoWk5/Rqgez6JNm7AdMjTveR3SdRCr0jgdRSYNZpwJ1GZ6+epSltdSWR",
- "+rodh+ywIUwtxWr6DmdyJ3sw2lWeNnPdfV+nO+xPjubP6gdJ8tdVyt0nL6PtXNpci4ekZWyTQwOIHVh9",
- "1RZik2htOi418RphLcWSDKPvGru6aFNQAGoCJg25enKTMktfX79WgDLDpe8W6Tlx9yjfPoy84SQsmNJQ",
- "Gxe8k8uHt/2gOtE8tsS8f3W6lHOzvp+ECIKGNcdix8YyP/gK0HV9zqTSE7TMJJdgGn2rUJP2rWmaFoSb",
- "/nZMWVPPwXIwQnQD20nOiipNyg6kH54ZiH4MN5eqZnhRMm69jWaYCj/poHuAbRLhsY7dOxH03CLoOf0Q",
- "+Bl2sExTA5M0lNec/k9yxFq8cBdnSdByipi6G9qL0h28Noql7zLaSIiO3C6mu2w+nXOZ+7H3emP5iP4+",
- "IcKOlFxLlBExHUAoFgvIfaY3FxRqs165fHqF4Is6l6D5fUf6wCmxWfwwCd+O/H3OPR36nNMb5USwKkYS",
- "+vgxg5DX0XWYexAnWQC3mVtGh9cbKZKIix3jsUWkGf2wvL3jNp90Hb5quQvXPr12D8Nm4/YUQHP3rFLg",
- "17f70Ha3y6Fu3Od03EgRu/uA4YBIcUyrSIDpEE0P56ZlyfJNy/BnR53egSQGinvdTPAtnCFbcoPtwU/T",
- "sXhPrZ4H5nbE9s7YcYrP/FPzyLT+zM4j15wNmrlsA3kl0ZrU8Bbu5tMPD82Ba//hl0stJF2AswhOLEj3",
- "GgKXcwgaopT0imhmHaRzNp9DbAlTd7HiNIDr2DvyAYTdQ4Jdc1l4W+6kzy6R7aGtegX7EZqmpwSl9Plc",
- "XHXtkf7hEenWwmUTbdwdjIrJhAI/wHbyCy0q8xJiUtW+qc5A2LzWD6CJ9eoH2OLIe10+DWB7dgVVcT8B",
- "UmjKuhI+qShL+APVqL6Ab+DGFh6wU+fpXTrS1rhSGv1Ho76hGvUkmkt5f8emdpExkA7Zq8u014k5W9Dc",
- "ljah79silu+XfaInSDwVQ++Nu1xyIdPGXu8yoIUnfFzs6N14dD9/j9Q96UbcsxOvwtWc3AX0xrT2/4bT",
- "14EbQstSijUtJs5Ppk/okGLthA5s7t1qPvD7Kn0qrr45f/7Kgf9uPMoKoHISVB29q8J25Z9mVbYEx+5r",
- "yKZjd7pdqwqLNj+kzI49aW4x9XpLm9apdVP7TUUH1XnWzNOe4nv5pnPxskvc4eoFZfD0qi3S1tGr6dxF",
- "15QV3vDroR2qZbfLHVZdKckn4gHu7SQWef/de6zeOIHr69drj9nanmIdpUJK/IQvnbqjp3OH16TPak3r",
- "ezgkrvMlZjJNv7u4y3OKjNE5nNGjy4HfCtm4qFxUY9Jh7f0JiOYxYfGYNspfOSt8RyycEitC/rb4zfCG",
- "k5P44J+cjMlvhfsQAYi/z9zv+I46OUkahpOqPsOyUJPH6QoehriI3o34sGoIDrfDxIXz9SrIyKKfDAOF",
- "Ws8zj+5bh71byRw+c/dLDgWYn6ZDVBXxplt0x8AMOUGXfVGJwfl5Zct5KiJ4OwYfo2QNaeHV4yp4WDt7",
- "9wjxaoV254kqWJZ2+uEzZVgSty69pjHBxoNtyGaOivX4lfOKRaObZupOJs/WQqJZkwhXyUzANX5nwrGA",
- "irN/VBCV9cWbuHU5+6cQjtoRsNP6RTdwu2rw6C4Ff+9vIvRatV0Ko50m12fBDOgRkaozdWC8Qzxjh/nv",
- "iFVwFOWvTwxsWzrX4b2UtfOdt7sItDMDe/bpLK79DyRXDtNu5rMhO83UZC7F75CWHdBImEjd4a3bDBXw",
- "vwNP+ai2GVnwHKgLVtez7yOQ4bqFPlK5ty7BLzpUzbvLFZ7mE4dt9IFKg2i/+9UGKp1e3G1C30M1djxp",
- "BtL0MDM8sJFbONby8e5ulNsTavNaNCLP0uc8DhQ9tePX59zB3AmuLejtjKYKHZn3ooEp2v6GY54WxHf2",
- "G6RCagY7O4liGUJbZpP9lSBr61E3VfId33522sGvvvqRhxQXP+/G1lelUCIxTMVvKUc/QuxnOaDrrcD6",
- "YZhet0Jigk+V9iHMIWOrpDL8+vp1nnU9v3K2YLakeKWA0Ll2eR7dQLaovKUiV8075CJxqLmYk7NxfWb9",
- "buRszRSbFYAtHtkWM6rwgg4+EaGLWR5wvVTY/PGA5suK5xJyvVQWsUqQ8D5H0TN4ws5A3wJwcobtHn1B",
- "PkGHYcXW8DB9wThhbfT00RfjXZWzEeNYJH4Xk8+Ry/tAhjRlo1e1HcOwVTdqOjJhLgF+h/77ZMf5sl2H",
- "nC5s6a6g/adrRTk1CEnBtNoDk+2L+4uuHC28cGudAaWl2BKm0/ODpoZj9USTG4ZowSCZWK2YXjlPUSVW",
- "hsLqMuR2Uj8c1tfzZdA8XP4jumCXiTf+R3hu0VVPhCN61f+I9vYYrWNCbcbWgtXxF75CLbnwmamxLlwo",
- "B2dxY+YyS0d5FcMx5qSUjGvUGlV6Pvmbeb5LmhmGOO0DdzL7/EmivlqzBBE/DPAPjncJCuQ6jXrZQ/Ze",
- "ynF9ySdc8MnKcJT8YZ3SITqVvb7iaf/ePrfjnqHvLV2bcSe9BFg1CJBG3PxepMh3DHhP4gzrOYhCD17Z",
- "B6fVSqYJhlZmh37+6bmTRFZCpipd1AzASSUStGSwxvjS9CaZMe+5F7IYtAv3gf7jerd5sTQS3fzpTj4W",
- "Iqty4p0W0ioZSf+XF3V+fDRu27jdlvZSyISe1mkcP7Bb6mH6wrYN3boD4rcezA1GG47SxUpPuIeN5wh9",
- "Poa/Vxsku+cNVemj34g073iU9U9OEOiTk7ETlX973Pxs2fvJyXCX2bS+0PyaQM3d7pp29krTN7XVX4mE",
- "9s5X8Qx+Yy5VSULDmrzLzJU6c2OMSbNU4oeXO44Tr3iwG3L6AHnU4Oc2bj4yf8XNrCNg+vlDs3psknzy",
- "8D2KoaDkK7EZSkSta8vT0x8ART0oGagVxJV0quMmPSX2uvlEZGtGnUEhzEs1LoA12GvlT7QLBjXjHXtR",
- "sSL/pbZCt24mSXm2TDqVz0zHX+0zIGoQaTCyJeUcimRv+1r+1b+qE+/+v4ueYVeMpz+1CzFb2FuQ1mA1",
- "gfBT+vENrpguzAQxipoJuUKKk2IhcoLz1JVLatbYrWieqiSbiPHHYVeVdl7JmDzBFRSZswLdaNP2cGw5",
- "kVT3cFUs++9LXJlxsAq/smoJOzpIQtkKr21FV2UBeAjXIOkCuwoOre6YsQ1HjsqSEFWaT9gSk78IoivJ",
- "iZjPo2UA10xCsR2TkiplBzkzy4INzj16+ujs7GyYkRHxNWDtFq9+4S/rxT06xSb2i6v8ZQsmHAT+XaB/",
- "V1PdIZvfJS5XfvUfFSidYrH4wQZko4XY3Ou29GooEzwl32F+MkPojRIBqBT1GZabOUGrshA0H2NS6Ktv",
- "zp8TO6vtIwFRh6VfF6gBbB6RpJFneI5Un3+tJ3fV8HF2p84xq1Z6EoqypjIpmhZ1LVnW8n5C3WCMnSl5",
- "ZtWywbHHTkIwtbhcQR7VgLVqACQO8x+tabZEfed0tFOl3FMNaHgJY88Ba3NRFPcaCmYhBzfLcFWMbRHj",
- "MRF6CfKWKcC8E7CGZsLGkO3UKeR9AsfmamXFuSWc6QHSayiPdegueOCs6Ov9K5KQtfbh3ra/OpMHFjk/",
- "tNjzJfZKx+20Kke3/B5syYyNL7oxJS+csSOjXHCWYbGJlAiOqRiHmVUH1OVI2zvVyJ3lxDFM1qsOAeoO",
- "i70VrD3LdIjrOjVEX81+W8Kxf2rYuCKAC9DK8UDIx758vDPQMa7AFUAz9BVzVCETrl/JsJjgQnJEl/Tx",
- "CLOp9ehavzXffnS6ecwZc8M46twcUt1L0BrYCsXQzs4J02QhQLnVNuPC1GvTZ3q14QjCm+lzsWDZJVvg",
- "GNYV0SDFegF3hzr3PsHOB9e0/dq0dbULws8Nlzo7qV/3myQLUWH/UzXXe9Gf8v3yjjQRcsP48Wg7iHGn",
- "qz/ey4YMYY2ef1Difd4hm1C+vjnKN+bJaukNWxAbuZtMG8x4AoznjHuDbzoPVpa8S3Bj8DT39FOZpNo+",
- "OgZxvCugRU84DAbVW4+B+w7VrsRgUIJr9HP0b2Ndeb+HrYQG9euC8i3xh8JQdySUfE2L4AyfqKOP0pkT",
- "xqyzcKuyfoqtGLY+8aG5DXTtDQQN3bEayqH3VF+20VmVL0BPaJ6n8s59hV8JfvUBhbCBrApFwEKcaTNd",
- "e5fa3ESZ4Kpa7ZjLN7jndDlTVClYzYqE6+2z8BHysMOYiGq2xX9TFbD6d8Y5vR8c/e093PPDahR0o9lT",
- "0rOh6Ylii8lwTOCdcn901FPfjdDr/keldB/4/YeI625xuXiPUvztG3NxxGm6Oz7+9moJWbTRn17gd58P",
- "LGRybXIlvMo6dd7QIwM3L7FlLeB9wyTga1r0ZFyIrTb2frWWjL68C1lvWhGqXfY6TUnNE4aoMPrzf1kP",
- "7JZlqGve7POxti7W79N44vCxE+n9lsYfGnZF6/VWM5Ree+LdTH41ERxq83OlGLr6UloUIhvMGdww56ZT",
- "f6pesVq5zPcJr7z1SuTxWYi9uQDSjM06LCdCK/Bhm/yGT6vkF3mbHq2hHwlEMzRrGaLRLWFsAzM9eB4Y",
- "O3U8UaSydZgl37ICi0P9++XLH0f9GxntQHdLXerspAq7b2NCpFqbPBaigY8dPEDwIq3/Vj0qdcwNlT4N",
- "rjpx8sO3VkE4BCSbJ+mQ1s+HDt4hgIWwVaFSdTO62WlG9XZ45EfUUG+v5SgxdaSool1tKfH2sUrPugkJ",
- "hUgHFSZtyEhDijul6gi5l4LXwNqLxuWjs8WVOnWZOgz02RDhsIOPd+PRRX6Q+JSqRTWyo6QY7HO2WOqv",
- "CpHdfA80B2nriaSek7aayArMM1QtWYnvn1IoVtcDLsxgLpH3EoebDg3NuVqCywrjkwR0xvIO1GvINNaH",
- "rt1AJcBwP4cyvUQDgTcoYpOP4AoiAXIo9XKnsGSdu0u9rMuGgos8Y4rMwJku1sDHhE1h2g5Wy+ukUKQA",
- "OvdKWCmEHlBXN4QtIRpjoFP01anRvFsM7OR8i1Ia2lK60+FFWM5DTIANtLylqs4c1UqjMDhcez6HDBPe",
- "70y/9x9L4FE+trFX3SEs8ygbHwvhgliy4aga7RrWXYnwdoIa1aR6n5D2JcS4ge0DRRo0lKwIHCJs75IB",
- "HpFj7bi+qECfacM5RjIV6AkR5P3gXQL+usbSXYoARNkp7wiGp3FzPdUZK+8GjZdo7gCG6Tq9V9H+Oh0e",
- "CqZ92f261dX7X8rPsJi9ck6lNKSbj/VJ5KJbjvnWpavHRIvBWugT14Pyv/kErXaWgt24CjWIMGubvaUy",
- "9y2OkibP3pssDfQ8zMzqwKiul8+hfjk2QjErhBGAJn2Boc1IpeDC+0BZX+s6aRlCPQcpIQ82wUIomGjh",
- "w6wOSP7pwid3YM96md8Jby2P/gNChu2Kemso/FQXksBykBRrJlDnfB5jhUhYUQO9jIo7pNWg+3boa/vd",
- "5xTx5f12q1f78B7Oxf4K2T70jqkO5uPTNSdOODiYezUSkdxBM8s4BznxRtx2aQfeTJOJeZXzKrOiSnw2",
- "g/Z6cNqxHdwsqdTMuqtsPaGirBw3sD21ah9fddzveAy0lSEt6FFC6RZRHFVXrVJwL44C3sdN31kKUUx6",
- "LIMX3XoU7cNww7IbwMSsITLFSMEPmsfGTEI+QYNU8Bm5XW59tYWyBA75wykh59xGB3r3kWYF0tbk/IHe",
- "Nf8GZ80rW2HGaaCn1zwdZoWVXuQ9uZ8fZgfP6+NNCgy/vOf8dpA7zK43vM9H7hZLwjTrBE+Hqje6/h0t",
- "ESoiPwtFSoC6tIbgr5ElJN5RBLOzRGmE0D+AEmdAJqoQKS/8u2SQMUOlMRVPhgBp4AOeqzUUbvAkApyT",
- "3Z6srO6zzzsq5kRC7Ztx1wSsLqepZeKqTzXSnjnM0uSMcyEhnhH9TG2i5hDZhnmO8T8zpiWV27ukSW2i",
- "KqWG6sXyXm/J4ChZL6R2luzisCjE7QTZ2iRUV0qpA0w71by2fZ3Sup856jOI3C6pciLilixpTjIhJWRx",
- "j3SIt4VqJSRMCoFemCnHjrk2j4QVxnVyUogFEWUmcrCF0NIU1DdXxTlF2QsiV7YkCiztYMoA2yei44FT",
- "mtvXmmcnKK/tLbThN//K9LHpK+r0d3bRE+si0BNfAMqlu3MYso278CLh2IxMbaVsWkSesw3SDcjUkZ8T",
- "LSsYE9eiXYXfHXwqgayYUhaUQEu3rCgwewTbRA4NwR8ojdoe2fkC/aDXDB3emplErEhdmtsxpF+JecBl",
- "nJGN6KUU1WIZ1QcIcPqnu6zcwz4e5WdVoU8ihoiaKZ6QlVDaPYvtSPWSaxfQTzLBtRRF0VTkWTl/4Yy+",
- "L+jmPMv0cyFuZjS7eYiPcC50WGk+9ikV2r679UyylYNx2EtBb/gEyUPtT7Nu26FXq6Pnwbyzxf06hod9",
- "mvwIzDf7met+u8Z5d2HtdTX5bPotdM4J1WLFsvRx+3N5v/b6rKa4VzLToq1CbLPQYDPkA/E9FtyZkHt2",
- "0QycJsuonhPHI5xbB3Ii818U49vjkjk4HtRzh3b5jhOwJlmvGNgCACG1iRB0JW3p4lhICwxHLGziFHRK",
- "aQM68MJB37/7wWZGODpQGu4FVMcbOQD4idVgjG1GTOvZPBMb//1hnTLzTsC/203lDebR51R5WZOWtG6V",
- "PpFVD0dIFyDY6YF4hUkwZkP9EEMp+oGXfwRAv2diA4ZB/omHgjGnrIB8kqpSfBF0YOPoue5iLKPRfT1H",
- "y8kzWvlKwGbsSoJLrGSlf9k0J5bUkJIIzbsacZ7DBmyM1u8gha3jO47MWVDYMr8tjYIoJwWsoeGw6bI9",
- "VSiFsjX4vip0JjlAiRbftqIt5YkYVwlsaV/c2ieRL9sQ7CbVMRaxdqfIHl1LUjO04RN7TNTQo2QgWrO8",
- "og38qUNFjqYu0RzlBKo6z4eJf2IOneZnO8JPfoBz3z8lynhMvBnGhw5mQWnU7WJAez2TK9V36nnaMTlO",
- "ZRYMRThbHuzalsRrvqFKesv7tZpdkq9fYgP3iQkeIfabDWQo1binEOTuMdRjOXE5kJDaOUBuHwymS0Kb",
- "vwROuIhqHt9SFV4xdVZX/4OdGBsx7h7ad7DR1/7D999ZgoMR1Uq2mC5RGsj6fjr+j3ISdx7E3vFSNKLA",
- "hfLuUI156nbPDmwgqiIn3Oynkf2xRrC7xRwXH5NZ5QcqCnFrixjHT9Rn4O25lvq8icmJ5Sxcy95PeuwS",
- "Dre1ICyKEFnRLRES/zEP0n9UtGDzLfIZC77vRtSSGhJyBmTrReH8rs3Eu8WrsQfMK2KEn8qumw0dMxpu",
- "a0aJgDYXuS/bJsiK3kC8DeggYvlnpg3jVNUMlRrmym5tZxcLbvE+PdOK5rESABPNbhvcwSc8N73//zps",
- "NZ7K538sC5r5ktWu+FyTz2BVe09cegmr3WHOXb7mSSBUyq+JVvo0GfkdtKkHsq5UzE9fcawG2J0S4J26",
- "YPdaxkClcKvG0Y4A8UFLOfYuHCeGs7OkuNTvvsXFlY8/zO4kM0T3LWMI+H+gXWm4V3Qi29IV1OP12GLp",
- "H2AXGol4ErBaNfhMbCYS5mqfI43Vg8/EpgZYBd0t45kEqqzf0cVL92ytEyAzbp7R1ms3mFXDKDnMGa9Z",
- "LeNlpROvIMyDzLcRwmJrAqK1xzbXJ2MYUXRNi5drkJLlfRtnTo8tDRwX6fEWFNc3oQAJN3J3AKbqFyDG",
- "U9f6+biZuf5tgUHrO6s05TmVedyccZKBNFIDuaVbdXdTVbA67DNW0UgWamYLicxWSNoWkGLrrM33NCQF",
- "AOkRLUoDLEHopJ2wAlnFkBY9hp8uDH8KS9CKbiaFWGDUb8+BcHmu0XRoH5CCoxLdSnfD1u3nUex32D0N",
- "liJxjEgLnHXIFLvP/UvcSnyE/syZ3nnyrYazHYZtPZ3twfRI5Ys6PMMSS/c8piLnXWKmOHrei6o+TYmn",
- "PYg2MekS3dGq9+wi+le4tAuxCn14scqmC0cqPt/qFSaob1A7AjBA1XEFNHMeYl1FXEdRYZEydtkNDtTT",
- "We2+v5d6wENFinJnvTltcNAx4xxS4XN3PoNJKcpJNsS31VYryp2RwUHahLGHPiITQs+6g9+NCvW7GjnR",
- "GoW8Di1y2ltIbJ+trMx2qQz6lEw9HL1pwBBz5GV4hK1qDWOtgipm7B/n3tjdVKIFJkEokZBVEpXMt3S7",
- "v/BjT/b5y+/PP3v0+NfHn31OTAOSswWouqZBq3Bi7ZrIeFtr9GGdETvL0+lN8NlCLOK89dKHvYVNcWfN",
- "cltVJyPulI08RDuduABSwbndEnl32iscpw6L+GNtV2qRR9+xFAre/55JURTpmjJBrkqYX1K7FRlgzAuk",
- "BKmY0oYRNu2nTNdO2WqJykXMGr62uaEEz8Brnx0VMN3jy5VaSJ9PL/IzzMXgbE4ENmXheJW1E+1al3un",
- "Wf0eCo3objMDUorSifZsTlIQYcyWrCDo1Z3aFPXpkZtuYLbWYTdFiM75PU1659y9hMWc7Ob2zVLcOs3p",
- "zSYmxAt/KO9Amn3Wjf48I3fhJLVh4A/DPxKJU47GNcJy3wevSL4PdkSFn3e8JkLSkEGgdRNkJMgDAeiJ",
- "h24ErUZBdlFucmltDGiN8ObntvjxojZL741MQUh8hz3gxbHMdbsQTOHA+ciJvV8EpERLedNHCY3l7wuP",
- "9qw3XCTRFjmlidagLFsSXbEwCohXX4c4855XSSccXQqhiXmZFkUijN3qcfBMxYRjngRyTYsPzzW+ZVLp",
- "c8QH5D/1B27FYcsxki0q1dETcj6ng8CKQpQ/CFT8FcbW/weYnU3ejm4WZ/jv3IGoEqKF9faeBws4cHKL",
- "Y1rHrkefk5kr91NKyJhqOxTcepEmxNuCZHPnXwsb3Y79vXeZoF+EvsdxmHt/IPJjZGQLngMO5vqof2Tm",
- "1MMBkqclRaodQkngL8Xr4qLqe66de5aGuVsqpyhx44GpnLrl4ocuD9eBl1eloLvOwbd+A7eJC79e29Bc",
- "ZYMrzFxfv9azIQnF0tVgTHfMcXaUsjD3LwrzQRKcWVS6MRwkScKqRe592Wta/pJRnobmLhpxv6eA/NKi",
- "34yGj4J5xe14oQAqxop7ti7m4+DFILjp9pRc8xOiltS/Ldyfjz/7fDQeAa9WZvH199F45L6+Sb3U8k0y",
- "rrROpNPxEXXVBB4oUtLtkGD2valzkvitMwV9eJFGaTZLv+m+N3uGD1cXgHDBkdUje7E3qMuf81cCoJ3E",
- "0Dqs4cRYkqzTA4Wt2Jcp6Je+tPg29XtPtY8W961YsddJrlGI5d14tLBJyrA6ya+uVt2H3XYPQU++QLf0",
- "+6QBs4hJrLUxeTRVlNRtQEEW1y1RIQMjr7NKMr29NPj3anf2600qGdR3IT2Ty/kVLPBO9tXiBrj3MauT",
- "OVXKS9ffCVqg9GkdA7iROUUxJd/YCiHuWvzywexf4dO/PcnPPn30r7O/nX12lsGTz744O6NfPKGPvvj0",
- "ETz+22dPzuDR/PMvZo/zx08ez548fvL5Z19knz55NHvy+Rf/+sBQugHZAuor/zwd/efkvFiIyfmri8mV",
- "AbbGCS3ZD2D2BjVsc0xQiEjN8IqFFWXF6Kn/6X/5i3KaiVU9vP915OpBjpZal+rp6ent7e007nK6wBwo",
- "Ey2qbHnq58Fclo33yquLEBdkff9wR2ubE25qyO9nvv30zeUVOX91Ma0JZvR0dDY9mz7CfIolcFqy0dPR",
- "p/gTnp4l7vspZtE+Va4Yz2kIHX037nwrS1uqx3xahDSg5q8l0AJZpPljBVqyzH+SQPOt+7+6pYsFyClG",
- "jNmf1o9P/dvj9K3LK/Nu17fT2Bvt9G0jOU++p6f3p9rX5PStL/e/e8BGKXfn52qQmnSU+A60S6NnNZaJ",
- "PEdon3Sjj4nCujvmp1IyYc7r2IgLOaA3EbrUSqwvomXFM+tiYqcAjv99cf6f6Gbz4vw/yZfkbOyCnBSq",
- "QVLT21QRgdAucgt21zdafbU9D5mgapec0dPXKdW0c1Avq1nBMvOKmPqTasgwOkhhyJpRoiFiZC8K9A8I",
- "bN+w8rPJF2/efva3d0mP9K5zWu3VufNrR8IM+I0yJzXcTIQv5I74XtHNl33Y3riAGTPuPyqQ23r5K2pu",
- "6XqpAyXA5K+JlJk+8vHW1UyPna4jd+x/v3z5IxGSOMXeK5rdhKhPHwFcRz3HAcCmZ9/a3O0dL8/L1S58",
- "dKUWZbOWQNADvMGi0Ago8qzHZ2eeUTulR8QFTh1ziWZqicZdakYPwsiG0k3/oQhsaKaLLaEqcuFCd2xf",
- "wL0VmyvKSSNCaKfVpjuj25JkeNWhGUgSpXCEpsUe+K5axa4b6HDvltLc5PtTfnSQkYQgme423lpPI3/t",
- "7v+M3e2KPqQU5kwzDDip7zV/ZzaAdAJvsfXg9qRhmpL/EhUKqObpUWkILFBIZGfhVrbmWjeny0IXvdLq",
- "mEj8cnLSXvjJSe2RPIdbZLKUY8M2Ok5OpmannhzIynaa0BoVCQadnUOG62zWC7oJihRKuOATDguq2RpI",
- "5E315OzRn3aFF9wG4BiJ3L4c3o1Hn/2Jt+yCG+GJFgRb2tV8+qddzSXINcuAXMGqFJJKVmzJzzxEONmX",
- "FconXfb3M7/h4pZ7RJhHcbVaUbl1kjoNPKfiUSnCnfynk/+tluaRi9KFQjc9lIOt4Ozz3vLF6M07/9AY",
- "+MDZ1ex0hvW6hzaF+FXU/wRCLaU6fYu2vd7fT52eL/0Rza/2hX7qlZc9LW0OwvTHxtPrrd6YhewezrSJ",
- "xsuozpZVefoW/4OP7WhFtv7Pqd7wU3RXP33bQIT73EFE8/e6e9wCy1Z44MR8rvCxuOvz6Vv7bzQRbEqQ",
- "zFxHmBrZ/Wqz4Z+qqiyLbffnLc+SP3bX0Uj63fPzqdf1pN7tzZZvG382aUotK52L22gWtJJax4AuZOZj",
- "pdp/n95Spo2Q5LJG07kG2e2sgRanrjJh69e63E/nC9Ywin5siVWlsInTms/mn+jtVSPIXdosQF8J1Ib0",
- "MdzNZMY4cqGYS9a6T/ux+0Tq8EasH7/VtdNJQgbVgsykoHlGlTZ/1GVGmu/vd/d8f7WTFl0k/AYQTNRp",
- "dG0khp9M99qHcdwhQma0L+TimZ+wjqx974JZB6KvaE58pr0JeUELs+GQk3Mn/jew8b6Fqo8vBX1kseWD",
- "yRlf+cOnCMW0o40HokxnA4vq8A4RKswr0jCABfCJY0GTmci3ruLpSNJbvbHJh9rM7ZQ2b4ymtpNKulJ9",
- "H4+gCv1j6z/3qT3/Uhn+pTL8S6n0l8rwr939S2V4dJXhXwq1vxRq/08q1A7RoqUEUqco6pdL2Rq4Dbtp",
- "vRBpXWoosPhmAkWmg/TWiIXHqkZMTwm5wuxX1NwSsAZJC5JRZaUrl6lthc7mmIYR8qfXfNKAxDpwm4k/",
- "qf9r3eyvq7OzT4GcPWz3UZoVRcybu31RMsZPNkjuS3I9uh51RpKwEmvIrZdaXGfC9to77P8Xxn3ZKWiD",
- "qTwwvZjP1khUNZ+zjFmUF4IvCF2IOnoE01VzgV9AGuCsbyNheuyi7ZhL8WB3pVUOoynjdyWAi3oL93o4",
- "tMgl7dtgCO9Ax4Z/Sak8/pLSBzK7XQn97stId47d4ap/cZUPwVU+Ol/5s5tzIyXk/0gx88nZkz/tgmKV",
- "9Y9Ck2997Ns9xDGXKzlLFly8q6Dls115xWDtJx37HeMtGjyOX78xF4ECufYXbO1G+/T0FJMnLoXSp6ik",
- "arrYxh/fBJjf+tuplGxtoHmHelAh2YJxWkycH+qkdpV9PD0bvfu/AQAA///38T8KmyYBAA==",
+ "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",
+ "aTFxfqiT2lX28fRkdPN/AwAA//9KiHz6MCcBAA==",
}
// 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 b0f910f29a..348c973461 100644
--- a/daemon/algod/api/server/v2/handlers.go
+++ b/daemon/algod/api/server/v2/handlers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -1318,7 +1318,7 @@ func (v2 *Handlers) SimulateTransaction(ctx echo.Context, params model.SimulateT
}
}
- response := convertSimulationResult(simulationResult, proto.EnableUnnamedBoxAccessInNewApps)
+ response := convertSimulationResult(simulationResult)
handle, contentType, err := getCodecHandle((*string)(params.Format))
if err != nil {
diff --git a/daemon/algod/api/server/v2/handlers_test.go b/daemon/algod/api/server/v2/handlers_test.go
index 6d013995c2..03186a7cef 100644
--- a/daemon/algod/api/server/v2/handlers_test.go
+++ b/daemon/algod/api/server/v2/handlers_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/v2/test/genesis_types_test.go b/daemon/algod/api/server/v2/test/genesis_types_test.go
index 7f3e67b96e..3795a2b9b0 100644
--- a/daemon/algod/api/server/v2/test/genesis_types_test.go
+++ b/daemon/algod/api/server/v2/test/genesis_types_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/v2/test/handlers_resources_test.go b/daemon/algod/api/server/v2/test/handlers_resources_test.go
index d058eb9639..d4fe5daa70 100644
--- a/daemon/algod/api/server/v2/test/handlers_resources_test.go
+++ b/daemon/algod/api/server/v2/test/handlers_resources_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/v2/test/handlers_test.go b/daemon/algod/api/server/v2/test/handlers_test.go
index 1e989332f2..11c60cc6ca 100644
--- a/daemon/algod/api/server/v2/test/handlers_test.go
+++ b/daemon/algod/api/server/v2/test/handlers_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -1261,17 +1261,12 @@ int 1`,
FailedAt: expectedFailedAt,
Txns: []v2.PreEncodedSimulateTxnResult{
{
- Txn: makePendingTxnResponse(t, transactions.SignedTxnWithAD{
- SignedTxn: stxns[0],
- // expect no ApplyData info
- }),
+ // expect no ApplyData info
+ Txn: makePendingTxnResponse(t, stxns[0].WithAD()),
AppBudgetConsumed: txnAppBudgetUsed[0],
},
{
- Txn: makePendingTxnResponse(t, transactions.SignedTxnWithAD{
- SignedTxn: stxns[1],
- ApplyData: scenario.ExpectedSimulationAD,
- }),
+ Txn: makePendingTxnResponse(t, stxns[1].WithAD(scenario.ExpectedSimulationAD)),
AppBudgetConsumed: txnAppBudgetUsed[1],
},
},
@@ -1997,7 +1992,7 @@ func addStateProof(blk bookkeeping.Block) bookkeeping.Block {
},
},
}
- txnib := transactions.SignedTxnInBlock{SignedTxnWithAD: transactions.SignedTxnWithAD{SignedTxn: tx}}
+ txnib := transactions.SignedTxnInBlock{SignedTxnWithAD: tx.WithAD()}
blk.Payset = append(blk.Payset, txnib)
updatedStateProofTracking := bookkeeping.StateProofTrackingData{
@@ -2316,13 +2311,13 @@ func TestDeltasForTxnGroup(t *testing.T) {
blk2 := bookkeeping.BlockHeader{Round: 2}
delta1 := ledgercore.StateDelta{Hdr: &blk1}
delta2 := ledgercore.StateDelta{Hdr: &blk2, KvMods: map[string]ledgercore.KvValueDelta{"bx1": {Data: []byte("foobar")}}}
- txn1 := transactions.SignedTxnWithAD{SignedTxn: transactions.SignedTxn{Txn: transactions.Transaction{Type: protocol.PaymentTx}}}
+ txn1 := transactions.SignedTxn{Txn: transactions.Transaction{Type: protocol.PaymentTx}}.WithAD()
groupID1, err := crypto.DigestFromString(crypto.Hash([]byte("hello")).String())
require.NoError(t, err)
- txn2 := transactions.SignedTxnWithAD{SignedTxn: transactions.SignedTxn{Txn: transactions.Transaction{
+ txn2 := transactions.SignedTxn{Txn: transactions.Transaction{
Type: protocol.AssetTransferTx,
Header: transactions.Header{Group: groupID1}},
- }}
+ }.WithAD()
tracer := eval.MakeTxnGroupDeltaTracer(2)
handlers := v2.Handlers{
diff --git a/daemon/algod/api/server/v2/test/helpers.go b/daemon/algod/api/server/v2/test/helpers.go
index bb602ad726..c3fe8d96cc 100644
--- a/daemon/algod/api/server/v2/test/helpers.go
+++ b/daemon/algod/api/server/v2/test/helpers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/server/v2/utils.go b/daemon/algod/api/server/v2/utils.go
index 36d72144c0..b2757e375d 100644
--- a/daemon/algod/api/server/v2/utils.go
+++ b/daemon/algod/api/server/v2/utils.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -132,6 +132,17 @@ func nilToZero[T any](valPtr *T) T {
return *valPtr
}
+func nilToZeroAddr(s *string) (basics.Address, error) {
+ if s == nil {
+ return basics.Address{}, nil
+ }
+ addr, err := basics.UnmarshalChecksumAddress(*s)
+ if err != nil {
+ return basics.Address{}, err
+ }
+ return addr, nil
+}
+
func computeCreatableIndexInPayset(tx node.TxnWithStatus, txnCounter uint64, payset []transactions.SignedTxnWithAD) (cidx *uint64) {
// Compute transaction index in block
txID := tx.Txn.Txn.ID()
@@ -462,13 +473,13 @@ func convertTxnTrace(txnTrace *simulation.TransactionTrace) *model.SimulationTra
}
}
-func convertTxnResult(txnResult simulation.TxnResult, simplify bool) PreEncodedSimulateTxnResult {
+func convertTxnResult(txnResult simulation.TxnResult) PreEncodedSimulateTxnResult {
result := PreEncodedSimulateTxnResult{
Txn: ConvertInnerTxn(&txnResult.Txn),
AppBudgetConsumed: omitEmpty(txnResult.AppBudgetConsumed),
LogicSigBudgetConsumed: omitEmpty(txnResult.LogicSigBudgetConsumed),
TransactionTrace: convertTxnTrace(txnResult.Trace),
- UnnamedResourcesAccessed: convertUnnamedResourcesAccessed(txnResult.UnnamedResourcesAccessed, simplify),
+ UnnamedResourcesAccessed: convertUnnamedResourcesAccessed(txnResult.UnnamedResourcesAccessed),
}
if !txnResult.FixedSigner.IsZero() {
@@ -479,13 +490,11 @@ func convertTxnResult(txnResult simulation.TxnResult, simplify bool) PreEncodedS
return result
}
-func convertUnnamedResourcesAccessed(resources *simulation.ResourceTracker, simplify bool) *model.SimulateUnnamedResourcesAccessed {
+func convertUnnamedResourcesAccessed(resources *simulation.ResourceTracker) *model.SimulateUnnamedResourcesAccessed {
if resources == nil {
return nil
}
- if simplify {
- resources.Simplify()
- }
+ resources.Simplify()
return &model.SimulateUnnamedResourcesAccessed{
Accounts: sliceOrNil(stringSlice(slices.Collect(maps.Keys(resources.Accounts)))),
Assets: sliceOrNil(slices.Collect(maps.Keys(resources.Assets))),
@@ -557,18 +566,15 @@ func convertSimulateInitialStates(initialStates *simulation.ResourcesInitialStat
}
}
-func convertTxnGroupResult(txnGroupResult simulation.TxnGroupResult, simplify bool) PreEncodedSimulateTxnGroupResult {
- txnResults := make([]PreEncodedSimulateTxnResult, len(txnGroupResult.Txns))
- for i, txnResult := range txnGroupResult.Txns {
- txnResults[i] = convertTxnResult(txnResult, simplify)
- }
+func convertTxnGroupResult(txnGroupResult simulation.TxnGroupResult) PreEncodedSimulateTxnGroupResult {
+ txnResults := util.Map(txnGroupResult.Txns, convertTxnResult)
encoded := PreEncodedSimulateTxnGroupResult{
Txns: txnResults,
FailureMessage: omitEmpty(txnGroupResult.FailureMessage),
AppBudgetAdded: omitEmpty(txnGroupResult.AppBudgetAdded),
AppBudgetConsumed: omitEmpty(txnGroupResult.AppBudgetConsumed),
- UnnamedResourcesAccessed: convertUnnamedResourcesAccessed(txnGroupResult.UnnamedResourcesAccessed, simplify),
+ UnnamedResourcesAccessed: convertUnnamedResourcesAccessed(txnGroupResult.UnnamedResourcesAccessed),
}
if len(txnGroupResult.FailedAt) > 0 {
@@ -579,7 +585,7 @@ func convertTxnGroupResult(txnGroupResult simulation.TxnGroupResult, simplify bo
return encoded
}
-func convertSimulationResult(result simulation.Result, simplify bool) PreEncodedSimulateResponse {
+func convertSimulationResult(result simulation.Result) PreEncodedSimulateResponse {
var evalOverrides *model.SimulationEvalOverrides
if result.EvalOverrides != (simulation.ResultEvalOverrides{}) {
evalOverrides = &model.SimulationEvalOverrides{
@@ -593,11 +599,9 @@ func convertSimulationResult(result simulation.Result, simplify bool) PreEncoded
}
return PreEncodedSimulateResponse{
- Version: result.Version,
- LastRound: result.LastRound,
- TxnGroups: util.Map(result.TxnGroups, func(tg simulation.TxnGroupResult) PreEncodedSimulateTxnGroupResult {
- return convertTxnGroupResult(tg, simplify)
- }),
+ Version: result.Version,
+ LastRound: result.LastRound,
+ TxnGroups: util.Map(result.TxnGroups, convertTxnGroupResult),
EvalOverrides: evalOverrides,
ExecTraceConfig: result.TraceConfig,
InitialStates: convertSimulateInitialStates(result.InitialStates),
diff --git a/daemon/algod/api/spec/common/model.go b/daemon/algod/api/spec/common/model.go
index 984c004628..91592c62e8 100644
--- a/daemon/algod/api/spec/common/model.go
+++ b/daemon/algod/api/spec/common/model.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/spec/v2/model.go b/daemon/algod/api/spec/v2/model.go
index 2ce7fb7e31..c473314b01 100644
--- a/daemon/algod/api/spec/v2/model.go
+++ b/daemon/algod/api/spec/v2/model.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/api/spec/v2/msgp_gen.go b/daemon/algod/api/spec/v2/msgp_gen.go
index f8afb04767..dd295c435b 100644
--- a/daemon/algod/api/spec/v2/msgp_gen.go
+++ b/daemon/algod/api/spec/v2/msgp_gen.go
@@ -1,7 +1,7 @@
-package v2
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package v2
+
import (
"github.com/algorand/msgp/msgp"
@@ -230,7 +230,7 @@ func (z *AccountApplicationModel) MsgIsZero() bool {
return ((*z).AppLocalState == nil) && ((*z).AppParams == nil)
}
-// MaxSize returns a maximum valid message size for this message type
+// AccountApplicationModelMaxSize returns a maximum valid message size for this message type
func AccountApplicationModelMaxSize() (s int) {
s = 1 + 16
s += basics.AppLocalStateMaxSize()
@@ -439,7 +439,7 @@ func (z *AccountAssetModel) MsgIsZero() bool {
return ((*z).AssetParams == nil) && ((*z).AssetHolding == nil)
}
-// MaxSize returns a maximum valid message size for this message type
+// AccountAssetModelMaxSize returns a maximum valid message size for this message type
func AccountAssetModelMaxSize() (s int) {
s = 1 + 13
s += basics.AssetParamsMaxSize()
diff --git a/daemon/algod/api/spec/v2/msgp_gen_test.go b/daemon/algod/api/spec/v2/msgp_gen_test.go
index 2fc11278d5..127bcc5635 100644
--- a/daemon/algod/api/spec/v2/msgp_gen_test.go
+++ b/daemon/algod/api/spec/v2/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package v2
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package v2
+
import (
"testing"
diff --git a/daemon/algod/api/swagger.go b/daemon/algod/api/swagger.go
index c2ff7ca334..0a993e7e85 100644
--- a/daemon/algod/api/swagger.go
+++ b/daemon/algod/api/swagger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/deadlockLogger.go b/daemon/algod/deadlockLogger.go
index b5b443b6c4..aa7b926bba 100644
--- a/daemon/algod/deadlockLogger.go
+++ b/daemon/algod/deadlockLogger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/deadlock_test.go b/daemon/algod/deadlock_test.go
index 9731f90eb6..bf32bc42f0 100644
--- a/daemon/algod/deadlock_test.go
+++ b/daemon/algod/deadlock_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/algod/server.go b/daemon/algod/server.go
index 72c2beba0c..89ec3eed42 100644
--- a/daemon/algod/server.go
+++ b/daemon/algod/server.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -151,13 +151,13 @@ func (s *Server) Initialize(cfg config.Local, phonebookAddresses []string, genes
}
}
- if cfg.IsGossipServer() {
+ if cfg.IsListenServer() {
var ot basics.OverflowTracker
fdRequired = ot.Add(fdRequired, network.ReservedHealthServiceConnections)
if ot.Overflowed {
return errors.New("Initialize() overflowed when adding up ReservedHealthServiceConnections to the existing RLIMIT_NOFILE value; decrease RestConnectionsHardLimit")
}
- if cfg.IsGossipServer() {
+ if cfg.IsListenServer() {
fdRequired = ot.Add(fdRequired, uint64(cfg.IncomingConnectionsLimit))
if ot.Overflowed {
return errors.New("Initialize() overflowed when adding up IncomingConnectionsLimit to the existing RLIMIT_NOFILE value; decrease IncomingConnectionsLimit")
@@ -189,7 +189,7 @@ func (s *Server) Initialize(cfg config.Local, phonebookAddresses []string, genes
if cfg.IsHybridServer() && cfg.P2PHybridIncomingConnectionsLimit == 0 {
return errors.New("Initialize() failed to adjust p2p hybrid connection limits")
}
- if cfg.IsGossipServer() && cfg.IncomingConnectionsLimit == 0 {
+ if cfg.IsListenServer() && cfg.IncomingConnectionsLimit == 0 {
return errors.New("Initialize() failed to adjust connection limits")
}
}
diff --git a/daemon/algod/server_test.go b/daemon/algod/server_test.go
index 3d2e26afe3..53ec159b7c 100644
--- a/daemon/algod/server_test.go
+++ b/daemon/algod/server_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/api/api.go b/daemon/kmd/api/api.go
index 1f5df79c9c..f72816e525 100644
--- a/daemon/kmd/api/api.go
+++ b/daemon/kmd/api/api.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -59,8 +59,8 @@
// Base path must be a fully specified package name (else, it seems that swagger feeds a relative path to
// loader.Config.Import(), and that breaks the vendor directory if the source is symlinked from elsewhere)
//
-//go:generate swagger generate spec -m --transparent-aliases -o="./swagger.json"
-//go:generate swagger validate ./swagger.json --stop-on-error
+//go:generate go run github.com/algorand/go-swagger/cmd/swagger@v0.0.0-20251018003531-2ea7c750dcac generate spec -m --transparent-aliases -o="./swagger.json"
+//go:generate go run github.com/algorand/go-swagger/cmd/swagger@v0.0.0-20251018003531-2ea7c750dcac validate ./swagger.json --stop-on-error
//go:generate sh ../lib/kmdapi/bundle_swagger_json.sh
package api
@@ -70,7 +70,7 @@ import (
"github.com/gorilla/mux"
- "github.com/algorand/go-algorand/daemon/kmd/api/v1"
+ v1 "github.com/algorand/go-algorand/daemon/kmd/api/v1"
"github.com/algorand/go-algorand/daemon/kmd/lib/kmdapi"
"github.com/algorand/go-algorand/daemon/kmd/session"
"github.com/algorand/go-algorand/logging"
diff --git a/daemon/kmd/api/cors.go b/daemon/kmd/api/cors.go
index c5afb04a6d..ce3ac849ac 100644
--- a/daemon/kmd/api/cors.go
+++ b/daemon/kmd/api/cors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/api/v1/auth.go b/daemon/kmd/api/v1/auth.go
index 976323b7f2..5a9eda738d 100644
--- a/daemon/kmd/api/v1/auth.go
+++ b/daemon/kmd/api/v1/auth.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/api/v1/errors.go b/daemon/kmd/api/v1/errors.go
index 0ad0c5557d..694070b1d3 100644
--- a/daemon/kmd/api/v1/errors.go
+++ b/daemon/kmd/api/v1/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/api/v1/handlers.go b/daemon/kmd/api/v1/handlers.go
index d8b33cc87b..49b865e703 100644
--- a/daemon/kmd/api/v1/handlers.go
+++ b/daemon/kmd/api/v1/handlers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -1265,7 +1265,7 @@ func wrapCtx(ctx reqContext, handler func(reqContext, http.ResponseWriter, *http
}
}
-// reqCallbackMiddlware calls the reqCB function once per request that passes
+// reqCallbackMiddleware calls the reqCB function once per request that passes
// through. We use this in server.go to kick a watchdog timer, so that we can
// kill kmd if we haven't received a request in a while.
func reqCallbackMiddleware(reqCB func()) func(http.Handler) http.Handler {
diff --git a/daemon/kmd/client/client.go b/daemon/kmd/client/client.go
index 06c8378c54..58130b0362 100644
--- a/daemon/kmd/client/client.go
+++ b/daemon/kmd/client/client.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/client/requests.go b/daemon/kmd/client/requests.go
index 17073a0b66..9d30c4b8fc 100644
--- a/daemon/kmd/client/requests.go
+++ b/daemon/kmd/client/requests.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/client/wrappers.go b/daemon/kmd/client/wrappers.go
index 4e1fb7da8c..b7b1c01167 100644
--- a/daemon/kmd/client/wrappers.go
+++ b/daemon/kmd/client/wrappers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/config/config.go b/daemon/kmd/config/config.go
index f2aae3816e..18455c3e7c 100644
--- a/daemon/kmd/config/config.go
+++ b/daemon/kmd/config/config.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/config/errors.go b/daemon/kmd/config/errors.go
index 5283cfaac4..91992ee30d 100644
--- a/daemon/kmd/config/errors.go
+++ b/daemon/kmd/config/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/kmd.go b/daemon/kmd/kmd.go
index 3c88f74c6f..b2f662b722 100644
--- a/daemon/kmd/kmd.go
+++ b/daemon/kmd/kmd.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/lib/kmdapi/common.go b/daemon/kmd/lib/kmdapi/common.go
index 248eac598a..cbe52a7771 100644
--- a/daemon/kmd/lib/kmdapi/common.go
+++ b/daemon/kmd/lib/kmdapi/common.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/lib/kmdapi/requests.go b/daemon/kmd/lib/kmdapi/requests.go
index b355291eed..7977646be5 100644
--- a/daemon/kmd/lib/kmdapi/requests.go
+++ b/daemon/kmd/lib/kmdapi/requests.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/lib/kmdapi/responses.go b/daemon/kmd/lib/kmdapi/responses.go
index 1cace7f65e..eff3cc7357 100644
--- a/daemon/kmd/lib/kmdapi/responses.go
+++ b/daemon/kmd/lib/kmdapi/responses.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/server/errors.go b/daemon/kmd/server/errors.go
index 02baf37177..f8cd9af67a 100644
--- a/daemon/kmd/server/errors.go
+++ b/daemon/kmd/server/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/server/server.go b/daemon/kmd/server/server.go
index b94530eaf9..1c441a9c71 100644
--- a/daemon/kmd/server/server.go
+++ b/daemon/kmd/server/server.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/session/auth.go b/daemon/kmd/session/auth.go
index 522cce7190..ebf2d6597c 100644
--- a/daemon/kmd/session/auth.go
+++ b/daemon/kmd/session/auth.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -96,7 +96,7 @@ func generateHandleIDAndSecret() ([]byte, []byte, error) {
return hexID, hexSecret, nil
}
-// cleanUpExpiredHandlesLocked periodically calls deleteExpiredHandles until
+// cleanUpExpiredHandles periodically calls deleteExpiredHandles until
// sm.ctx is canceled.
func (sm *Manager) cleanUpExpiredHandles() {
ticker := time.NewTicker(handleCleanupSeconds * time.Second)
diff --git a/daemon/kmd/session/session.go b/daemon/kmd/session/session.go
index d3bd5be9e9..3e6580228d 100644
--- a/daemon/kmd/session/session.go
+++ b/daemon/kmd/session/session.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/driver.go b/daemon/kmd/wallet/driver/driver.go
index a58a21b3c1..42ae934cdf 100644
--- a/daemon/kmd/wallet/driver/driver.go
+++ b/daemon/kmd/wallet/driver/driver.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/ledger.go b/daemon/kmd/wallet/driver/ledger.go
index 0bcbceabba..6241d86743 100644
--- a/daemon/kmd/wallet/driver/ledger.go
+++ b/daemon/kmd/wallet/driver/ledger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/ledger_errors.go b/daemon/kmd/wallet/driver/ledger_errors.go
index 5b9a73f8cb..58771e88e5 100644
--- a/daemon/kmd/wallet/driver/ledger_errors.go
+++ b/daemon/kmd/wallet/driver/ledger_errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/ledger_hid.go b/daemon/kmd/wallet/driver/ledger_hid.go
index 0ccde7602d..32f5e96c3a 100644
--- a/daemon/kmd/wallet/driver/ledger_hid.go
+++ b/daemon/kmd/wallet/driver/ledger_hid.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/sqlite.go b/daemon/kmd/wallet/driver/sqlite.go
index 5269e72559..67099647a3 100644
--- a/daemon/kmd/wallet/driver/sqlite.go
+++ b/daemon/kmd/wallet/driver/sqlite.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -118,7 +118,7 @@ func init() {
codecHandle.PositiveIntUnsigned = true
}
-// interface{} => msgpack blob
+// encode interface{} => msgpack blob
func msgpackEncode(obj interface{}) []byte {
var b []byte
enc := codec.NewEncoderBytes(&b, codecHandle)
@@ -126,7 +126,7 @@ func msgpackEncode(obj interface{}) []byte {
return b
}
-// msgpack blob => interface{}
+// decode msgpack blob => interface{}
func msgpackDecode(b []byte, objptr interface{}) error {
dec := codec.NewDecoderBytes(b, codecHandle)
return dec.Decode(objptr)
@@ -263,7 +263,7 @@ func (swd *SQLiteWalletDriver) ListWalletMetadatas() (metadatas []wallet.Metadat
return metadatas, nil
}
-// findDBPathsById returns the paths to wallets with the specified id
+// findDBPathsByID returns the paths to wallets with the specified id
func (swd *SQLiteWalletDriver) findDBPathsByID(id []byte) (paths []string, err error) {
return swd.findDBPathsByField("ID", id)
}
diff --git a/daemon/kmd/wallet/driver/sqlite_crypto.go b/daemon/kmd/wallet/driver/sqlite_crypto.go
index f30ac6d937..361a2dd3dc 100644
--- a/daemon/kmd/wallet/driver/sqlite_crypto.go
+++ b/daemon/kmd/wallet/driver/sqlite_crypto.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/sqlite_errors.go b/daemon/kmd/wallet/driver/sqlite_errors.go
index bc16e6a839..8c792258fc 100644
--- a/daemon/kmd/wallet/driver/sqlite_errors.go
+++ b/daemon/kmd/wallet/driver/sqlite_errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/driver/util.go b/daemon/kmd/wallet/driver/util.go
index 96263d4ace..623cfd1167 100644
--- a/daemon/kmd/wallet/driver/util.go
+++ b/daemon/kmd/wallet/driver/util.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/daemon/kmd/wallet/wallet.go b/daemon/kmd/wallet/wallet.go
index 9c4921e6cd..133254223c 100644
--- a/daemon/kmd/wallet/wallet.go
+++ b/daemon/kmd/wallet/wallet.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/account.go b/data/account/account.go
index 03ac4471fb..b7720fdf60 100644
--- a/data/account/account.go
+++ b/data/account/account.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/msgp_gen.go b/data/account/msgp_gen.go
index 36459a83f3..b4217367e4 100644
--- a/data/account/msgp_gen.go
+++ b/data/account/msgp_gen.go
@@ -1,7 +1,7 @@
-package account
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package account
+
import (
"github.com/algorand/msgp/msgp"
@@ -261,7 +261,7 @@ func (z *ParticipationKeyIdentity) MsgIsZero() bool {
return ((*z).Parent.MsgIsZero()) && ((*z).VRFSK.MsgIsZero()) && ((*z).VoteID.MsgIsZero()) && ((*z).FirstValid.MsgIsZero()) && ((*z).LastValid.MsgIsZero()) && ((*z).KeyDilution == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// ParticipationKeyIdentityMaxSize returns a maximum valid message size for this message type
func ParticipationKeyIdentityMaxSize() (s int) {
s = 1 + 5 + basics.AddressMaxSize() + 6 + crypto.VrfPrivkeyMaxSize() + 8 + crypto.OneTimeSignatureVerifierMaxSize() + 3 + basics.RoundMaxSize() + 3 + basics.RoundMaxSize() + 3 + msgp.Uint64Size
return
@@ -348,7 +348,7 @@ func (z StateProofKeys) MsgIsZero() bool {
return len(z) == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// StateProofKeysMaxSize returns a maximum valid message size for this message type
func StateProofKeysMaxSize() (s int) {
// Calculating size of slice: z
s += msgp.ArrayHeaderSize + ((1000) * (merklesignature.KeyRoundPairMaxSize()))
diff --git a/data/account/msgp_gen_test.go b/data/account/msgp_gen_test.go
index 380e391fc3..43192d8c01 100644
--- a/data/account/msgp_gen_test.go
+++ b/data/account/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package account
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package account
+
import (
"testing"
diff --git a/data/account/partInstall.go b/data/account/partInstall.go
index c424d590b9..7d6b9d9e02 100644
--- a/data/account/partInstall.go
+++ b/data/account/partInstall.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/participation.go b/data/account/participation.go
index bf50a546c0..ae15ed0b2a 100644
--- a/data/account/participation.go
+++ b/data/account/participation.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/participationRegistry.go b/data/account/participationRegistry.go
index a4ebcb7001..cbd4de2486 100644
--- a/data/account/participationRegistry.go
+++ b/data/account/participationRegistry.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/participationRegistryBench_test.go b/data/account/participationRegistryBench_test.go
index a9ef60a5d9..3f0ce02d41 100644
--- a/data/account/participationRegistryBench_test.go
+++ b/data/account/participationRegistryBench_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/participationRegistry_test.go b/data/account/participationRegistry_test.go
index e2ed12ba82..c75bcf6c24 100644
--- a/data/account/participationRegistry_test.go
+++ b/data/account/participationRegistry_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/participation_test.go b/data/account/participation_test.go
index d2d967d8c8..6477cb9a31 100644
--- a/data/account/participation_test.go
+++ b/data/account/participation_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/registeryDbOps.go b/data/account/registeryDbOps.go
index 165f53c41d..11d905a737 100644
--- a/data/account/registeryDbOps.go
+++ b/data/account/registeryDbOps.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/account/rootInstall.go b/data/account/rootInstall.go
index 304e252d16..4bfeb9c57a 100644
--- a/data/account/rootInstall.go
+++ b/data/account/rootInstall.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/accountManager.go b/data/accountManager.go
index 83a51f4c28..91a43a5a2d 100644
--- a/data/accountManager.go
+++ b/data/accountManager.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/accountManager_test.go b/data/accountManager_test.go
index 8cce9ce945..48a37535ce 100644
--- a/data/accountManager_test.go
+++ b/data/accountManager_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/appRateLimiter.go b/data/appRateLimiter.go
index 2f9e0e8f9a..230fa8714a 100644
--- a/data/appRateLimiter.go
+++ b/data/appRateLimiter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -169,6 +169,9 @@ func (r *appRateLimiter) shouldDrop(txgroup []transactions.SignedTxn, origin []b
// in order to make it testable
func (r *appRateLimiter) shouldDropAt(txgroup []transactions.SignedTxn, origin []byte, nowNano int64) bool {
keysBuckets := txgroupToKeys(txgroup, origin, r.seed, r.salt, numBuckets)
+ if keysBuckets == nil {
+ return false
+ }
defer putAppKeyBuf(keysBuckets)
if len(keysBuckets.keys) == 0 {
return false
@@ -201,6 +204,27 @@ func (r *appRateLimiter) shouldDropKeys(buckets []int, keys []keyType, nowNano i
return false
}
+func (r *appRateLimiter) penalizeEvalError(txgroup []transactions.SignedTxn, origin []byte) {
+ keysBuckets := txgroupToKeys(txgroup, origin, r.seed, r.salt, numBuckets)
+ if keysBuckets == nil {
+ return
+ }
+ defer putAppKeyBuf(keysBuckets)
+ if len(keysBuckets.keys) == 0 {
+ return
+ }
+
+ nowNano := time.Now().UnixNano()
+ curInt := r.interval(nowNano)
+
+ const penaltyFactor = 4 // penalize by 25% of the service rate
+ for i, key := range keysBuckets.keys {
+ b := keysBuckets.buckets[i]
+ entry, _ := r.entry(&r.buckets[b], key, curInt)
+ entry.cur.Add(max(1, int64(r.serviceRatePerWindow)/penaltyFactor))
+ }
+}
+
func (r *appRateLimiter) len() int {
var count int
for i := 0; i < numBuckets; i++ {
@@ -241,6 +265,17 @@ func putAppKeyBuf(buf *appKeyBuf) {
// txgroupToKeys converts txgroup data to keys
func txgroupToKeys(txgroup []transactions.SignedTxn, origin []byte, seed uint64, salt [16]byte, numBuckets int) *appKeyBuf {
+ hasApps := false
+ for i := range txgroup {
+ if txgroup[i].Txn.Type == protocol.ApplicationCallTx {
+ hasApps = true
+ break
+ }
+ }
+ if !hasApps {
+ return nil
+ }
+
keysBuckets := getAppKeyBuf()
// since blake2 is a crypto hash function it seems OK to shrink 32 bytes digest down to 8.
// Rationale: we expect thousands of apps sent from thousands of peers,
@@ -265,7 +300,7 @@ func txgroupToKeys(txgroup []transactions.SignedTxn, origin []byte, seed uint64,
txnToBucket := func(appIdx basics.AppIndex) int {
return int(memhash64(uint64(appIdx), seed) % uint64(numBuckets))
}
- seen := make(map[basics.AppIndex]struct{}, len(txgroup)*(1+bounds.MaxAppTxnForeignApps))
+ seen := make(map[basics.AppIndex]struct{}, len(txgroup)*(1+max(bounds.MaxAppTxnForeignApps, bounds.MaxAppAccess)))
valid := func(appIdx basics.AppIndex) bool {
if appIdx != 0 {
_, ok := seen[appIdx]
@@ -273,24 +308,24 @@ func txgroupToKeys(txgroup []transactions.SignedTxn, origin []byte, seed uint64,
}
return false
}
+ record := func(appIdx basics.AppIndex) {
+ // hash appIdx into a bucket, do not use modulo without hashing first since it could
+ // assign two vanilla (and presumable, popular) apps to the same bucket.
+ if valid(appIdx) {
+ keysBuckets.buckets = append(keysBuckets.buckets, txnToBucket(appIdx))
+ keysBuckets.keys = append(keysBuckets.keys, txnToDigest(appIdx))
+ seen[appIdx] = struct{}{}
+ }
+ }
for i := range txgroup {
if txgroup[i].Txn.Type == protocol.ApplicationCallTx {
appIdx := txgroup[i].Txn.ApplicationID
- if valid(appIdx) {
- keysBuckets.buckets = append(keysBuckets.buckets, txnToBucket(appIdx))
- keysBuckets.keys = append(keysBuckets.keys, txnToDigest(appIdx))
- seen[appIdx] = struct{}{}
+ record(appIdx)
+ for _, appIdx := range txgroup[i].Txn.ForeignApps {
+ record(appIdx)
}
- // hash appIdx into a bucket, do not use modulo without hashing first since it could
- // assign two vanilla (and presumable, popular) apps to the same bucket.
- if len(txgroup[i].Txn.ForeignApps) > 0 {
- for _, appIdx := range txgroup[i].Txn.ForeignApps {
- if valid(appIdx) {
- keysBuckets.buckets = append(keysBuckets.buckets, txnToBucket(appIdx))
- keysBuckets.keys = append(keysBuckets.keys, txnToDigest(appIdx))
- seen[appIdx] = struct{}{}
- }
- }
+ for _, acc := range txgroup[i].Txn.Access {
+ record(acc.App)
}
}
}
diff --git a/data/appRateLimiter_test.go b/data/appRateLimiter_test.go
index 472731ac15..690fcb2012 100644
--- a/data/appRateLimiter_test.go
+++ b/data/appRateLimiter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -184,7 +184,7 @@ func TestAppRateLimiter_Interval(t *testing.T) {
require.True(t, drop)
}
-// TestAppRateLimiter_IntervalFull checks the cur counter accounts only admitted requests
+// TestAppRateLimiter_IntervalAdmitted checks the cur counter accounts only admitted requests
func TestAppRateLimiter_IntervalAdmitted(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
@@ -248,6 +248,82 @@ func TestAppRateLimiter_IntervalSkip(t *testing.T) {
require.True(t, drop)
}
+// TestAppRateLimiter_PenalizeEvalError checks that penalizeEvalError increases the rate counter
+func TestAppRateLimiter_PenalizeEvalError(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ window := 10 * time.Second
+ perWindowRate := uint64(200)
+ perSecondRate := perWindowRate / uint64(window/time.Second)
+ rm := makeAppRateLimiter(512, perSecondRate, window)
+
+ txns := getAppTxnGroup(1)
+ bk := txgroupToKeys(txns, nil, rm.seed, rm.salt, numBuckets)
+ require.Equal(t, 1, len(bk.buckets))
+ require.Equal(t, 1, len(bk.keys))
+ b := bk.buckets[0]
+ k := bk.keys[0]
+ putAppKeyBuf(bk)
+
+ expectedPenalty := int64(rm.serviceRatePerWindow / 4)
+
+ // penalize the sender, this should create an entry with calculated penalty
+ rm.penalizeEvalError(txns, nil)
+
+ entry := rm.buckets[b].entries[k]
+ require.NotNil(t, entry)
+ require.Equal(t, expectedPenalty, entry.cur.Load())
+
+ // penalize again
+ rm.penalizeEvalError(txns, nil)
+ require.Equal(t, 2*expectedPenalty, entry.cur.Load())
+
+ // verify that penalty affects rate limiting decisions
+ // after penalty, only (rate - 2*penalty) requests should be allowed
+ now := time.Now().UnixNano()
+ allowedRequests := int(perWindowRate) - int(2*expectedPenalty)
+ executed := false
+ for i := 0; i < allowedRequests; i++ {
+ require.False(t, rm.shouldDropAt(txns, nil, now))
+ executed = true
+ }
+ require.True(t, executed)
+ require.True(t, rm.shouldDropAt(txns, nil, now))
+
+ // now checks multiple app ids
+ // create a txgroup with multiple apps including foreign apps
+ apptxn := transactions.Transaction{
+ Type: protocol.ApplicationCallTx,
+ ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
+ ApplicationID: 10,
+ ForeignApps: []basics.AppIndex{20, 30},
+ },
+ }
+ txns = []transactions.SignedTxn{{Txn: apptxn}}
+
+ bk = txgroupToKeys(txns, nil, rm.seed, rm.salt, numBuckets)
+ require.Equal(t, 3, len(bk.keys)) // app 10, 20, 30
+ putAppKeyBuf(bk)
+
+ rm.penalizeEvalError(txns, nil)
+
+ // all 4 apps (1, 10, 20, 30) should have entries with penalty
+ require.Equal(t, 4, rm.len())
+
+ // verify each app was penalized
+ for _, appID := range []basics.AppIndex{10, 20, 30} {
+ bk := txgroupToKeys(getAppTxnGroup(appID), nil, rm.seed, rm.salt, numBuckets)
+ b := bk.buckets[0]
+ k := bk.keys[0]
+ putAppKeyBuf(bk)
+
+ entry := rm.buckets[b].entries[k]
+ require.NotNil(t, entry)
+ require.Equal(t, expectedPenalty, entry.cur.Load())
+ }
+}
+
func TestAppRateLimiter_IPAddr(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
@@ -448,6 +524,14 @@ func TestAppRateLimiter_TxgroupToKeys(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
+ paytx := transactions.Transaction{
+ Type: protocol.PaymentTx,
+ }
+ payTxgroup := []transactions.SignedTxn{{Txn: paytx}}
+
+ kb0 := txgroupToKeys(payTxgroup, nil, 123, [16]byte{}, 1)
+ require.Nil(t, kb0)
+
apptxn := transactions.Transaction{
Type: protocol.ApplicationCallTx,
ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
@@ -459,32 +543,48 @@ func TestAppRateLimiter_TxgroupToKeys(t *testing.T) {
kb := txgroupToKeys(txgroup, nil, 123, [16]byte{}, 1)
require.Equal(t, 0, len(kb.keys))
- require.Equal(t, len(kb.buckets), len(kb.buckets))
+ require.Equal(t, len(kb.keys), len(kb.buckets))
putAppKeyBuf(kb)
txgroup[0].Txn.ApplicationID = 1
kb = txgroupToKeys(txgroup, nil, 123, [16]byte{}, 1)
require.Equal(t, 1, len(kb.keys))
- require.Equal(t, len(kb.buckets), len(kb.buckets))
+ require.Equal(t, len(kb.keys), len(kb.buckets))
putAppKeyBuf(kb)
txgroup[0].Txn.ForeignApps = append(txgroup[0].Txn.ForeignApps, 1)
kb = txgroupToKeys(txgroup, nil, 123, [16]byte{}, 1)
require.Equal(t, 1, len(kb.keys))
- require.Equal(t, len(kb.buckets), len(kb.buckets))
+ require.Equal(t, len(kb.keys), len(kb.buckets))
putAppKeyBuf(kb)
txgroup[0].Txn.ForeignApps = append(txgroup[0].Txn.ForeignApps, 2)
kb = txgroupToKeys(txgroup, nil, 123, [16]byte{}, 1)
require.Equal(t, 2, len(kb.keys))
- require.Equal(t, len(kb.buckets), len(kb.buckets))
+ require.Equal(t, len(kb.keys), len(kb.buckets))
putAppKeyBuf(kb)
apptxn.ApplicationID = 2
txgroup = append(txgroup, transactions.SignedTxn{Txn: apptxn})
kb = txgroupToKeys(txgroup, nil, 123, [16]byte{}, 1)
require.Equal(t, 2, len(kb.keys))
- require.Equal(t, len(kb.buckets), len(kb.buckets))
+ require.Equal(t, len(kb.keys), len(kb.buckets))
+ putAppKeyBuf(kb)
+
+ // new app if from access list
+ apptxn.Access = []transactions.ResourceRef{{App: 3}}
+ txgroup = append(txgroup, transactions.SignedTxn{Txn: apptxn})
+ kb = txgroupToKeys(txgroup, nil, 123, [16]byte{}, 1)
+ require.Equal(t, 3, len(kb.keys))
+ require.Equal(t, len(kb.keys), len(kb.buckets))
+ putAppKeyBuf(kb)
+
+ // known app id in access list
+ apptxn.Access = []transactions.ResourceRef{{App: 3}, {App: 2}}
+ txgroup = append(txgroup, transactions.SignedTxn{Txn: apptxn})
+ kb = txgroupToKeys(txgroup, nil, 123, [16]byte{}, 1)
+ require.Equal(t, 3, len(kb.keys))
+ require.Equal(t, len(kb.keys), len(kb.buckets))
putAppKeyBuf(kb)
}
diff --git a/data/basics/address.go b/data/basics/address.go
index c34a800860..f9f69aa740 100644
--- a/data/basics/address.go
+++ b/data/basics/address.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/address_test.go b/data/basics/address_test.go
index ca07315611..e4b5c62845 100644
--- a/data/basics/address_test.go
+++ b/data/basics/address_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/fields_test.go b/data/basics/fields_test.go
index 48717fc20e..fe6b1bc981 100644
--- a/data/basics/fields_test.go
+++ b/data/basics/fields_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/fraction.go b/data/basics/fraction.go
index 736357f8f2..bd57124fd4 100644
--- a/data/basics/fraction.go
+++ b/data/basics/fraction.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/fraction_test.go b/data/basics/fraction_test.go
index d1f2e9738a..02f61b8a30 100644
--- a/data/basics/fraction_test.go
+++ b/data/basics/fraction_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/msgp_gen.go b/data/basics/msgp_gen.go
index aa35233b2a..9234d2d789 100644
--- a/data/basics/msgp_gen.go
+++ b/data/basics/msgp_gen.go
@@ -1,7 +1,7 @@
-package basics
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package basics
+
import (
"sort"
@@ -1501,7 +1501,7 @@ func (z *AccountData) MsgIsZero() bool {
return ((*z).Status == 0) && ((*z).MicroAlgos.MsgIsZero()) && ((*z).RewardsBase == 0) && ((*z).RewardedMicroAlgos.MsgIsZero()) && ((*z).VoteID.MsgIsZero()) && ((*z).SelectionID.MsgIsZero()) && ((*z).StateProofID.MsgIsZero()) && ((*z).VoteFirstValid == 0) && ((*z).VoteLastValid == 0) && ((*z).VoteKeyDilution == 0) && ((*z).LastProposed == 0) && ((*z).LastHeartbeat == 0) && (len((*z).AssetParams) == 0) && (len((*z).Assets) == 0) && ((*z).AuthAddr.MsgIsZero()) && ((*z).IncentiveEligible == false) && (len((*z).AppLocalStates) == 0) && (len((*z).AppParams) == 0) && (((*z).TotalAppSchema.NumUint == 0) && ((*z).TotalAppSchema.NumByteSlice == 0)) && ((*z).TotalExtraAppPages == 0) && ((*z).TotalBoxes == 0) && ((*z).TotalBoxBytes == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// AccountDataMaxSize returns a maximum valid message size for this message type
func AccountDataMaxSize() (s int) {
s = 3 + 4 + msgp.ByteSize + 5 + MicroAlgosMaxSize() + 6 + msgp.Uint64Size + 4 + MicroAlgosMaxSize() + 5 + crypto.OneTimeSignatureVerifierMaxSize() + 4 + crypto.VRFVerifierMaxSize() + 6 + merklesignature.CommitmentMaxSize() + 8 + msgp.Uint64Size + 8 + msgp.Uint64Size + 7 + msgp.Uint64Size + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 5
s += msgp.MapHeaderSize
@@ -1563,7 +1563,7 @@ func (z *Address) MsgIsZero() bool {
return ((*(crypto.Digest))(z)).MsgIsZero()
}
-// MaxSize returns a maximum valid message size for this message type
+// crypto.DigestMaxSize returns a maximum valid message size for this message type
func AddressMaxSize() int {
return crypto.DigestMaxSize()
}
@@ -1622,7 +1622,7 @@ func (z AppIndex) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// AppIndexMaxSize returns a maximum valid message size for this message type
func AppIndexMaxSize() (s int) {
s = msgp.Uint64Size
return
@@ -1993,7 +1993,7 @@ func (z *AppLocalState) MsgIsZero() bool {
return (((*z).Schema.NumUint == 0) && ((*z).Schema.NumByteSlice == 0)) && (len((*z).KeyValue) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// AppLocalStateMaxSize returns a maximum valid message size for this message type
func AppLocalStateMaxSize() (s int) {
s = 1 + 5 + 1 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 4
s += msgp.MapHeaderSize
@@ -2008,8 +2008,8 @@ func AppLocalStateMaxSize() (s int) {
func (z *AppParams) MarshalMsg(b []byte) (o []byte) {
o = msgp.Require(b, z.Msgsize())
// omitempty: check for empty values
- zb0003Len := uint32(7)
- var zb0003Mask uint16 /* 9 bits */
+ zb0003Len := uint32(8)
+ var zb0003Mask uint16 /* 10 bits */
if len((*z).ApprovalProgram) == 0 {
zb0003Len--
zb0003Mask |= 0x4
@@ -2034,10 +2034,14 @@ func (z *AppParams) MarshalMsg(b []byte) (o []byte) {
zb0003Len--
zb0003Mask |= 0x80
}
- if (*z).Version == 0 {
+ if (*z).SizeSponsor.MsgIsZero() {
zb0003Len--
zb0003Mask |= 0x100
}
+ if (*z).Version == 0 {
+ zb0003Len--
+ zb0003Mask |= 0x200
+ }
// variable map header, size zb0003Len
o = append(o, 0x80|uint8(zb0003Len))
if zb0003Len != 0 {
@@ -2131,6 +2135,11 @@ func (z *AppParams) MarshalMsg(b []byte) (o []byte) {
}
}
if (zb0003Mask & 0x100) == 0 { // if not empty
+ // string "ss"
+ o = append(o, 0xa2, 0x73, 0x73)
+ o = (*z).SizeSponsor.MarshalMsg(o)
+ }
+ if (zb0003Mask & 0x200) == 0 { // if not empty
// string "v"
o = append(o, 0xa1, 0x76)
o = msgp.AppendUint64(o, (*z).Version)
@@ -2394,6 +2403,14 @@ func (z *AppParams) UnmarshalMsgWithState(bts []byte, st msgp.UnmarshalState) (o
return
}
}
+ if zb0003 > 0 {
+ zb0003--
+ bts, err = (*z).SizeSponsor.UnmarshalMsgWithState(bts, st)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SizeSponsor")
+ return
+ }
+ }
if zb0003 > 0 {
err = msgp.ErrTooManyArrayFields(zb0003)
if err != nil {
@@ -2635,6 +2652,12 @@ func (z *AppParams) UnmarshalMsgWithState(bts []byte, st msgp.UnmarshalState) (o
err = msgp.WrapError(err, "Version")
return
}
+ case "ss":
+ bts, err = (*z).SizeSponsor.UnmarshalMsgWithState(bts, st)
+ if err != nil {
+ err = msgp.WrapError(err, "SizeSponsor")
+ return
+ }
default:
err = msgp.ErrNoField(string(field))
if err != nil {
@@ -2666,16 +2689,16 @@ func (z *AppParams) Msgsize() (s int) {
s += 0 + msgp.StringPrefixSize + len(zb0001) + zb0002.Msgsize()
}
}
- s += 5 + 1 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 5 + 1 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 4 + msgp.Uint32Size + 2 + msgp.Uint64Size
+ s += 5 + 1 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 5 + 1 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 4 + msgp.Uint32Size + 2 + msgp.Uint64Size + 3 + (*z).SizeSponsor.Msgsize()
return
}
// MsgIsZero returns whether this is a zero value
func (z *AppParams) MsgIsZero() bool {
- return (len((*z).ApprovalProgram) == 0) && (len((*z).ClearStateProgram) == 0) && (len((*z).GlobalState) == 0) && (((*z).StateSchemas.LocalStateSchema.NumUint == 0) && ((*z).StateSchemas.LocalStateSchema.NumByteSlice == 0)) && (((*z).StateSchemas.GlobalStateSchema.NumUint == 0) && ((*z).StateSchemas.GlobalStateSchema.NumByteSlice == 0)) && ((*z).ExtraProgramPages == 0) && ((*z).Version == 0)
+ return (len((*z).ApprovalProgram) == 0) && (len((*z).ClearStateProgram) == 0) && (len((*z).GlobalState) == 0) && (((*z).StateSchemas.LocalStateSchema.NumUint == 0) && ((*z).StateSchemas.LocalStateSchema.NumByteSlice == 0)) && (((*z).StateSchemas.GlobalStateSchema.NumUint == 0) && ((*z).StateSchemas.GlobalStateSchema.NumByteSlice == 0)) && ((*z).ExtraProgramPages == 0) && ((*z).Version == 0) && ((*z).SizeSponsor.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// AppParamsMaxSize returns a maximum valid message size for this message type
func AppParamsMaxSize() (s int) {
s = 1 + 7 + msgp.BytesPrefixSize + bounds.MaxAvailableAppProgramLen + 7 + msgp.BytesPrefixSize + bounds.MaxAvailableAppProgramLen + 3
s += msgp.MapHeaderSize
@@ -2683,7 +2706,7 @@ func AppParamsMaxSize() (s int) {
s += bounds.EncodedMaxKeyValueEntries * (msgp.StringPrefixSize + bounds.MaxAppBytesKeyLen)
// Adding size of map values for z.GlobalState
s += bounds.EncodedMaxKeyValueEntries * (TealValueMaxSize())
- s += 5 + 1 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 5 + 1 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 4 + msgp.Uint32Size + 2 + msgp.Uint64Size
+ s += 5 + 1 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 5 + 1 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 4 + msgp.Uint32Size + 2 + msgp.Uint64Size + 3 + AddressMaxSize()
return
}
@@ -2824,7 +2847,7 @@ func (z *AssetHolding) MsgIsZero() bool {
return ((*z).Amount == 0) && ((*z).Frozen == false)
}
-// MaxSize returns a maximum valid message size for this message type
+// AssetHoldingMaxSize returns a maximum valid message size for this message type
func AssetHoldingMaxSize() (s int) {
s = 1 + 2 + msgp.Uint64Size + 2 + msgp.BoolSize
return
@@ -2884,7 +2907,7 @@ func (z AssetIndex) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// AssetIndexMaxSize returns a maximum valid message size for this message type
func AssetIndexMaxSize() (s int) {
s = msgp.Uint64Size
return
@@ -3294,7 +3317,7 @@ func (z *AssetParams) MsgIsZero() bool {
return ((*z).Total == 0) && ((*z).Decimals == 0) && ((*z).DefaultFrozen == false) && ((*z).UnitName == "") && ((*z).AssetName == "") && ((*z).URL == "") && ((*z).MetadataHash == ([32]byte{})) && ((*z).Manager.MsgIsZero()) && ((*z).Reserve.MsgIsZero()) && ((*z).Freeze.MsgIsZero()) && ((*z).Clawback.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// AssetParamsMaxSize returns a maximum valid message size for this message type
func AssetParamsMaxSize() (s int) {
s = 1 + 2 + msgp.Uint64Size + 3 + msgp.Uint32Size + 3 + msgp.BoolSize + 3 + msgp.StringPrefixSize + bounds.MaxAssetUnitNameBytes + 3 + msgp.StringPrefixSize + bounds.MaxAssetNameBytes + 3 + msgp.StringPrefixSize + bounds.MaxAssetURLBytes + 3
// Calculating size of array: z.MetadataHash
@@ -4581,7 +4604,7 @@ func (z *BalanceRecord) MsgIsZero() bool {
return ((*z).Addr.MsgIsZero()) && ((*z).AccountData.Status == 0) && ((*z).AccountData.MicroAlgos.MsgIsZero()) && ((*z).AccountData.RewardsBase == 0) && ((*z).AccountData.RewardedMicroAlgos.MsgIsZero()) && ((*z).AccountData.VoteID.MsgIsZero()) && ((*z).AccountData.SelectionID.MsgIsZero()) && ((*z).AccountData.StateProofID.MsgIsZero()) && ((*z).AccountData.VoteFirstValid == 0) && ((*z).AccountData.VoteLastValid == 0) && ((*z).AccountData.VoteKeyDilution == 0) && ((*z).AccountData.LastProposed == 0) && ((*z).AccountData.LastHeartbeat == 0) && (len((*z).AccountData.AssetParams) == 0) && (len((*z).AccountData.Assets) == 0) && ((*z).AccountData.AuthAddr.MsgIsZero()) && ((*z).AccountData.IncentiveEligible == false) && (len((*z).AccountData.AppLocalStates) == 0) && (len((*z).AccountData.AppParams) == 0) && (((*z).AccountData.TotalAppSchema.NumUint == 0) && ((*z).AccountData.TotalAppSchema.NumByteSlice == 0)) && ((*z).AccountData.TotalExtraAppPages == 0) && ((*z).AccountData.TotalBoxes == 0) && ((*z).AccountData.TotalBoxBytes == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// BalanceRecordMaxSize returns a maximum valid message size for this message type
func BalanceRecordMaxSize() (s int) {
s = 3 + 5 + AddressMaxSize() + 4 + msgp.ByteSize + 5 + MicroAlgosMaxSize() + 6 + msgp.Uint64Size + 4 + MicroAlgosMaxSize() + 5 + crypto.OneTimeSignatureVerifierMaxSize() + 4 + crypto.VRFVerifierMaxSize() + 6 + merklesignature.CommitmentMaxSize() + 8 + msgp.Uint64Size + 8 + msgp.Uint64Size + 7 + msgp.Uint64Size + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 5
s += msgp.MapHeaderSize
@@ -4666,7 +4689,7 @@ func (z CreatableIndex) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// CreatableIndexMaxSize returns a maximum valid message size for this message type
func CreatableIndexMaxSize() (s int) {
s = msgp.Uint64Size
return
@@ -4726,7 +4749,7 @@ func (z CreatableType) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// CreatableTypeMaxSize returns a maximum valid message size for this message type
func CreatableTypeMaxSize() (s int) {
s = msgp.Uint64Size
return
@@ -4786,7 +4809,7 @@ func (z DeltaAction) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// DeltaActionMaxSize returns a maximum valid message size for this message type
func DeltaActionMaxSize() (s int) {
s = msgp.Uint64Size
return
@@ -4929,7 +4952,7 @@ func (z *Participant) MsgIsZero() bool {
return ((*z).PK.MsgIsZero()) && ((*z).Weight == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// ParticipantMaxSize returns a maximum valid message size for this message type
func ParticipantMaxSize() (s int) {
s = 1 + 2 + merklesignature.VerifierMaxSize() + 2 + msgp.Uint64Size
return
@@ -4989,7 +5012,7 @@ func (z Round) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// RoundMaxSize returns a maximum valid message size for this message type
func RoundMaxSize() (s int) {
s = msgp.Uint64Size
return
@@ -5049,7 +5072,7 @@ func (z RoundInterval) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// RoundIntervalMaxSize returns a maximum valid message size for this message type
func RoundIntervalMaxSize() (s int) {
s = msgp.Uint64Size
return
@@ -5155,7 +5178,7 @@ func (z StateDelta) MsgIsZero() bool {
return len(z) == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// StateDeltaMaxSize returns a maximum valid message size for this message type
func StateDeltaMaxSize() (s int) {
s += msgp.MapHeaderSize
// Adding size of map keys for z
@@ -5302,7 +5325,7 @@ func (z *StateSchema) MsgIsZero() bool {
return ((*z).NumUint == 0) && ((*z).NumByteSlice == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// StateSchemaMaxSize returns a maximum valid message size for this message type
func StateSchemaMaxSize() (s int) {
s = 1 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size
return
@@ -5745,7 +5768,7 @@ func (z *StateSchemas) MsgIsZero() bool {
return (((*z).LocalStateSchema.NumUint == 0) && ((*z).LocalStateSchema.NumByteSlice == 0)) && (((*z).GlobalStateSchema.NumUint == 0) && ((*z).GlobalStateSchema.NumByteSlice == 0))
}
-// MaxSize returns a maximum valid message size for this message type
+// StateSchemasMaxSize returns a maximum valid message size for this message type
func StateSchemasMaxSize() (s int) {
s = 1 + 5 + 1 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size + 5 + 1 + 4 + msgp.Uint64Size + 4 + msgp.Uint64Size
return
@@ -5805,7 +5828,7 @@ func (z Status) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// StatusMaxSize returns a maximum valid message size for this message type
func StatusMaxSize() (s int) {
s = msgp.ByteSize
return
@@ -5911,7 +5934,7 @@ func (z TealKeyValue) MsgIsZero() bool {
return len(z) == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// TealKeyValueMaxSize returns a maximum valid message size for this message type
func TealKeyValueMaxSize() (s int) {
s += msgp.MapHeaderSize
// Adding size of map keys for z
@@ -5975,7 +5998,7 @@ func (z TealType) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// TealTypeMaxSize returns a maximum valid message size for this message type
func TealTypeMaxSize() (s int) {
s = msgp.Uint64Size
return
@@ -6149,7 +6172,7 @@ func (z *TealValue) MsgIsZero() bool {
return ((*z).Type == 0) && ((*z).Bytes == "") && ((*z).Uint == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// TealValueMaxSize returns a maximum valid message size for this message type
func TealValueMaxSize() (s int) {
s = 1 + 3 + msgp.Uint64Size + 3
panic("Unable to determine max size: String type z.Bytes is unbounded")
@@ -6343,7 +6366,7 @@ func (z *ValueDelta) MsgIsZero() bool {
return ((*z).Action == 0) && ((*z).Bytes == "") && ((*z).Uint == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// ValueDeltaMaxSize returns a maximum valid message size for this message type
func ValueDeltaMaxSize() (s int) {
s = 1 + 3 + msgp.Uint64Size + 3 + msgp.StringPrefixSize + bounds.MaxAppBytesValueLen + 3 + msgp.Uint64Size
return
diff --git a/data/basics/msgp_gen_test.go b/data/basics/msgp_gen_test.go
index c5e0f3d4a5..91677e8f1f 100644
--- a/data/basics/msgp_gen_test.go
+++ b/data/basics/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package basics
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package basics
+
import (
"testing"
diff --git a/data/basics/overflow.go b/data/basics/overflow.go
index 17ae0b6769..215f4ce75d 100644
--- a/data/basics/overflow.go
+++ b/data/basics/overflow.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/serr.go b/data/basics/serr.go
index 4e767a8bde..7c7a85e2b3 100644
--- a/data/basics/serr.go
+++ b/data/basics/serr.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/serr_test.go b/data/basics/serr_test.go
index 1a9b3d336b..90f8a9b6d6 100644
--- a/data/basics/serr_test.go
+++ b/data/basics/serr_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/sort.go b/data/basics/sort.go
index f6e3ddccbe..54b726f7b0 100644
--- a/data/basics/sort.go
+++ b/data/basics/sort.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/stateProofParticipant.go b/data/basics/stateProofParticipant.go
index b2f2c180e0..9bfc00646d 100644
--- a/data/basics/stateProofParticipant.go
+++ b/data/basics/stateProofParticipant.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/teal.go b/data/basics/teal.go
index a2b340c325..b99d7b99ed 100644
--- a/data/basics/teal.go
+++ b/data/basics/teal.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -87,6 +87,16 @@ type StateSchema struct {
NumByteSlice uint64 `codec:"nbs"`
}
+// String returns a string representation of a StateSchema
+func (sm StateSchema) String() string {
+ return fmt.Sprintf("{NumUint:%d NumByteSlice:%d}", sm.NumUint, sm.NumByteSlice)
+}
+
+// Empty returns true if the StateSchema has no entries
+func (sm StateSchema) Empty() bool {
+ return sm.NumUint == 0 && sm.NumByteSlice == 0
+}
+
// AddSchema adds two StateSchemas together
func (sm StateSchema) AddSchema(osm StateSchema) (out StateSchema) {
out.NumUint = AddSaturate(sm.NumUint, osm.NumUint)
@@ -102,10 +112,13 @@ func (sm StateSchema) SubSchema(osm StateSchema) (out StateSchema) {
}
// NumEntries counts the total number of values that may be stored for particular schema
-func (sm StateSchema) NumEntries() (tot uint64) {
- tot = AddSaturate(tot, sm.NumUint)
- tot = AddSaturate(tot, sm.NumByteSlice)
- return tot
+func (sm StateSchema) NumEntries() uint64 {
+ return AddSaturate(sm.NumUint, sm.NumByteSlice)
+}
+
+// Allows determines if `other` "fits" within this schema.
+func (sm StateSchema) Allows(other StateSchema) bool {
+ return other.NumUint <= sm.NumUint && other.NumByteSlice <= sm.NumByteSlice
}
// MinBalance computes the MinBalance requirements for a StateSchema based on
diff --git a/data/basics/teal_test.go b/data/basics/teal_test.go
index 50b0501e49..6a711085be 100644
--- a/data/basics/teal_test.go
+++ b/data/basics/teal_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/commandandcontrol/lib/ccCommon.go b/data/basics/testing/copiers.go
similarity index 66%
rename from test/commandandcontrol/lib/ccCommon.go
rename to data/basics/testing/copiers.go
index 3bd9dc779d..742e8875f3 100644
--- a/test/commandandcontrol/lib/ccCommon.go
+++ b/data/basics/testing/copiers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -14,12 +14,17 @@
// You should have received a copy of the GNU Affero General Public License
// along with go-algorand. If not, see .
-package lib
+package testing
-// CCServiceRequest object for receiving commands from the client
-type CCServiceRequest struct {
- Component string `json:"component"`
- Command string `json:"command"`
- Parameters string `json:"parameters"`
- TargetAgentList []string `json:"targetAgentList"`
+import (
+ "reflect"
+ "testing"
+)
+
+// RoundTrip checks that converting an A -> B -> A gives the original value.
+// Returns true if equal, false otherwise.
+func RoundTrip[A any, B any](t *testing.T, a A, toB func(A) B, toA func(B) A) bool {
+ b := toB(a)
+ a2 := toA(b)
+ return reflect.DeepEqual(a, a2)
}
diff --git a/data/basics/testing/nearzero.go b/data/basics/testing/nearzero.go
index e073cea496..e54c456781 100644
--- a/data/basics/testing/nearzero.go
+++ b/data/basics/testing/nearzero.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -27,7 +27,7 @@ import (
// the same type in which each element of the slice is the same type as the
// sample, but exactly one field (or sub-field) is set to a non-zero value. It
// returns one example for every sub-field.
-func NearZeros(t *testing.T, sample any) []any {
+func NearZeros[T any](t *testing.T, sample T) []T {
typ := reflect.TypeOf(sample)
// If sample is a pointer, work with the underlying type.
if typ.Kind() == reflect.Ptr {
@@ -37,10 +37,10 @@ func NearZeros(t *testing.T, sample any) []any {
t.Fatalf("NearZeros: sample must be a struct, got %s", typ.Kind())
}
paths := collectPaths(typ, nil, nil)
- var results []any
+ var results []T
for _, path := range paths {
inst := makeInstanceWithNonZeroField(typ, path)
- results = append(results, inst)
+ results = append(results, inst.(T))
}
return results
}
diff --git a/data/basics/testing/nearzero_test.go b/data/basics/testing/nearzero_test.go
index eb22932b5f..ef47b13096 100644
--- a/data/basics/testing/nearzero_test.go
+++ b/data/basics/testing/nearzero_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -58,8 +58,7 @@ func TestNearZeros(t *testing.T) {
// Show that Two is allocated (twice, once for I, once for J)
count := 0
- for _, nz := range NearZeros(t, four{}) {
- f := nz.(four)
+ for _, f := range NearZeros(t, four{}) {
if f.Two != nil {
count++
}
@@ -76,8 +75,7 @@ func TestNearZeros(t *testing.T) {
// Show that Slice is allocated once
count = 0
- for _, nz := range NearZeros(t, five{}) {
- f := nz.(five)
+ for _, f := range NearZeros(t, five{}) {
if f.Slice != nil {
count++
}
@@ -94,8 +92,7 @@ func TestNearZeros(t *testing.T) {
// Show that Slice2 is allocated twice, in order to fill Slice2[0].{I,J}
count = 0
- for _, nz := range NearZeros(t, six{}) {
- f := nz.(six)
+ for _, f := range NearZeros(t, six{}) {
if f.Slice2 != nil {
count++
a.True(f.Slice2[0].I > 0 || f.Slice2[0].J > 0)
@@ -123,18 +120,18 @@ func TestMap(t *testing.T) {
A map[int]int
}
assert.Len(t, NearZeros(t, mapint{}), 1)
- assert.Zero(t, NearZeros(t, mapint{})[0].(mapint).A[1])
+ assert.Zero(t, NearZeros(t, mapint{})[0].A[1])
type mapstring struct {
A map[int]string
}
assert.Len(t, NearZeros(t, mapstring{}), 1)
- assert.Zero(t, NearZeros(t, mapstring{})[0].(mapstring).A[1])
+ assert.Zero(t, NearZeros(t, mapstring{})[0].A[1])
type mapstruct2 struct {
A map[int]struct{ A, B, C int }
}
assert.Len(t, NearZeros(t, mapstruct2{}), 1)
- assert.Len(t, NearZeros(t, mapstruct2{})[0].(mapstruct2).A, 1)
- assert.Zero(t, NearZeros(t, mapstruct2{})[0].(mapstruct2).A[1])
+ assert.Len(t, NearZeros(t, mapstruct2{})[0].A, 1)
+ assert.Zero(t, NearZeros(t, mapstruct2{})[0].A[1])
}
diff --git a/data/basics/testing/userBalance.go b/data/basics/testing/userBalance.go
index f12737c767..70ff66d9e1 100644
--- a/data/basics/testing/userBalance.go
+++ b/data/basics/testing/userBalance.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/testing/userBalance_test.go b/data/basics/testing/userBalance_test.go
index 38bef08bea..6a68f9b40a 100644
--- a/data/basics/testing/userBalance_test.go
+++ b/data/basics/testing/userBalance_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/units.go b/data/basics/units.go
index 2934936feb..b78e27de20 100644
--- a/data/basics/units.go
+++ b/data/basics/units.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/units_test.go b/data/basics/units_test.go
index 6ea36f2b05..8bd3ee6667 100644
--- a/data/basics/units_test.go
+++ b/data/basics/units_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/basics/userBalance.go b/data/basics/userBalance.go
index 4ad24579b1..d4fe5b98e7 100644
--- a/data/basics/userBalance.go
+++ b/data/basics/userBalance.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -250,6 +250,10 @@ type AppParams struct {
StateSchemas
ExtraProgramPages uint32 `codec:"epp"`
Version uint64 `codec:"v"`
+
+ // SizeSponsor, if non-zero, is the account that must hold MBR for
+ // extra program pages, and the global schema.
+ SizeSponsor Address `codec:"ss"`
}
// StateSchemas is a thin wrapper around the LocalStateSchema and the
diff --git a/data/basics/userBalance_test.go b/data/basics/userBalance_test.go
index 4cb93340e7..5e4791193a 100644
--- a/data/basics/userBalance_test.go
+++ b/data/basics/userBalance_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/bookkeeping/block.go b/data/bookkeeping/block.go
index c305ae6ffc..427ef355c5 100644
--- a/data/bookkeeping/block.go
+++ b/data/bookkeeping/block.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -110,7 +110,7 @@ type BlockHeader struct {
// Each block is associated with at most one active upgrade proposal
// (a new version of the protocol). An upgrade proposal can be made
// by a block proposer, as long as no other upgrade proposal is active.
- // The upgrade proposal lasts for many rounds (UpgradeVoteRounds), and
+ // The upgrade proposal lasts for consensus.UpgradeVoteRounds, and
// in each round, that round's block proposer votes to support (or not)
// the proposed upgrade.
//
@@ -232,7 +232,7 @@ type UpgradeState struct {
NextProtocol protocol.ConsensusVersion `codec:"nextproto"`
// NextProtocolApprovals is the number of approvals for the next protocol proposal. It is expressed in basics.Round because it is a count of rounds.
NextProtocolApprovals basics.Round `codec:"nextyes"`
- // NextProtocolVoteBefore specify the last voting round for the next protocol proposal. If there is no voting for
+ // NextProtocolVoteBefore specifies the last voting round for the next protocol proposal. If there is no voting for
// an upgrade taking place, this would be zero.
NextProtocolVoteBefore basics.Round `codec:"nextbefore"`
// NextProtocolSwitchOn specify the round number at which the next protocol would be adopted. If there is no upgrade taking place,
diff --git a/data/bookkeeping/block_test.go b/data/bookkeeping/block_test.go
index 367e27b157..1a556a5f90 100644
--- a/data/bookkeeping/block_test.go
+++ b/data/bookkeeping/block_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/bookkeeping/encoding_test.go b/data/bookkeeping/encoding_test.go
index 3de80f0ea6..94a52e24f8 100644
--- a/data/bookkeeping/encoding_test.go
+++ b/data/bookkeeping/encoding_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -54,9 +54,7 @@ func TestBlockWithTxnEncoding(t *testing.T) {
var b Block
b.Payset = []transactions.SignedTxnInBlock{
{
- SignedTxnWithAD: transactions.SignedTxnWithAD{
- SignedTxn: sigtxn,
- },
+ SignedTxnWithAD: sigtxn.WithAD(),
},
}
enc := protocol.Encode(&b)
diff --git a/data/bookkeeping/genesis.go b/data/bookkeeping/genesis.go
index 5951354ad8..48a90427ac 100644
--- a/data/bookkeeping/genesis.go
+++ b/data/bookkeeping/genesis.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/bookkeeping/genesis_test.go b/data/bookkeeping/genesis_test.go
index 3e930ea9e6..9312f25dc6 100644
--- a/data/bookkeeping/genesis_test.go
+++ b/data/bookkeeping/genesis_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/bookkeeping/lightBlockHeader.go b/data/bookkeeping/lightBlockHeader.go
index 9e6e0462b8..49c9f6c09d 100644
--- a/data/bookkeeping/lightBlockHeader.go
+++ b/data/bookkeeping/lightBlockHeader.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/bookkeeping/lightBlockHeader_test.go b/data/bookkeeping/lightBlockHeader_test.go
index 7e8cf04b1d..ad8600307a 100644
--- a/data/bookkeeping/lightBlockHeader_test.go
+++ b/data/bookkeeping/lightBlockHeader_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/bookkeeping/msgp_gen.go b/data/bookkeeping/msgp_gen.go
index 32fe332eae..25745c831a 100644
--- a/data/bookkeeping/msgp_gen.go
+++ b/data/bookkeeping/msgp_gen.go
@@ -1,7 +1,7 @@
-package bookkeeping
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package bookkeeping
+
import (
"sort"
@@ -1194,7 +1194,7 @@ func (z *Block) MsgIsZero() bool {
return ((*z).BlockHeader.Round.MsgIsZero()) && ((*z).BlockHeader.Branch.MsgIsZero()) && ((*z).BlockHeader.Branch512.MsgIsZero()) && ((*z).BlockHeader.Seed.MsgIsZero()) && ((*z).BlockHeader.TxnCommitments.NativeSha512_256Commitment.MsgIsZero()) && ((*z).BlockHeader.TxnCommitments.Sha256Commitment.MsgIsZero()) && ((*z).BlockHeader.TxnCommitments.Sha512Commitment.MsgIsZero()) && ((*z).BlockHeader.TimeStamp == 0) && ((*z).BlockHeader.GenesisID == "") && ((*z).BlockHeader.GenesisHash.MsgIsZero()) && ((*z).BlockHeader.Proposer.MsgIsZero()) && ((*z).BlockHeader.FeesCollected.MsgIsZero()) && ((*z).BlockHeader.Bonus.MsgIsZero()) && ((*z).BlockHeader.ProposerPayout.MsgIsZero()) && ((*z).BlockHeader.RewardsState.FeeSink.MsgIsZero()) && ((*z).BlockHeader.RewardsState.RewardsPool.MsgIsZero()) && ((*z).BlockHeader.RewardsState.RewardsLevel == 0) && ((*z).BlockHeader.RewardsState.RewardsRate == 0) && ((*z).BlockHeader.RewardsState.RewardsResidue == 0) && ((*z).BlockHeader.RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.NextProtocol.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.NextProtocolApprovals.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).BlockHeader.UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).BlockHeader.UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).BlockHeader.UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).BlockHeader.UpgradeVote.UpgradeApprove == false) && ((*z).BlockHeader.TxnCounter == 0) && (len((*z).BlockHeader.StateProofTracking) == 0) && (len((*z).BlockHeader.ParticipationUpdates.ExpiredParticipationAccounts) == 0) && (len((*z).BlockHeader.ParticipationUpdates.AbsentParticipationAccounts) == 0) && ((*z).Payset.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// BlockMaxSize returns a maximum valid message size for this message type
func BlockMaxSize() (s int) {
s = 3 + 4 + basics.RoundMaxSize() + 5 + BlockHashMaxSize() + 8 + crypto.Sha512DigestMaxSize() + 5 + committee.SeedMaxSize() + 4 + crypto.DigestMaxSize() + 7 + crypto.DigestMaxSize() + 7 + crypto.Sha512DigestMaxSize() + 3 + msgp.Int64Size + 4 + msgp.StringPrefixSize + bounds.MaxGenesisIDLen + 3 + crypto.DigestMaxSize() + 4 + basics.AddressMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 5 + basics.AddressMaxSize() + 4 + basics.AddressMaxSize() + 5 + msgp.Uint64Size + 5 + msgp.Uint64Size + 5 + msgp.Uint64Size + 7 + basics.RoundMaxSize() + 6 + protocol.ConsensusVersionMaxSize() + 10 + protocol.ConsensusVersionMaxSize() + 8 + basics.RoundMaxSize() + 11 + basics.RoundMaxSize() + 11 + basics.RoundMaxSize() + 12 + protocol.ConsensusVersionMaxSize() + 13 + basics.RoundMaxSize() + 11 + msgp.BoolSize + 3 + msgp.Uint64Size + 4
s += msgp.MapHeaderSize
@@ -1245,7 +1245,7 @@ func (z *BlockHash) MsgIsZero() bool {
return ((*(crypto.Digest))(z)).MsgIsZero()
}
-// MaxSize returns a maximum valid message size for this message type
+// crypto.DigestMaxSize returns a maximum valid message size for this message type
func BlockHashMaxSize() int {
return crypto.DigestMaxSize()
}
@@ -2281,7 +2281,7 @@ func (z *BlockHeader) MsgIsZero() bool {
return ((*z).Round.MsgIsZero()) && ((*z).Branch.MsgIsZero()) && ((*z).Branch512.MsgIsZero()) && ((*z).Seed.MsgIsZero()) && ((*z).TxnCommitments.NativeSha512_256Commitment.MsgIsZero()) && ((*z).TxnCommitments.Sha256Commitment.MsgIsZero()) && ((*z).TxnCommitments.Sha512Commitment.MsgIsZero()) && ((*z).TimeStamp == 0) && ((*z).GenesisID == "") && ((*z).GenesisHash.MsgIsZero()) && ((*z).Proposer.MsgIsZero()) && ((*z).FeesCollected.MsgIsZero()) && ((*z).Bonus.MsgIsZero()) && ((*z).ProposerPayout.MsgIsZero()) && ((*z).RewardsState.FeeSink.MsgIsZero()) && ((*z).RewardsState.RewardsPool.MsgIsZero()) && ((*z).RewardsState.RewardsLevel == 0) && ((*z).RewardsState.RewardsRate == 0) && ((*z).RewardsState.RewardsResidue == 0) && ((*z).RewardsState.RewardsRecalculationRound.MsgIsZero()) && ((*z).UpgradeState.CurrentProtocol.MsgIsZero()) && ((*z).UpgradeState.NextProtocol.MsgIsZero()) && ((*z).UpgradeState.NextProtocolApprovals.MsgIsZero()) && ((*z).UpgradeState.NextProtocolVoteBefore.MsgIsZero()) && ((*z).UpgradeState.NextProtocolSwitchOn.MsgIsZero()) && ((*z).UpgradeVote.UpgradePropose.MsgIsZero()) && ((*z).UpgradeVote.UpgradeDelay.MsgIsZero()) && ((*z).UpgradeVote.UpgradeApprove == false) && ((*z).TxnCounter == 0) && (len((*z).StateProofTracking) == 0) && (len((*z).ParticipationUpdates.ExpiredParticipationAccounts) == 0) && (len((*z).ParticipationUpdates.AbsentParticipationAccounts) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// BlockHeaderMaxSize returns a maximum valid message size for this message type
func BlockHeaderMaxSize() (s int) {
s = 3 + 4 + basics.RoundMaxSize() + 5 + BlockHashMaxSize() + 8 + crypto.Sha512DigestMaxSize() + 5 + committee.SeedMaxSize() + 4 + crypto.DigestMaxSize() + 7 + crypto.DigestMaxSize() + 7 + crypto.Sha512DigestMaxSize() + 3 + msgp.Int64Size + 4 + msgp.StringPrefixSize + bounds.MaxGenesisIDLen + 3 + crypto.DigestMaxSize() + 4 + basics.AddressMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 5 + basics.AddressMaxSize() + 4 + basics.AddressMaxSize() + 5 + msgp.Uint64Size + 5 + msgp.Uint64Size + 5 + msgp.Uint64Size + 7 + basics.RoundMaxSize() + 6 + protocol.ConsensusVersionMaxSize() + 10 + protocol.ConsensusVersionMaxSize() + 8 + basics.RoundMaxSize() + 11 + basics.RoundMaxSize() + 11 + basics.RoundMaxSize() + 12 + protocol.ConsensusVersionMaxSize() + 13 + basics.RoundMaxSize() + 11 + msgp.BoolSize + 3 + msgp.Uint64Size + 4
s += msgp.MapHeaderSize
@@ -2649,7 +2649,7 @@ func (z *Genesis) MsgIsZero() bool {
return ((*z).SchemaID == "") && ((*z).Network.MsgIsZero()) && ((*z).Proto.MsgIsZero()) && (len((*z).Allocation) == 0) && ((*z).RewardsPool == "") && ((*z).FeeSink == "") && ((*z).Timestamp == 0) && ((*z).Comment == "") && ((*z).DevMode == false)
}
-// MaxSize returns a maximum valid message size for this message type
+// GenesisMaxSize returns a maximum valid message size for this message type
func GenesisMaxSize() (s int) {
s = 1 + 3
panic("Unable to determine max size: String type z.SchemaID is unbounded")
@@ -2930,7 +2930,7 @@ func (z *GenesisAccountData) MsgIsZero() bool {
return ((*z).Status.MsgIsZero()) && ((*z).MicroAlgos.MsgIsZero()) && ((*z).VoteID.MsgIsZero()) && ((*z).StateProofID.MsgIsZero()) && ((*z).SelectionID.MsgIsZero()) && ((*z).VoteFirstValid.MsgIsZero()) && ((*z).VoteLastValid.MsgIsZero()) && ((*z).VoteKeyDilution == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// GenesisAccountDataMaxSize returns a maximum valid message size for this message type
func GenesisAccountDataMaxSize() (s int) {
s = 1 + 4 + basics.StatusMaxSize() + 5 + basics.MicroAlgosMaxSize() + 5 + crypto.OneTimeSignatureVerifierMaxSize() + 6 + merklesignature.CommitmentMaxSize() + 4 + crypto.VRFVerifierMaxSize() + 8 + basics.RoundMaxSize() + 8 + basics.RoundMaxSize() + 7 + msgp.Uint64Size
return
@@ -3072,7 +3072,7 @@ func (z *GenesisAllocation) MsgIsZero() bool {
return ((*z).Address == "") && ((*z).Comment == "") && ((*z).State.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// GenesisAllocationMaxSize returns a maximum valid message size for this message type
func GenesisAllocationMaxSize() (s int) {
s = 1 + 5
panic("Unable to determine max size: String type z.Address is unbounded")
@@ -3284,7 +3284,7 @@ func (z *LightBlockHeader) MsgIsZero() bool {
return ((*z).Seed.MsgIsZero()) && ((*z).BlockHash.MsgIsZero()) && ((*z).Round.MsgIsZero()) && ((*z).GenesisHash.MsgIsZero()) && ((*z).Sha256TxnCommitment.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// LightBlockHeaderMaxSize returns a maximum valid message size for this message type
func LightBlockHeaderMaxSize() (s int) {
s = 1 + 2 + committee.SeedMaxSize() + 2 + BlockHashMaxSize() + 2 + basics.RoundMaxSize() + 3 + crypto.DigestMaxSize() + 3 + crypto.GenericDigestMaxSize()
return
@@ -3532,7 +3532,7 @@ func (z *ParticipationUpdates) MsgIsZero() bool {
return (len((*z).ExpiredParticipationAccounts) == 0) && (len((*z).AbsentParticipationAccounts) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// ParticipationUpdatesMaxSize returns a maximum valid message size for this message type
func ParticipationUpdatesMaxSize() (s int) {
s = 1 + 11
// Calculating size of slice: z.ExpiredParticipationAccounts
@@ -3772,7 +3772,7 @@ func (z *RewardsState) MsgIsZero() bool {
return ((*z).FeeSink.MsgIsZero()) && ((*z).RewardsPool.MsgIsZero()) && ((*z).RewardsLevel == 0) && ((*z).RewardsRate == 0) && ((*z).RewardsResidue == 0) && ((*z).RewardsRecalculationRound.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// RewardsStateMaxSize returns a maximum valid message size for this message type
func RewardsStateMaxSize() (s int) {
s = 1 + 5 + basics.AddressMaxSize() + 4 + basics.AddressMaxSize() + 5 + msgp.Uint64Size + 5 + msgp.Uint64Size + 5 + msgp.Uint64Size + 7 + basics.RoundMaxSize()
return
@@ -3938,7 +3938,7 @@ func (z *StateProofTrackingData) MsgIsZero() bool {
return ((*z).StateProofVotersCommitment.MsgIsZero()) && ((*z).StateProofOnlineTotalWeight.MsgIsZero()) && ((*z).StateProofNextRound.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// StateProofTrackingDataMaxSize returns a maximum valid message size for this message type
func StateProofTrackingDataMaxSize() (s int) {
s = 1 + 2 + crypto.GenericDigestMaxSize() + 2 + basics.MicroAlgosMaxSize() + 2 + basics.RoundMaxSize()
return
@@ -4104,7 +4104,7 @@ func (z *TxnCommitments) MsgIsZero() bool {
return ((*z).NativeSha512_256Commitment.MsgIsZero()) && ((*z).Sha256Commitment.MsgIsZero()) && ((*z).Sha512Commitment.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// TxnCommitmentsMaxSize returns a maximum valid message size for this message type
func TxnCommitmentsMaxSize() (s int) {
s = 1 + 4 + crypto.DigestMaxSize() + 7 + crypto.DigestMaxSize() + 7 + crypto.Sha512DigestMaxSize()
return
@@ -4270,7 +4270,7 @@ func (z *UpgradeVote) MsgIsZero() bool {
return ((*z).UpgradePropose.MsgIsZero()) && ((*z).UpgradeDelay.MsgIsZero()) && ((*z).UpgradeApprove == false)
}
-// MaxSize returns a maximum valid message size for this message type
+// UpgradeVoteMaxSize returns a maximum valid message size for this message type
func UpgradeVoteMaxSize() (s int) {
s = 1 + 12 + protocol.ConsensusVersionMaxSize() + 13 + basics.RoundMaxSize() + 11 + msgp.BoolSize
return
diff --git a/data/bookkeeping/msgp_gen_test.go b/data/bookkeeping/msgp_gen_test.go
index b49bd7240e..7de75b670e 100644
--- a/data/bookkeeping/msgp_gen_test.go
+++ b/data/bookkeeping/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package bookkeeping
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package bookkeeping
+
import (
"testing"
diff --git a/data/bookkeeping/prettyprinting.go b/data/bookkeeping/prettyprinting.go
index dedf23c3e8..e989a834eb 100644
--- a/data/bookkeeping/prettyprinting.go
+++ b/data/bookkeeping/prettyprinting.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/bookkeeping/txn_merkle.go b/data/bookkeeping/txn_merkle.go
index 66e3d60213..6e14d59033 100644
--- a/data/bookkeeping/txn_merkle.go
+++ b/data/bookkeeping/txn_merkle.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/bookkeeping/txn_merkle_test.go b/data/bookkeeping/txn_merkle_test.go
index 6e220875b3..db9827b90e 100644
--- a/data/bookkeeping/txn_merkle_test.go
+++ b/data/bookkeeping/txn_merkle_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/committee.go b/data/committee/committee.go
index 1ba853b652..6c9a61f2b1 100644
--- a/data/committee/committee.go
+++ b/data/committee/committee.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/common_test.go b/data/committee/common_test.go
index f6dd60ecf2..246d88156b 100644
--- a/data/committee/common_test.go
+++ b/data/committee/common_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/credential.go b/data/committee/credential.go
index b09ed56200..7d6ce35b1e 100644
--- a/data/committee/credential.go
+++ b/data/committee/credential.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/credential_test.go b/data/committee/credential_test.go
index 57ce97cd38..f6d03127d6 100644
--- a/data/committee/credential_test.go
+++ b/data/committee/credential_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/encoding_test.go b/data/committee/encoding_test.go
index 5c3f659868..b15ac794f7 100644
--- a/data/committee/encoding_test.go
+++ b/data/committee/encoding_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/committee/msgp_gen.go b/data/committee/msgp_gen.go
index 9af6fdd4d8..3b67d45256 100644
--- a/data/committee/msgp_gen.go
+++ b/data/committee/msgp_gen.go
@@ -1,7 +1,7 @@
-package committee
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package committee
+
import (
"github.com/algorand/msgp/msgp"
@@ -257,7 +257,7 @@ func (z *Credential) MsgIsZero() bool {
return ((*z).Weight == 0) && ((*z).VrfOut.MsgIsZero()) && ((*z).DomainSeparationEnabled == false) && ((*z).Hashable.MsgIsZero()) && ((*z).UnauthenticatedCredential.Proof.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// CredentialMaxSize returns a maximum valid message size for this message type
func CredentialMaxSize() (s int) {
s = 1 + 3 + msgp.Uint64Size + 2 + crypto.DigestMaxSize() + 3 + msgp.BoolSize + 3 + HashableCredentialMaxSize() + 3 + crypto.VrfProofMaxSize()
return
@@ -310,7 +310,7 @@ func (z *Seed) MsgIsZero() bool {
return (*z) == (Seed{})
}
-// MaxSize returns a maximum valid message size for this message type
+// SeedMaxSize returns a maximum valid message size for this message type
func SeedMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((32) * (msgp.ByteSize))
@@ -431,7 +431,7 @@ func (z *UnauthenticatedCredential) MsgIsZero() bool {
return ((*z).Proof.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// UnauthenticatedCredentialMaxSize returns a maximum valid message size for this message type
func UnauthenticatedCredentialMaxSize() (s int) {
s = 1 + 3 + crypto.VrfProofMaxSize()
return
@@ -597,7 +597,7 @@ func (z *hashableCredential) MsgIsZero() bool {
return ((*z).RawOut.MsgIsZero()) && ((*z).Member.MsgIsZero()) && ((*z).Iter == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// HashableCredentialMaxSize returns a maximum valid message size for this message type
func HashableCredentialMaxSize() (s int) {
s = 1 + 2 + crypto.VrfOutputMaxSize() + 2 + basics.AddressMaxSize() + 2 + msgp.Uint64Size
return
diff --git a/data/committee/msgp_gen_test.go b/data/committee/msgp_gen_test.go
index fc6b79ce76..aac5f4f6b1 100644
--- a/data/committee/msgp_gen_test.go
+++ b/data/committee/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package committee
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package committee
+
import (
"testing"
diff --git a/data/common_test.go b/data/common_test.go
index 279c591fe7..8f59bb32d7 100644
--- a/data/common_test.go
+++ b/data/common_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/datatest/fabricateLedger.go b/data/datatest/fabricateLedger.go
index 4b25ca3e35..60e22604c1 100644
--- a/data/datatest/fabricateLedger.go
+++ b/data/datatest/fabricateLedger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/datatest/impls.go b/data/datatest/impls.go
index 33cdf594ce..137e4bf870 100644
--- a/data/datatest/impls.go
+++ b/data/datatest/impls.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -141,7 +141,7 @@ func (i ledgerImpl) ConsensusParams(r basics.Round) (config.ConsensusParams, err
return i.l.ConsensusParams(r)
}
-// ConsensusParams implements Ledger.ConsensusVersion.
+// ConsensusVersion implements Ledger.ConsensusVersion.
func (i ledgerImpl) ConsensusVersion(r basics.Round) (protocol.ConsensusVersion, error) {
return i.l.ConsensusVersion(r)
}
diff --git a/data/hashable/message.go b/data/hashable/message.go
index b49a99d769..aea10da7c0 100644
--- a/data/hashable/message.go
+++ b/data/hashable/message.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/hashable/msgp_gen.go b/data/hashable/msgp_gen.go
index fc20f28a28..81d05c9737 100644
--- a/data/hashable/msgp_gen.go
+++ b/data/hashable/msgp_gen.go
@@ -1,7 +1,7 @@
-package hashable
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package hashable
+
import (
"github.com/algorand/msgp/msgp"
)
@@ -132,7 +132,7 @@ func (z *Message) MsgIsZero() bool {
return ((*z).Message == "")
}
-// MaxSize returns a maximum valid message size for this message type
+// MessageMaxSize returns a maximum valid message size for this message type
func MessageMaxSize() (s int) {
s = 1 + 4
panic("Unable to determine max size: String type z.Message is unbounded")
diff --git a/data/hashable/msgp_gen_test.go b/data/hashable/msgp_gen_test.go
index 50178fac0e..173f9fc349 100644
--- a/data/hashable/msgp_gen_test.go
+++ b/data/hashable/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package hashable
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package hashable
+
import (
"testing"
diff --git a/data/ledger.go b/data/ledger.go
index 01e2065191..43594dd5f7 100644
--- a/data/ledger.go
+++ b/data/ledger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/ledger_test.go b/data/ledger_test.go
index 00d633e232..09aebcd9f7 100644
--- a/data/ledger_test.go
+++ b/data/ledger_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -190,9 +190,7 @@ func TestLedgerCirculation(t *testing.T) {
tx.Type = protocol.PaymentTx
signedTx := tx.Sign(srcAccountKey)
blk.Payset = transactions.Payset{transactions.SignedTxnInBlock{
- SignedTxnWithAD: transactions.SignedTxnWithAD{
- SignedTxn: signedTx,
- },
+ SignedTxnWithAD: signedTx.WithAD(),
}}
require.NoError(t, l.AddBlock(blk, agreement.Certificate{}))
l.WaitForCommit(rnd)
diff --git a/data/pools/errors.go b/data/pools/errors.go
index 71224c8db4..514bc19123 100644
--- a/data/pools/errors.go
+++ b/data/pools/errors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -21,6 +21,11 @@ import (
"fmt"
"github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/data/transactions/logic"
+ "github.com/algorand/go-algorand/ledger/ledgercore"
+ "github.com/algorand/go-algorand/util/metrics"
)
// ErrStaleBlockAssemblyRequest returned by AssembleBlock when requested block number is older than the current transaction pool round
@@ -45,3 +50,155 @@ func (e *ErrTxPoolFeeError) Error() string {
return fmt.Sprintf("fee %d below threshold %d (%d per byte * %d bytes)",
e.fee, e.feeThreshold, e.feePerByte, e.encodedLength)
}
+
+// TxPoolErrorTag constants for categorizing transaction pool errors.
+// These are used by both the txHandler (initial remember) and the
+// transaction pool (re-evaluation) to classify errors consistently.
+const (
+ TxPoolErrTagCap = "cap"
+ TxPoolErrTagPendingEval = "pending_eval"
+ TxPoolErrTagNoSpace = "no_space"
+ TxPoolErrTagFee = "fee"
+ TxPoolErrTagTxnDead = "txn_dead"
+ TxPoolErrTagTxnEarly = "txn_early"
+ TxPoolErrTagTooLarge = "too_large"
+ TxPoolErrTagGroupID = "groupid"
+ TxPoolErrTagTxID = "txid"
+ TxPoolErrTagLease = "lease"
+ TxPoolErrTagTxIDEval = "txid_eval"
+ TxPoolErrTagLeaseEval = "lease_eval"
+ TxPoolErrTagNotWell = "not_well" // TxnNotWellFormedError - malformed transaction
+ TxPoolErrTagTealErr = "teal_err" // TEAL runtime error (logic.EvalError)
+ TxPoolErrTagTealReject = "teal_reject" // TEAL returned false ("rejected by ApprovalProgram")
+ TxPoolErrTagMinBalance = "min_balance" // Account balance below minimum
+ TxPoolErrTagOverspend = "overspend" // Insufficient Algo funds
+ TxPoolErrTagAssetBalance = "asset_bal" // Insufficient asset balance
+ TxPoolErrTagEvalGeneric = "eval" // Other evaluation errors not matching known patterns
+)
+
+// TxPoolErrTags is the list of all error tags for use with TagCounter.
+var TxPoolErrTags = []string{
+ TxPoolErrTagCap, TxPoolErrTagPendingEval, TxPoolErrTagNoSpace, TxPoolErrTagFee,
+ TxPoolErrTagTxnDead, TxPoolErrTagTxnEarly, TxPoolErrTagTooLarge, TxPoolErrTagGroupID,
+ TxPoolErrTagTxID, TxPoolErrTagLease, TxPoolErrTagTxIDEval, TxPoolErrTagLeaseEval,
+ TxPoolErrTagNotWell, TxPoolErrTagTealErr, TxPoolErrTagTealReject,
+ TxPoolErrTagMinBalance, TxPoolErrTagOverspend, TxPoolErrTagAssetBalance, TxPoolErrTagEvalGeneric,
+}
+
+// txPoolReevalCounter tracks transaction groups that failed during block assembly
+// re-evaluation. These are transactions that were accepted into the pool but
+// failed when re-evaluated against the latest confirmed block.
+var txPoolReevalCounter = metrics.NewTagCounter(
+ "algod_tx_pool_reeval_{TAG}",
+ "Number of transaction groups removed from pool during re-evaluation due to {TAG}",
+ TxPoolErrTags...,
+)
+
+// txPoolReevalSuccess tracks transaction groups successfully re-evaluated
+// after a new block commits.
+var txPoolReevalSuccess = metrics.MakeCounter(metrics.MetricName{
+ Name: "algod_tx_pool_reeval_success",
+ Description: "Number of transaction groups successfully re-evaluated after new block",
+})
+
+// txPoolReevalCommitted tracks transaction groups removed during re-evaluation
+// because they were already committed in the latest block.
+var txPoolReevalCommitted = metrics.MakeCounter(metrics.MetricName{
+ Name: "algod_tx_pool_reeval_committed",
+ Description: "Number of transaction groups removed because already committed in latest block",
+})
+
+// ClassifyTxPoolError examines an error from BlockEvaluator.TransactionGroup
+// and returns the appropriate tag for metrics. Both errors.Is (for sentinel
+// errors) and errors.As (for typed errors) traverse wrapped error chains.
+func ClassifyTxPoolError(err error) string {
+ if err == nil {
+ return ""
+ }
+
+ // Sentinel errors (specific values)
+ if errors.Is(err, ErrPendingQueueReachedMaxCap) {
+ return TxPoolErrTagCap
+ }
+ if errors.Is(err, ErrNoPendingBlockEvaluator) {
+ return TxPoolErrTagPendingEval
+ }
+ if errors.Is(err, ledgercore.ErrNoSpace) {
+ return TxPoolErrTagNoSpace
+ }
+
+ // Typed errors
+ var feeErr *ErrTxPoolFeeError
+ if errors.As(err, &feeErr) {
+ return TxPoolErrTagFee
+ }
+
+ var minFeeErr *transactions.MinFeeError
+ if errors.As(err, &minFeeErr) {
+ return TxPoolErrTagFee
+ }
+
+ var deadErr *bookkeeping.TxnDeadError
+ if errors.As(err, &deadErr) {
+ if deadErr.Early {
+ return TxPoolErrTagTxnEarly
+ }
+ return TxPoolErrTagTxnDead
+ }
+
+ var txInLedgerErr *ledgercore.TransactionInLedgerError
+ if errors.As(err, &txInLedgerErr) {
+ if txInLedgerErr.InBlockEvaluator {
+ return TxPoolErrTagTxIDEval
+ }
+ return TxPoolErrTagTxID
+ }
+
+ var leaseErr *ledgercore.LeaseInLedgerError
+ if errors.As(err, &leaseErr) {
+ if leaseErr.InBlockEvaluator {
+ return TxPoolErrTagLeaseEval
+ }
+ return TxPoolErrTagLease
+ }
+
+ var groupErr *ledgercore.TxGroupMalformedError
+ if errors.As(err, &groupErr) {
+ if groupErr.Reason == ledgercore.TxGroupMalformedErrorReasonExceedMaxSize {
+ return TxPoolErrTagTooLarge
+ }
+ return TxPoolErrTagGroupID
+ }
+
+ var notWellErr *ledgercore.TxnNotWellFormedError
+ if errors.As(err, ¬WellErr) {
+ return TxPoolErrTagNotWell
+ }
+
+ var overspendErr *ledgercore.OverspendError
+ if errors.As(err, &overspendErr) {
+ return TxPoolErrTagOverspend
+ }
+
+ var minBalErr *ledgercore.MinBalanceError
+ if errors.As(err, &minBalErr) {
+ return TxPoolErrTagMinBalance
+ }
+
+ var assetBalErr *ledgercore.AssetBalanceError
+ if errors.As(err, &assetBalErr) {
+ return TxPoolErrTagAssetBalance
+ }
+
+ var approvalErr *ledgercore.ApprovalProgramRejectedError
+ if errors.As(err, &approvalErr) {
+ return TxPoolErrTagTealReject
+ }
+
+ var evalErr logic.EvalError
+ if errors.As(err, &evalErr) {
+ return TxPoolErrTagTealErr
+ }
+
+ return TxPoolErrTagEvalGeneric
+}
diff --git a/data/pools/errors_test.go b/data/pools/errors_test.go
new file mode 100644
index 0000000000..a33d2a59df
--- /dev/null
+++ b/data/pools/errors_test.go
@@ -0,0 +1,147 @@
+// Copyright (C) 2019-2026 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 pools
+
+import (
+ "errors"
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ "github.com/algorand/go-algorand/data/basics"
+ "github.com/algorand/go-algorand/data/bookkeeping"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/data/transactions/logic"
+ "github.com/algorand/go-algorand/ledger/ledgercore"
+ "github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/algorand/go-algorand/util/metrics"
+)
+
+func TestClassifyTxPoolErrorGeneralCoverage(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ // Table mirrors the distinct branches inside ClassifyTxPoolError/classifyUnwrappedError.
+ tcases := []struct {
+ name string
+ err error
+ tag string
+ wrap bool
+ }{
+ {name: "cap", err: ErrPendingQueueReachedMaxCap, tag: TxPoolErrTagCap},
+ {name: "cap_wrapped", err: ErrPendingQueueReachedMaxCap, tag: TxPoolErrTagCap, wrap: true},
+ {name: "pending_eval", err: ErrNoPendingBlockEvaluator, tag: TxPoolErrTagPendingEval},
+ {name: "pending_eval_wrapped", err: ErrNoPendingBlockEvaluator, tag: TxPoolErrTagPendingEval, wrap: true},
+ {name: "no_space", err: ledgercore.ErrNoSpace, tag: TxPoolErrTagNoSpace},
+ {name: "no_space_wrapped", err: ledgercore.ErrNoSpace, tag: TxPoolErrTagNoSpace, wrap: true},
+ {name: "fee_escalation", err: &ErrTxPoolFeeError{}, tag: TxPoolErrTagFee},
+ {name: "fee_escalation_wrapped", err: &ErrTxPoolFeeError{}, tag: TxPoolErrTagFee, wrap: true},
+ {name: "fee_min_fee", err: func() error { e := transactions.MinFeeError("min"); return &e }(), tag: TxPoolErrTagFee},
+ {name: "fee_min_fee_wrapped", err: func() error { e := transactions.MinFeeError("min"); return &e }(), tag: TxPoolErrTagFee, wrap: true},
+ {name: "txn_dead", err: &bookkeeping.TxnDeadError{}, tag: TxPoolErrTagTxnDead},
+ {name: "txn_dead_wrapped", err: &bookkeeping.TxnDeadError{}, tag: TxPoolErrTagTxnDead, wrap: true},
+ {name: "txn_early", err: &bookkeeping.TxnDeadError{Early: true}, tag: TxPoolErrTagTxnEarly},
+ {name: "txn_early_wrapped", err: &bookkeeping.TxnDeadError{Early: true}, tag: TxPoolErrTagTxnEarly, wrap: true},
+ {name: "txid_ledger", err: &ledgercore.TransactionInLedgerError{InBlockEvaluator: false}, tag: TxPoolErrTagTxID},
+ {name: "txid_ledger_wrapped", err: &ledgercore.TransactionInLedgerError{InBlockEvaluator: false}, tag: TxPoolErrTagTxID, wrap: true},
+ {name: "txid_eval", err: &ledgercore.TransactionInLedgerError{InBlockEvaluator: true}, tag: TxPoolErrTagTxIDEval},
+ {name: "txid_eval_wrapped", err: &ledgercore.TransactionInLedgerError{InBlockEvaluator: true}, tag: TxPoolErrTagTxIDEval, wrap: true},
+ {name: "lease_ledger", err: ledgercore.MakeLeaseInLedgerError(transactions.Txid{}, ledgercore.Txlease{Lease: [32]byte{1}}, false), tag: TxPoolErrTagLease},
+ {name: "lease_ledger_wrapped", err: ledgercore.MakeLeaseInLedgerError(transactions.Txid{}, ledgercore.Txlease{Lease: [32]byte{1}}, false), tag: TxPoolErrTagLease, wrap: true},
+ {name: "lease_eval", err: ledgercore.MakeLeaseInLedgerError(transactions.Txid{}, ledgercore.Txlease{Lease: [32]byte{2}}, true), tag: TxPoolErrTagLeaseEval},
+ {name: "lease_eval_wrapped", err: ledgercore.MakeLeaseInLedgerError(transactions.Txid{}, ledgercore.Txlease{Lease: [32]byte{2}}, true), tag: TxPoolErrTagLeaseEval, wrap: true},
+ {name: "group_too_large", err: &ledgercore.TxGroupMalformedError{Reason: ledgercore.TxGroupMalformedErrorReasonExceedMaxSize}, tag: TxPoolErrTagTooLarge},
+ {name: "group_too_large_wrapped", err: &ledgercore.TxGroupMalformedError{Reason: ledgercore.TxGroupMalformedErrorReasonExceedMaxSize}, tag: TxPoolErrTagTooLarge, wrap: true},
+ {name: "group_other", err: &ledgercore.TxGroupMalformedError{Reason: ledgercore.TxGroupMalformedErrorReasonGeneric}, tag: TxPoolErrTagGroupID},
+ {name: "group_other_wrapped", err: &ledgercore.TxGroupMalformedError{Reason: ledgercore.TxGroupMalformedErrorReasonGeneric}, tag: TxPoolErrTagGroupID, wrap: true},
+ {name: "not_well", err: func() error { e := ledgercore.TxnNotWellFormedError("bad txn"); return &e }(), tag: TxPoolErrTagNotWell},
+ {name: "not_well_wrapped", err: func() error { e := ledgercore.TxnNotWellFormedError("bad txn"); return &e }(), tag: TxPoolErrTagNotWell, wrap: true},
+ {name: "overspend", err: &ledgercore.OverspendError{Account: basics.Address{}, Data: ledgercore.AccountData{}, Tried: basics.MicroAlgos{Raw: 1}}, tag: TxPoolErrTagOverspend},
+ {name: "overspend_wrapped", err: &ledgercore.OverspendError{Account: basics.Address{}, Data: ledgercore.AccountData{}, Tried: basics.MicroAlgos{Raw: 1}}, tag: TxPoolErrTagOverspend, wrap: true},
+ {name: "min_balance", err: &ledgercore.MinBalanceError{Account: basics.Address{}, Balance: 1, MinBalance: 2, TotalAssets: 3}, tag: TxPoolErrTagMinBalance},
+ {name: "min_balance_wrapped", err: &ledgercore.MinBalanceError{Account: basics.Address{}, Balance: 1, MinBalance: 2, TotalAssets: 3}, tag: TxPoolErrTagMinBalance, wrap: true},
+ {name: "asset_balance", err: &ledgercore.AssetBalanceError{Amount: 10, SenderAmount: 5}, tag: TxPoolErrTagAssetBalance},
+ {name: "asset_balance_wrapped", err: &ledgercore.AssetBalanceError{Amount: 10, SenderAmount: 5}, tag: TxPoolErrTagAssetBalance, wrap: true},
+ {name: "approval_reject", err: &ledgercore.ApprovalProgramRejectedError{}, tag: TxPoolErrTagTealReject},
+ {name: "approval_reject_wrapped", err: &ledgercore.ApprovalProgramRejectedError{}, tag: TxPoolErrTagTealReject, wrap: true},
+ {name: "logic_eval", err: logic.EvalError{Err: errors.New("logic")}, tag: TxPoolErrTagTealErr},
+ {name: "logic_eval_wrapped", err: logic.EvalError{Err: errors.New("logic")}, tag: TxPoolErrTagTealErr, wrap: true},
+ {name: "unknown_error", err: errors.New("unknown"), tag: TxPoolErrTagEvalGeneric},
+ {name: "unknown_error_wrapped", err: errors.New("unknown"), tag: TxPoolErrTagEvalGeneric, wrap: true},
+ }
+
+ for _, tc := range tcases {
+ t.Run(tc.name, func(t *testing.T) {
+ err := tc.err
+ if tc.wrap {
+ err = fmt.Errorf("wrap: %w", err)
+ }
+ require.Equal(t, tc.tag, ClassifyTxPoolError(err))
+ })
+ }
+}
+
+func TestTxPoolReevalCounterCoversAllTags(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ // Re-eval counter uses TxPoolErrTags to ensure all possible classification results are predeclared.
+ reevalCases := []struct {
+ name string
+ err error
+ tag string
+ }{
+ {name: "fee", err: &ErrTxPoolFeeError{}, tag: TxPoolErrTagFee},
+ {name: "txn_dead", err: &bookkeeping.TxnDeadError{}, tag: TxPoolErrTagTxnDead},
+ {name: "txn_early", err: &bookkeeping.TxnDeadError{Early: true}, tag: TxPoolErrTagTxnEarly},
+ {name: "too_large", err: &ledgercore.TxGroupMalformedError{Reason: ledgercore.TxGroupMalformedErrorReasonExceedMaxSize}, tag: TxPoolErrTagTooLarge},
+ {name: "groupid", err: &ledgercore.TxGroupMalformedError{Reason: ledgercore.TxGroupMalformedErrorReasonInconsistentGroupID}, tag: TxPoolErrTagGroupID},
+ {name: "txid", err: &ledgercore.TransactionInLedgerError{Txid: transactions.Txid{}, InBlockEvaluator: false}, tag: TxPoolErrTagTxID},
+ {name: "txid_eval", err: &ledgercore.TransactionInLedgerError{Txid: transactions.Txid{}, InBlockEvaluator: true}, tag: TxPoolErrTagTxIDEval},
+ {name: "lease", err: ledgercore.MakeLeaseInLedgerError(transactions.Txid{}, ledgercore.Txlease{Sender: basics.Address{}, Lease: [32]byte{3}}, false), tag: TxPoolErrTagLease},
+ {name: "lease_eval", err: ledgercore.MakeLeaseInLedgerError(transactions.Txid{}, ledgercore.Txlease{Sender: basics.Address{}, Lease: [32]byte{4}}, true), tag: TxPoolErrTagLeaseEval},
+ {name: "no_space", err: ledgercore.ErrNoSpace, tag: TxPoolErrTagNoSpace},
+ {name: "not_well", err: func() error { e := ledgercore.TxnNotWellFormedError("bad"); return &e }(), tag: TxPoolErrTagNotWell},
+ {name: "teal_err", err: logic.EvalError{Err: errors.New("logic")}, tag: TxPoolErrTagTealErr},
+ {name: "teal_reject", err: &ledgercore.ApprovalProgramRejectedError{}, tag: TxPoolErrTagTealReject},
+ {name: "min_balance", err: &ledgercore.MinBalanceError{Account: basics.Address{}, Balance: 1, MinBalance: 2, TotalAssets: 3}, tag: TxPoolErrTagMinBalance},
+ {name: "overspend", err: &ledgercore.OverspendError{Account: basics.Address{}, Data: ledgercore.AccountData{}, Tried: basics.MicroAlgos{Raw: 1}}, tag: TxPoolErrTagOverspend},
+ {name: "asset_balance", err: &ledgercore.AssetBalanceError{Amount: 10, SenderAmount: 5}, tag: TxPoolErrTagAssetBalance},
+ }
+
+ orig := txPoolReevalCounter
+ txPoolReevalCounter = metrics.NewTagCounter(
+ "algod_tx_pool_reeval_{TAG}",
+ "Number of transaction groups removed from pool during re-evaluation due to {TAG}",
+ TxPoolErrTags...,
+ )
+ t.Cleanup(func() { txPoolReevalCounter = orig })
+
+ for _, tc := range reevalCases {
+ t.Run(tc.name, func(t *testing.T) {
+ tag := ClassifyTxPoolError(tc.err)
+ require.Equal(t, tc.tag, tag)
+ require.Contains(t, TxPoolErrTags, tag)
+ txPoolReevalCounter.Add(tag, 1)
+ })
+ }
+
+ metricsMap := map[string]float64{}
+ txPoolReevalCounter.AddMetric(metricsMap)
+ for _, tc := range reevalCases {
+ require.Equal(t, float64(1), metricsMap["algod_tx_pool_reeval_"+tc.tag])
+ }
+}
diff --git a/data/pools/statusCache.go b/data/pools/statusCache.go
index 2c00e185e5..fcdad50774 100644
--- a/data/pools/statusCache.go
+++ b/data/pools/statusCache.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/pools/transactionPool.go b/data/pools/transactionPool.go
index 98e8e69c54..316ea34525 100644
--- a/data/pools/transactionPool.go
+++ b/data/pools/transactionPool.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -61,7 +61,6 @@ type TransactionPool struct {
mu deadlock.Mutex
cond sync.Cond
- expiredTxCount map[basics.Round]int
pendingBlockEvaluator BlockEvaluator
evalTracer logic.EvalTracer
numPendingWholeBlocks basics.Round
@@ -110,8 +109,7 @@ type BlockEvaluator interface {
TestTransactionGroup(txgroup []transactions.SignedTxn) error
Round() basics.Round
PaySetSize() int
- TransactionGroup(txads []transactions.SignedTxnWithAD) error
- Transaction(txn transactions.SignedTxn, ad transactions.ApplyData) error
+ TransactionGroup(txads ...transactions.SignedTxnWithAD) error
GenerateBlock(addrs []basics.Address) (*ledgercore.UnfinishedBlock, error)
ResetTxnBytes()
}
@@ -131,7 +129,6 @@ func MakeTransactionPool(ledger *ledger.Ledger, cfg config.Local, log logging.Lo
pool := TransactionPool{
pendingTxids: make(map[transactions.Txid]transactions.SignedTxn),
rememberedTxids: make(map[transactions.Txid]transactions.SignedTxn),
- expiredTxCount: make(map[basics.Round]int),
ledger: ledger,
statusCache: makeStatusCache(cfg.TxPoolSize),
logProcessBlockStats: cfg.EnableProcessBlockStats,
@@ -195,7 +192,6 @@ func (pool *TransactionPool) Reset() {
pool.pendingTxGroups = nil
pool.rememberedTxids = make(map[transactions.Txid]transactions.SignedTxn)
pool.rememberedTxGroups = nil
- pool.expiredTxCount = make(map[basics.Round]int)
pool.numPendingWholeBlocks = 0
pool.pendingBlockEvaluator = nil
pool.statusCache.reset()
@@ -209,15 +205,6 @@ func (pool *TransactionPool) getVotingAccountsForRound(rnd basics.Round) []basic
return pool.vac.VotingAccountsForRound(rnd)
}
-// NumExpired returns the number of transactions that expired at the
-// end of a round (only meaningful if cleanup has been called for that
-// round).
-func (pool *TransactionPool) NumExpired(round basics.Round) int {
- pool.mu.Lock()
- defer pool.mu.Unlock()
- return pool.expiredTxCount[round]
-}
-
// PendingTxIDs return the IDs of all pending transactions.
func (pool *TransactionPool) PendingTxIDs() []transactions.Txid {
pool.pendingMu.RLock()
@@ -586,10 +573,6 @@ func (pool *TransactionPool) OnNewBlock(block bookkeeping.Block, delta ledgercor
stats.KnownCommittedCount = knownCommitted
stats.UnknownCommittedCount = unknownCommitted
- proto := config.Consensus[block.CurrentProtocol]
- pool.expiredTxCount[block.Round()] = int(stats.ExpiredCount)
- delete(pool.expiredTxCount, block.Round()-expiredHistory*basics.Round(proto.MaxTxnLife))
-
if pool.logProcessBlockStats {
var details struct {
Round uint64
@@ -632,7 +615,7 @@ func (pool *TransactionPool) addToPendingBlockEvaluatorOnce(txgroup []transactio
transactionGroupStartsTime = time.Now()
}
- err := pool.pendingBlockEvaluator.TransactionGroup(txgroupad)
+ err := pool.pendingBlockEvaluator.TransactionGroup(txgroupad...)
if recomputing {
if !pool.assemblyResults.assemblyCompletedOrAbandoned {
@@ -766,6 +749,7 @@ func (pool *TransactionPool) recomputeBlockEvaluator(committedTxIDs map[transact
}
if _, alreadyCommitted := committedTxIDs[txgroup[0].ID()]; alreadyCommitted {
asmStats.EarlyCommittedCount++
+ txPoolReevalCommitted.Inc(nil)
continue
}
err := pool.add(txgroup, &asmStats)
@@ -773,6 +757,9 @@ func (pool *TransactionPool) recomputeBlockEvaluator(committedTxIDs map[transact
for _, tx := range txgroup {
pool.statusCache.put(tx, err.Error())
}
+
+ txPoolReevalCounter.Add(ClassifyTxPoolError(err), 1)
+
// metrics here are duplicated for historic reasons. stats is hardly used and should be removed in favor of asmstats
switch terr := err.(type) {
case *ledgercore.TransactionInLedgerError:
@@ -802,6 +789,8 @@ func (pool *TransactionPool) recomputeBlockEvaluator(committedTxIDs map[transact
stats.RemovedInvalidCount++
pool.log.Infof("Pending transaction in pool no longer valid: %v", err)
}
+ } else {
+ txPoolReevalSuccess.Inc(nil)
}
}
diff --git a/data/pools/transactionPool_test.go b/data/pools/transactionPool_test.go
index 73a06892d1..3946f7d2df 100644
--- a/data/pools/transactionPool_test.go
+++ b/data/pools/transactionPool_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -20,6 +20,7 @@ import (
"bufio"
"bytes"
"context"
+ "errors"
"fmt"
"math/rand"
"os"
@@ -49,6 +50,7 @@ import (
"github.com/algorand/go-algorand/stateproof"
"github.com/algorand/go-algorand/stateproof/verify"
"github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/algorand/go-algorand/util/metrics"
)
var proto = config.Consensus[protocol.ConsensusCurrentVersion]
@@ -231,7 +233,9 @@ func TestSenderGoesBelowMinBalance(t *testing.T) {
},
}
signedTx := tx.Sign(secrets[0])
- require.Error(t, transactionPool.RememberOne(signedTx))
+ err := transactionPool.RememberOne(signedTx)
+ require.Error(t, err)
+ require.Equal(t, TxPoolErrTagMinBalance, ClassifyTxPoolError(err))
}
func TestSenderGoesBelowMinBalanceDueToAssets(t *testing.T) {
@@ -565,7 +569,7 @@ func TestRememberForget(t *testing.T) {
tx.Note[1] = byte(j)
signedTx := tx.Sign(secrets[i])
transactionPool.RememberOne(signedTx)
- err := eval.Transaction(signedTx, transactions.ApplyData{})
+ err := eval.TransactionGroup(signedTx.WithAD())
require.NoError(t, err)
}
}
@@ -637,6 +641,8 @@ func TestCleanUp(t *testing.T) {
}
}
+ require.Len(t, transactionPool.PendingTxGroups(), issuedTransactions)
+
for mockLedger.Latest() < 6 {
eval := newBlockEvaluator(t, mockLedger)
ufblk, err := eval.GenerateBlock(nil)
@@ -649,24 +655,7 @@ func TestCleanUp(t *testing.T) {
transactionPool.OnNewBlock(blk.Block(), ledgercore.StateDelta{})
}
- pending := transactionPool.PendingTxGroups()
- require.Zero(t, len(pending))
- require.Zero(t, transactionPool.NumExpired(4))
- require.Equal(t, issuedTransactions, transactionPool.NumExpired(5))
-
- for mockLedger.Latest() < 6+basics.Round(expiredHistory*proto.MaxTxnLife) {
- eval := newBlockEvaluator(t, mockLedger)
- ufblk, err := eval.GenerateBlock(nil)
- require.NoError(t, err)
-
- blk := ledgercore.MakeValidatedBlock(ufblk.UnfinishedBlock(), ufblk.UnfinishedDeltas())
- err = mockLedger.AddValidatedBlock(blk, agreement.Certificate{})
- require.NoError(t, err)
-
- transactionPool.OnNewBlock(blk.Block(), ledgercore.StateDelta{})
- require.Zero(t, transactionPool.NumExpired(blk.Block().Round()))
- }
- require.Len(t, transactionPool.expiredTxCount, int(expiredHistory*proto.MaxTxnLife))
+ require.Empty(t, transactionPool.PendingTxGroups())
}
func TestFixOverflowOnNewBlock(t *testing.T) {
@@ -748,7 +737,7 @@ func TestFixOverflowOnNewBlock(t *testing.T) {
signedTx := tx.Sign(secrets[0])
blockEval := newBlockEvaluator(t, mockLedger)
- err := blockEval.Transaction(signedTx, transactions.ApplyData{})
+ err := blockEval.TransactionGroup(signedTx.WithAD())
require.NoError(t, err)
// simulate this transaction was applied
@@ -766,6 +755,84 @@ func TestFixOverflowOnNewBlock(t *testing.T) {
require.Len(t, pending, savedTransactions-1)
}
+func TestTxPoolReevalMetricsRecordLedgerDuplicate(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ // Sanity: ensure tags cover the scenarios we expect to record.
+ require.Contains(t, TxPoolErrTags, TxPoolErrTagTxID)
+ require.Contains(t, TxPoolErrTags, TxPoolErrTagLease)
+ require.Contains(t, TxPoolErrTags, TxPoolErrTagNoSpace)
+
+ // Isolate the counter for this test.
+ origCounter := txPoolReevalCounter
+ txPoolReevalCounter = metrics.NewTagCounter(
+ "algod_tx_pool_reeval_{TAG}",
+ "Number of transaction groups removed from pool during re-evaluation due to {TAG}",
+ TxPoolErrTags...,
+ )
+ t.Cleanup(func() { txPoolReevalCounter = origCounter })
+
+ secrets := make([]*crypto.SignatureSecrets, 2)
+ addresses := make([]basics.Address, 2)
+ for i := 0; i < len(secrets); i++ {
+ secret := keypair()
+ secrets[i] = secret
+ addresses[i] = basics.Address(secret.SignatureVerifier)
+ }
+
+ mockLedger := makeMockLedger(t, initAccFixed(addresses, 1<<32))
+ cfg := config.GetDefaultLocal()
+ cfg.TxPoolSize = testPoolSize
+ cfg.EnableProcessBlockStats = false
+ transactionPool := MakeTransactionPool(mockLedger, cfg, logging.Base(), nil)
+
+ base := transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: addresses[0],
+ Fee: basics.MicroAlgos{Raw: proto.MinTxnFee},
+ FirstValid: 1,
+ LastValid: 20,
+ GenesisHash: mockLedger.GenesisHash(),
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: addresses[1],
+ Amount: basics.MicroAlgos{Raw: 1},
+ },
+ }
+ txA := base
+ txA.Note = []byte{0xAA}
+ txB := base
+ txB.Note = []byte{0xBB}
+
+ signedA := txA.Sign(secrets[0])
+ signedB := txB.Sign(secrets[0])
+
+ require.NoError(t, transactionPool.RememberOne(signedA))
+ require.NoError(t, transactionPool.RememberOne(signedB))
+
+ eval := newBlockEvaluator(t, mockLedger)
+ require.NoError(t, eval.TransactionGroup(signedB.WithAD()))
+ ufblk, err := eval.GenerateBlock(nil)
+ require.NoError(t, err)
+ vb := ledgercore.MakeValidatedBlock(ufblk.UnfinishedBlock(), ufblk.UnfinishedDeltas())
+ require.NoError(t, mockLedger.AddValidatedBlock(vb, agreement.Certificate{}))
+
+ // Intentionally provide a delta without Txids so the recompute path hits the ledger duplicate
+ // detection instead of skipping via committedTxIDs filtering.
+ delta := vb.Delta()
+ delta.Txids = nil
+ transactionPool.OnNewBlock(vb.Block(), delta)
+
+ // Expect a re-eval tag for txid duplicate and that only the uncommitted txn remains pending.
+ metricsMap := map[string]float64{}
+ txPoolReevalCounter.AddMetric(metricsMap)
+ require.Equal(t, float64(1), metricsMap["algod_tx_pool_reeval_"+TxPoolErrTagTxID])
+ pending := transactionPool.PendingTxGroups()
+ require.Len(t, pending, 1)
+ require.Equal(t, signedA.ID(), pending[0][0].ID())
+}
+
func TestOverspender(t *testing.T) {
partitiontest.PartitionTest(t)
@@ -1287,7 +1354,7 @@ func BenchmarkTransactionPoolSteadyState(b *testing.B) {
eval := newBlockEvaluator(b, l)
for len(ledgerTxnQueue) > 0 {
stx := ledgerTxnQueue[0]
- err := eval.Transaction(stx, transactions.ApplyData{})
+ err := eval.TransactionGroup(stx.WithAD())
if err == ledgercore.ErrNoSpace {
break
}
@@ -1537,7 +1604,7 @@ func TestStateProofLogging(t *testing.T) {
eval, err := mockLedger.StartEvaluator(b.BlockHeader, 0, 1000000, nil)
require.NoError(t, err)
- err = eval.Transaction(stxn, transactions.ApplyData{})
+ err = eval.TransactionGroup(stxn.WithAD())
require.NoError(t, err)
err = transactionPool.RememberOne(stxn)
@@ -1626,3 +1693,442 @@ func generateProofForTesting(
return proof
}
+
+// commitTxns evaluates transactions into a new block, commits it to the ledger,
+// and notifies the pool. This is used by classification integration tests that
+// need block progression.
+func commitTxns(t TestingT, l *ledger.Ledger, pool *TransactionPool, txns ...transactions.SignedTxn) {
+ eval := newBlockEvaluator(t, l)
+ for _, txn := range txns {
+ require.NoError(t, eval.TransactionGroup(transactions.WrapSignedTxnsWithAD([]transactions.SignedTxn{txn})...))
+ }
+ ufblk, err := eval.GenerateBlock(nil)
+ require.NoError(t, err)
+ vb := ledgercore.MakeValidatedBlock(ufblk.UnfinishedBlock(), ufblk.UnfinishedDeltas())
+ require.NoError(t, l.AddValidatedBlock(vb, agreement.Certificate{}))
+ pool.OnNewBlock(vb.Block(), vb.Delta())
+}
+
+func TestPoolFeeClassification(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ // Fill pool past one block to trigger fee escalation, then submit a txn
+ // with MinTxnFee which will be below the escalated threshold.
+ numOfAccounts := 5
+ secrets := make([]*crypto.SignatureSecrets, numOfAccounts)
+ addresses := make([]basics.Address, numOfAccounts)
+ for i := 0; i < numOfAccounts; i++ {
+ secret := keypair()
+ secrets[i] = secret
+ addresses[i] = basics.Address(secret.SignatureVerifier)
+ }
+
+ l := makeMockLedger(t, initAccFixed(addresses, 1<<32))
+ cfg := config.GetDefaultLocal()
+ cfg.TxPoolSize = testPoolSize * 30
+ cfg.EnableProcessBlockStats = false
+ transactionPool := MakeTransactionPool(l, cfg, logging.Base(), nil)
+
+ // Fill pool with enough large txns to fill multiple blocks (triggering fee escalation)
+ // but stay under the pool's capacity limit.
+ for i, sender := range addresses {
+ for j := 0; j < testPoolSize*15/len(addresses); j++ {
+ var receiver basics.Address
+ crypto.RandBytes(receiver[:])
+ tx := transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: sender,
+ Fee: basics.MicroAlgos{Raw: proto.MinTxnFee * 100},
+ FirstValid: 0,
+ LastValid: basics.Round(proto.MaxTxnLife),
+ GenesisHash: l.GenesisHash(),
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: receiver,
+ Amount: basics.MicroAlgos{Raw: proto.MinBalance},
+ },
+ }
+ tx.Note = make([]byte, 1024)
+ crypto.RandBytes(tx.Note)
+ signedTx := tx.Sign(secrets[i])
+ require.NoError(t, transactionPool.RememberOne(signedTx))
+ }
+ }
+
+ require.True(t, transactionPool.numPendingWholeBlocks > 0, "pool should have >0 whole blocks pending")
+
+ // Submit a txn with MinTxnFee but a large note so the fee-per-byte
+ // threshold exceeds MinTxnFee under fee escalation.
+ var receiver basics.Address
+ crypto.RandBytes(receiver[:])
+ tx := transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: addresses[0],
+ Fee: basics.MicroAlgos{Raw: proto.MinTxnFee},
+ FirstValid: 0,
+ LastValid: basics.Round(proto.MaxTxnLife),
+ GenesisHash: l.GenesisHash(),
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: receiver,
+ Amount: basics.MicroAlgos{Raw: 0},
+ },
+ }
+ tx.Note = make([]byte, 1024)
+ err := transactionPool.RememberOne(tx.Sign(secrets[0]))
+ require.Error(t, err)
+ require.Equal(t, TxPoolErrTagFee, ClassifyTxPoolError(err))
+}
+
+func TestPoolLeaseReevalClassification(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ origCounter := txPoolReevalCounter
+ txPoolReevalCounter = metrics.NewTagCounter(
+ "algod_tx_pool_reeval_{TAG}",
+ "Number of transaction groups removed from pool during re-evaluation due to {TAG}",
+ TxPoolErrTags...,
+ )
+ t.Cleanup(func() { txPoolReevalCounter = origCounter })
+
+ secrets := make([]*crypto.SignatureSecrets, 2)
+ addresses := make([]basics.Address, 2)
+ for i := range secrets {
+ secret := keypair()
+ secrets[i] = secret
+ addresses[i] = basics.Address(secret.SignatureVerifier)
+ }
+
+ mockLedger := makeMockLedger(t, initAccFixed(addresses, 1<<32))
+ cfg := config.GetDefaultLocal()
+ cfg.TxPoolSize = testPoolSize
+ cfg.EnableProcessBlockStats = false
+ transactionPool := MakeTransactionPool(mockLedger, cfg, logging.Base(), nil)
+
+ var lease [32]byte
+ lease[0] = 0x01
+
+ // Remember a txn with a lease
+ txA := transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: addresses[0],
+ Fee: basics.MicroAlgos{Raw: proto.MinTxnFee},
+ FirstValid: 1,
+ LastValid: 20,
+ Lease: lease,
+ GenesisHash: mockLedger.GenesisHash(),
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: addresses[1],
+ Amount: basics.MicroAlgos{Raw: 1},
+ },
+ }
+ signedA := txA.Sign(secrets[0])
+ require.NoError(t, transactionPool.RememberOne(signedA))
+
+ // Commit the txn in a block
+ eval := newBlockEvaluator(t, mockLedger)
+ require.NoError(t, eval.TransactionGroup(signedA.WithAD()))
+ ufblk, err := eval.GenerateBlock(nil)
+ require.NoError(t, err)
+ vb := ledgercore.MakeValidatedBlock(ufblk.UnfinishedBlock(), ufblk.UnfinishedDeltas())
+ require.NoError(t, mockLedger.AddValidatedBlock(vb, agreement.Certificate{}))
+
+ // Nil out Txids so the pool re-evaluates instead of filtering by committed txids
+ delta := vb.Delta()
+ delta.Txids = nil
+ transactionPool.OnNewBlock(vb.Block(), delta)
+
+ metricsMap := map[string]float64{}
+ txPoolReevalCounter.AddMetric(metricsMap)
+ require.Equal(t, float64(1), metricsMap["algod_tx_pool_reeval_"+TxPoolErrTagLease])
+}
+
+func TestPoolAssetBalanceClassification(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ creatorSecret := keypair()
+ creatorAddr := basics.Address(creatorSecret.SignatureVerifier)
+ senderSecret := keypair()
+ senderAddr := basics.Address(senderSecret.SignatureVerifier)
+
+ l := makeMockLedgerFuture(t, initAcc(map[basics.Address]uint64{
+ creatorAddr: 1 << 32,
+ senderAddr: 1 << 32,
+ }))
+ futureProto := config.Consensus[protocol.ConsensusFuture]
+ cfg := config.GetDefaultLocal()
+ cfg.TxPoolSize = testPoolSize
+ cfg.EnableProcessBlockStats = false
+ transactionPool := MakeTransactionPool(l, cfg, logging.Base(), nil)
+
+ // Block 1: creator creates asset, sender opts in
+ createTx := transactions.Transaction{
+ Type: protocol.AssetConfigTx,
+ Header: transactions.Header{
+ Sender: creatorAddr,
+ Fee: basics.MicroAlgos{Raw: futureProto.MinTxnFee},
+ FirstValid: 0,
+ LastValid: basics.Round(futureProto.MaxTxnLife),
+ GenesisHash: l.GenesisHash(),
+ },
+ AssetConfigTxnFields: transactions.AssetConfigTxnFields{
+ AssetParams: basics.AssetParams{
+ Total: 100,
+ Manager: creatorAddr,
+ Clawback: creatorAddr,
+ },
+ },
+ }
+
+ optInTx := transactions.Transaction{
+ Type: protocol.AssetTransferTx,
+ Header: transactions.Header{
+ Sender: senderAddr,
+ Fee: basics.MicroAlgos{Raw: futureProto.MinTxnFee},
+ FirstValid: 0,
+ LastValid: basics.Round(futureProto.MaxTxnLife),
+ GenesisHash: l.GenesisHash(),
+ },
+ AssetTransferTxnFields: transactions.AssetTransferTxnFields{
+ XferAsset: 1, // first asset created gets index 1
+ AssetAmount: 0,
+ AssetReceiver: senderAddr,
+ },
+ }
+
+ commitTxns(t, l, transactionPool, createTx.Sign(creatorSecret), optInTx.Sign(senderSecret))
+
+ // Sender transfers more than they hold (0)
+ xferTx := transactions.Transaction{
+ Type: protocol.AssetTransferTx,
+ Header: transactions.Header{
+ Sender: senderAddr,
+ Fee: basics.MicroAlgos{Raw: futureProto.MinTxnFee},
+ FirstValid: 1,
+ LastValid: basics.Round(futureProto.MaxTxnLife),
+ GenesisHash: l.GenesisHash(),
+ },
+ AssetTransferTxnFields: transactions.AssetTransferTxnFields{
+ XferAsset: 1,
+ AssetAmount: 10,
+ AssetReceiver: creatorAddr,
+ },
+ }
+ err := transactionPool.RememberOne(xferTx.Sign(senderSecret))
+ require.Error(t, err)
+ require.Equal(t, TxPoolErrTagAssetBalance, ClassifyTxPoolError(err))
+}
+
+func TestPoolTealRejectClassification(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ creatorSecret := keypair()
+ creatorAddr := basics.Address(creatorSecret.SignatureVerifier)
+ callerSecret := keypair()
+ callerAddr := basics.Address(callerSecret.SignatureVerifier)
+
+ l := makeMockLedgerFuture(t, initAcc(map[basics.Address]uint64{
+ creatorAddr: 1 << 32,
+ callerAddr: 1 << 32,
+ }))
+ futureProto := config.Consensus[protocol.ConsensusFuture]
+ cfg := config.GetDefaultLocal()
+ cfg.TxPoolSize = testPoolSize
+ cfg.EnableProcessBlockStats = false
+ transactionPool := MakeTransactionPool(l, cfg, logging.Base(), nil)
+
+ // Block 1: create app whose approval accepts creation but rejects calls
+ approvalSrc := `#pragma version 2
+txn ApplicationID
+bz accept
+int 0
+return
+accept:
+int 1`
+ clearSrc := `#pragma version 2
+int 1`
+ approvalOps, err := logic.AssembleString(approvalSrc)
+ require.NoError(t, err)
+ clearOps, err := logic.AssembleString(clearSrc)
+ require.NoError(t, err)
+
+ createAppTx := transactions.Transaction{
+ Type: protocol.ApplicationCallTx,
+ Header: transactions.Header{
+ Sender: creatorAddr,
+ Fee: basics.MicroAlgos{Raw: futureProto.MinTxnFee},
+ FirstValid: 0,
+ LastValid: basics.Round(futureProto.MaxTxnLife),
+ GenesisHash: l.GenesisHash(),
+ },
+ ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
+ ApprovalProgram: approvalOps.Program,
+ ClearStateProgram: clearOps.Program,
+ },
+ }
+ commitTxns(t, l, transactionPool, createAppTx.Sign(creatorSecret))
+
+ // Call the app -- approval returns 0 => rejected
+ callTx := transactions.Transaction{
+ Type: protocol.ApplicationCallTx,
+ Header: transactions.Header{
+ Sender: callerAddr,
+ Fee: basics.MicroAlgos{Raw: futureProto.MinTxnFee},
+ FirstValid: 1,
+ LastValid: basics.Round(futureProto.MaxTxnLife),
+ GenesisHash: l.GenesisHash(),
+ },
+ ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
+ ApplicationID: 1,
+ },
+ }
+ err = transactionPool.RememberOne(callTx.Sign(callerSecret))
+ require.Error(t, err)
+ require.Equal(t, TxPoolErrTagTealReject, ClassifyTxPoolError(err))
+}
+
+func TestPoolTealErrClassification(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ creatorSecret := keypair()
+ creatorAddr := basics.Address(creatorSecret.SignatureVerifier)
+ callerSecret := keypair()
+ callerAddr := basics.Address(callerSecret.SignatureVerifier)
+
+ l := makeMockLedgerFuture(t, initAcc(map[basics.Address]uint64{
+ creatorAddr: 1 << 32,
+ callerAddr: 1 << 32,
+ }))
+ futureProto := config.Consensus[protocol.ConsensusFuture]
+ cfg := config.GetDefaultLocal()
+ cfg.TxPoolSize = testPoolSize
+ cfg.EnableProcessBlockStats = false
+ transactionPool := MakeTransactionPool(l, cfg, logging.Base(), nil)
+
+ // Block 1: create app whose approval accepts creation but errs on calls
+ approvalSrc := `#pragma version 2
+txn ApplicationID
+bz accept
+err
+accept:
+int 1`
+ clearSrc := `#pragma version 2
+int 1`
+ approvalOps, err := logic.AssembleString(approvalSrc)
+ require.NoError(t, err)
+ clearOps, err := logic.AssembleString(clearSrc)
+ require.NoError(t, err)
+
+ createAppTx := transactions.Transaction{
+ Type: protocol.ApplicationCallTx,
+ Header: transactions.Header{
+ Sender: creatorAddr,
+ Fee: basics.MicroAlgos{Raw: futureProto.MinTxnFee},
+ FirstValid: 0,
+ LastValid: basics.Round(futureProto.MaxTxnLife),
+ GenesisHash: l.GenesisHash(),
+ },
+ ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
+ ApprovalProgram: approvalOps.Program,
+ ClearStateProgram: clearOps.Program,
+ },
+ }
+ commitTxns(t, l, transactionPool, createAppTx.Sign(creatorSecret))
+
+ // Call the app -- approval hits `err` opcode
+ callTx := transactions.Transaction{
+ Type: protocol.ApplicationCallTx,
+ Header: transactions.Header{
+ Sender: callerAddr,
+ Fee: basics.MicroAlgos{Raw: futureProto.MinTxnFee},
+ FirstValid: 1,
+ LastValid: basics.Round(futureProto.MaxTxnLife),
+ GenesisHash: l.GenesisHash(),
+ },
+ ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
+ ApplicationID: 1,
+ },
+ }
+ err = transactionPool.RememberOne(callTx.Sign(callerSecret))
+ require.Error(t, err)
+ require.Equal(t, TxPoolErrTagTealErr, ClassifyTxPoolError(err))
+}
+
+// TestRememberTxnDeadError tests that when a transaction has invalid FirstValid/LastValid
+// the Remember call returns a TxnDeadError that can be detected
+// using errors.As. This is used in txHandler to avoid penalizing nodes
+// that might be out of sync.
+func TestRememberTxnDeadError(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ numOfAccounts := 2
+ secrets := make([]*crypto.SignatureSecrets, numOfAccounts)
+ addresses := make([]basics.Address, numOfAccounts)
+
+ for i := 0; i < numOfAccounts; i++ {
+ secret := keypair()
+ addr := basics.Address(secret.SignatureVerifier)
+ secrets[i] = secret
+ addresses[i] = addr
+ }
+
+ mockLedger := makeMockLedger(t, initAccFixed(addresses, 1<<32))
+ cfg := config.GetDefaultLocal()
+ cfg.TxPoolSize = testPoolSize
+ cfg.EnableProcessBlockStats = false
+ transactionPool := MakeTransactionPool(mockLedger, cfg, logging.Base(), nil)
+
+ // Advance the ledger by a few blocks so we can create an expired transaction
+ for i := 0; i < 10; i++ {
+ eval := newBlockEvaluator(t, mockLedger)
+ ufblk, err := eval.GenerateBlock(nil)
+ require.NoError(t, err)
+
+ blk := ledgercore.MakeValidatedBlock(ufblk.UnfinishedBlock(), ufblk.UnfinishedDeltas())
+ err = mockLedger.AddValidatedBlock(blk, agreement.Certificate{})
+ require.NoError(t, err)
+
+ transactionPool.OnNewBlock(blk.Block(), ledgercore.StateDelta{})
+ }
+
+ currentRound := mockLedger.Latest()
+ require.Equal(t, basics.Round(10), currentRound)
+
+ sender := addresses[0]
+ receiver := addresses[1]
+
+ // Create a transaction with LastValid in the past (expired)
+ tx := transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: sender,
+ Fee: basics.MicroAlgos{Raw: proto.MinTxnFee},
+ FirstValid: 0,
+ LastValid: 5,
+ Note: []byte{1},
+ GenesisHash: mockLedger.GenesisHash(),
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: receiver,
+ Amount: basics.MicroAlgos{Raw: 1},
+ },
+ }
+ signedTx := tx.Sign(secrets[0])
+
+ err := transactionPool.Remember([]transactions.SignedTxn{signedTx})
+ require.Error(t, err)
+
+ //nolint:testifylint
+ {
+ // The error should be detectable as TxnDeadError using errors.As
+ // in a way transaction pool clients use it.
+ var tde *bookkeeping.TxnDeadError
+ require.True(t, errors.As(err, &tde), "error should be TxnDeadError, got: %v", err)
+ require.False(t, tde.Early)
+ require.Equal(t, basics.Round(5), tde.LastValid)
+ }
+}
diff --git a/data/stateproofmsg/message.go b/data/stateproofmsg/message.go
index 765786423e..e8e144d4d1 100644
--- a/data/stateproofmsg/message.go
+++ b/data/stateproofmsg/message.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/stateproofmsg/msgp_gen.go b/data/stateproofmsg/msgp_gen.go
index ed245dad0d..9f68ebaba9 100644
--- a/data/stateproofmsg/msgp_gen.go
+++ b/data/stateproofmsg/msgp_gen.go
@@ -1,7 +1,7 @@
-package stateproofmsg
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package stateproofmsg
+
import (
"github.com/algorand/msgp/msgp"
@@ -267,7 +267,7 @@ func (z *Message) MsgIsZero() bool {
return (len((*z).BlockHeadersCommitment) == 0) && (len((*z).VotersCommitment) == 0) && ((*z).LnProvenWeight == 0) && ((*z).FirstAttestedRound.MsgIsZero()) && ((*z).LastAttestedRound.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// MessageMaxSize returns a maximum valid message size for this message type
func MessageMaxSize() (s int) {
s = 1 + 2 + msgp.BytesPrefixSize + crypto.Sha256Size + 2 + msgp.BytesPrefixSize + crypto.SumhashDigestSize + 2 + msgp.Uint64Size + 2 + basics.RoundMaxSize() + 2 + basics.RoundMaxSize()
return
diff --git a/data/stateproofmsg/msgp_gen_test.go b/data/stateproofmsg/msgp_gen_test.go
index c8ce88e556..4d411fa7a3 100644
--- a/data/stateproofmsg/msgp_gen_test.go
+++ b/data/stateproofmsg/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package stateproofmsg
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package stateproofmsg
+
import (
"testing"
diff --git a/data/transactions/application.go b/data/transactions/application.go
index 56069bf6be..8f6be79dc1 100644
--- a/data/transactions/application.go
+++ b/data/transactions/application.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -66,7 +66,7 @@ const (
// OnCompletion is an enum representing some layer 1 side effect that an
// ApplicationCall transaction will have if it is included in a block.
//
-//go:generate stringer -type=OnCompletion -output=application_string.go
+//go:generate go tool -modfile=../../tool.mod stringer -type=OnCompletion -output=application_string.go
type OnCompletion uint64
const (
@@ -210,7 +210,7 @@ func (rr ResourceRef) Empty() bool {
// wellFormed checks that a ResourceRef is a proper member of `access. `rr` is
// either empty a single kind of resource. Any internal indices point to proper
// locations inside `access`.
-func (rr ResourceRef) wellFormed(access []ResourceRef, proto config.ConsensusParams) error {
+func (rr ResourceRef) wellFormed(access []ResourceRef, inCreate bool, proto config.ConsensusParams) error {
// Count the number of non-empty fields
count := 0
// The "basic" resources are inherently wellFormed
@@ -231,7 +231,13 @@ func (rr ResourceRef) wellFormed(access []ResourceRef, proto config.ConsensusPar
count++
}
if !rr.Locals.Empty() {
- if _, _, err := rr.Locals.Resolve(access, basics.Address{}); err != nil {
+ if !proto.AllowZeroLocalAppRef && rr.Locals.App == 0 {
+ return errors.New("0 App in LocalsRef is not supported")
+ }
+ if inCreate && rr.Locals.App == 0 {
+ return errors.New("0 App in LocalsRef during app create is not allowed or necessary")
+ }
+ if _, _, err := rr.Locals.Resolve(access, basics.Address{}, 0); err != nil {
return err
}
count++
@@ -309,9 +315,9 @@ func (lr LocalsRef) Empty() bool {
return lr == LocalsRef{}
}
-// Resolve looks up the referenced address and app in the access list. 0 is
-// returned if the App index is 0, meaning "current app".
-func (lr LocalsRef) Resolve(access []ResourceRef, sender basics.Address) (basics.Address, basics.AppIndex, error) {
+// Resolve looks up the referenced address and app in the access list. Zero
+// values are translated to the supplied sender or current app.
+func (lr LocalsRef) Resolve(access []ResourceRef, sender basics.Address, current basics.AppIndex) (basics.Address, basics.AppIndex, error) {
address := sender // Returned when lr.Address == 0
if lr.Address != 0 {
if lr.Address > uint64(len(access)) { // recall that Access is 1-based
@@ -322,12 +328,15 @@ func (lr LocalsRef) Resolve(access []ResourceRef, sender basics.Address) (basics
return basics.Address{}, 0, fmt.Errorf("locals Address reference %d is not an Address", lr.Address)
}
}
- if lr.App == 0 || lr.App > uint64(len(access)) { // 1-based
- return basics.Address{}, 0, fmt.Errorf("locals App reference %d outside tx.Access", lr.App)
- }
- app := access[lr.App-1].App
- if app == 0 {
- return basics.Address{}, 0, fmt.Errorf("locals App reference %d is not an App", lr.App)
+ app := current // Returned when lr.App == 0
+ if lr.App != 0 {
+ if lr.App > uint64(len(access)) { // 1-based
+ return basics.Address{}, 0, fmt.Errorf("locals App reference %d outside tx.Access", lr.App)
+ }
+ app = access[lr.App-1].App
+ if app == 0 {
+ return basics.Address{}, 0, fmt.Errorf("locals App reference %d is not an App", lr.App)
+ }
}
return address, app, nil
}
@@ -392,10 +401,10 @@ func (ac *ApplicationCallTxnFields) Empty() bool {
if ac.Access != nil {
return false
}
- if ac.LocalStateSchema != (basics.StateSchema{}) {
+ if !ac.LocalStateSchema.Empty() {
return false
}
- if ac.GlobalStateSchema != (basics.StateSchema{}) {
+ if !ac.GlobalStateSchema.Empty() {
return false
}
if ac.ApprovalProgram != nil {
@@ -446,22 +455,35 @@ func (ac ApplicationCallTxnFields) wellFormed(proto config.ConsensusParams) erro
}
}
+ if ac.ExtraProgramPages > uint32(proto.MaxExtraAppProgramPages) {
+ return fmt.Errorf("tx.ExtraProgramPages exceeds MaxExtraAppProgramPages = %d", proto.MaxExtraAppProgramPages)
+ }
+
effectiveEPP := ac.ExtraProgramPages
// Schemas and ExtraProgramPages may only be set during application creation
- if ac.ApplicationID != 0 {
- if ac.GlobalStateSchema != (basics.StateSchema{}) {
- return fmt.Errorf("tx.GlobalStateSchema is immutable")
+ // and explicit attempts to change size during updates.
+ if ac.ApplicationID != 0 && !(proto.AppSizeUpdates && ac.UpdatingSizes()) {
+ if !ac.GlobalStateSchema.Empty() {
+ return fmt.Errorf("inappropriate non-zero tx.GlobalStateSchema (%v)",
+ ac.GlobalStateSchema)
}
- if ac.LocalStateSchema != (basics.StateSchema{}) {
- return fmt.Errorf("tx.LocalStateSchema is immutable")
+ if !ac.LocalStateSchema.Empty() {
+ return fmt.Errorf("inappropriate non-zero tx.LocalStateSchema (%v)",
+ ac.LocalStateSchema)
}
if ac.ExtraProgramPages != 0 {
- return fmt.Errorf("tx.ExtraProgramPages is immutable")
+ return fmt.Errorf("inappropriate non-zero tx.ExtraProgramPages (%d)",
+ ac.ExtraProgramPages)
}
-
+ // allow maximimum size programs for now, since we have not checked the
+ // app params to know the actual epp.
effectiveEPP = uint32(proto.MaxExtraAppProgramPages)
}
+ if err := ac.WellSizedPrograms(effectiveEPP, proto); err != nil {
+ return err
+ }
+
// Limit total number of arguments
if len(ac.ApplicationArgs) > proto.MaxAppArgs {
return fmt.Errorf("tx.ApplicationArgs has too many arguments. %d > %d",
@@ -499,7 +521,7 @@ func (ac ApplicationCallTxnFields) wellFormed(proto config.ConsensusParams) erro
}
for _, rr := range ac.Access {
- if err := rr.wellFormed(ac.Access, proto); err != nil {
+ if err := rr.wellFormed(ac.Access, ac.ApplicationID == 0, proto); err != nil {
return err
}
}
@@ -523,14 +545,6 @@ func (ac ApplicationCallTxnFields) wellFormed(proto config.ConsensusParams) erro
}
}
- if ac.ExtraProgramPages > uint32(proto.MaxExtraAppProgramPages) {
- return fmt.Errorf("tx.ExtraProgramPages exceeds MaxExtraAppProgramPages = %d", proto.MaxExtraAppProgramPages)
- }
-
- if err := ac.WellSizedPrograms(effectiveEPP, proto); err != nil {
- return err
- }
-
for i, br := range ac.Boxes {
// recall 0 is the current app so indexes are shifted, thus test is for greater than, not gte.
if br.Index > uint64(len(ac.ForeignApps)) {
@@ -554,6 +568,12 @@ func (ac ApplicationCallTxnFields) wellFormed(proto config.ConsensusParams) erro
return nil
}
+// UpdatingSizes returns true if this is an application update transaction that has non-zero sizing fields.
+func (ac ApplicationCallTxnFields) UpdatingSizes() bool {
+ return ac.OnCompletion == UpdateApplicationOC &&
+ (ac.ExtraProgramPages != 0 || !ac.GlobalStateSchema.Empty())
+}
+
// WellSizedPrograms checks the sizes of the programs in ac, based on the
// parameters of proto and returns an error if they are too big.
func (ac ApplicationCallTxnFields) WellSizedPrograms(extraPages uint32, proto config.ConsensusParams) error {
diff --git a/data/transactions/application_string.go b/data/transactions/application_string.go
index 8548b45445..aa180be4e3 100644
--- a/data/transactions/application_string.go
+++ b/data/transactions/application_string.go
@@ -21,8 +21,9 @@ const _OnCompletion_name = "NoOpOCOptInOCCloseOutOCClearStateOCUpdateApplication
var _OnCompletion_index = [...]uint8{0, 6, 13, 23, 35, 54, 73}
func (i OnCompletion) String() string {
- if i >= OnCompletion(len(_OnCompletion_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_OnCompletion_index)-1 {
return "OnCompletion(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _OnCompletion_name[_OnCompletion_index[i]:_OnCompletion_index[i+1]]
+ return _OnCompletion_name[_OnCompletion_index[idx]:_OnCompletion_index[idx+1]]
}
diff --git a/data/transactions/application_test.go b/data/transactions/application_test.go
index aac9855967..c208b59aa1 100644
--- a/data/transactions/application_test.go
+++ b/data/transactions/application_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -37,8 +37,7 @@ func TestResourceRefEmpty(t *testing.T) {
t.Parallel()
assert.True(t, ResourceRef{}.Empty())
- for _, nz := range basics_testing.NearZeros(t, ResourceRef{}) {
- rr := nz.(ResourceRef)
+ for _, rr := range basics_testing.NearZeros(t, ResourceRef{}) {
assert.False(t, rr.Empty(), "Empty is disregarding a non-zero field in %+v", rr)
}
}
@@ -52,8 +51,7 @@ func TestApplicationCallFieldsEmpty(t *testing.T) {
ac := ApplicationCallTxnFields{}
a.True(ac.Empty())
- for _, nz := range basics_testing.NearZeros(t, ac) {
- fields := nz.(ApplicationCallTxnFields)
+ for _, fields := range basics_testing.NearZeros(t, ac) {
a.False(fields.Empty(), "Empty is disregarding a non-zero field in %+v", fields)
}
}
@@ -205,7 +203,8 @@ func TestAppCallAccessWellFormed(t *testing.T) {
},
},
{
- expectedError: "locals App reference 0 outside tx.Access",
+ // eliminate this test after AllowZeroAppInLocalsRef is removed
+ expectedError: "0 App in LocalsRef is not supported",
ac: ApplicationCallTxnFields{
ApplicationID: 1,
Access: []ResourceRef{
@@ -213,6 +212,28 @@ func TestAppCallAccessWellFormed(t *testing.T) {
{Locals: LocalsRef{Address: 1}},
},
},
+ cv: protocol.ConsensusV41,
+ },
+ {
+ ac: ApplicationCallTxnFields{
+ ApplicationID: 1,
+ Access: []ResourceRef{
+ {Address: basics.Address{0xaa}},
+ {Locals: LocalsRef{Address: 1}},
+ },
+ },
+ },
+ {
+ expectedError: "0 App in LocalsRef during app create is not allowed or necessary",
+ ac: ApplicationCallTxnFields{
+ ApplicationID: 0,
+ ApprovalProgram: []byte{0x05},
+ ClearStateProgram: []byte{0x05},
+ Access: []ResourceRef{
+ {Address: basics.Address{0xaa}},
+ {Locals: LocalsRef{Address: 1}},
+ },
+ },
},
{
ac: ApplicationCallTxnFields{
@@ -553,7 +574,7 @@ func TestWellFormedErrors(t *testing.T) {
},
GlobalStateSchema: basics.StateSchema{NumByteSlice: 1},
},
- expectedError: "tx.GlobalStateSchema is immutable",
+ expectedError: "inappropriate non-zero tx.GlobalStateSchema",
},
{
ac: ApplicationCallTxnFields{
@@ -563,7 +584,7 @@ func TestWellFormedErrors(t *testing.T) {
},
LocalStateSchema: basics.StateSchema{NumUint: 1},
},
- expectedError: "tx.LocalStateSchema is immutable",
+ expectedError: "inappropriate non-zero tx.LocalStateSchema",
},
{
ac: ApplicationCallTxnFields{
@@ -597,7 +618,7 @@ func TestWellFormedErrors(t *testing.T) {
},
ExtraProgramPages: 1,
},
- expectedError: "tx.ExtraProgramPages is immutable",
+ expectedError: "inappropriate non-zero tx.ExtraProgramPages",
},
{
ac: ApplicationCallTxnFields{
@@ -716,6 +737,39 @@ func TestWellFormedErrors(t *testing.T) {
OnCompletion: UpdateApplicationOC,
},
},
+ {
+ ac: ApplicationCallTxnFields{
+ ApplicationID: 1,
+ ApprovalProgram: []byte(strings.Repeat("X", 1025)),
+ ClearStateProgram: []byte(strings.Repeat("X", 1025)),
+ ExtraProgramPages: 0,
+ // Since we are updating the size, that includes epp, so programs are too big.
+ GlobalStateSchema: basics.StateSchema{NumByteSlice: 1},
+ OnCompletion: UpdateApplicationOC,
+ },
+ expectedError: "app programs too long. max total len 2048 bytes",
+ },
+ {
+ ac: ApplicationCallTxnFields{
+ ApplicationID: 1,
+ ApprovalProgram: []byte(strings.Repeat("X", 1025)),
+ ClearStateProgram: []byte(strings.Repeat("X", 1025)),
+ ExtraProgramPages: 1,
+ // Since we are updating epp, size is checked, but is big enough
+ OnCompletion: UpdateApplicationOC,
+ },
+ },
+ {
+ ac: ApplicationCallTxnFields{
+ ApplicationID: 1,
+ ApprovalProgram: []byte(strings.Repeat("X", 2048)),
+ ClearStateProgram: []byte(strings.Repeat("X", 2049)),
+ ExtraProgramPages: 1,
+ // Now we update epp, but not big enough for programs in txn
+ OnCompletion: UpdateApplicationOC,
+ },
+ expectedError: "app programs too long. max total len 4096 bytes",
+ },
{
ac: ApplicationCallTxnFields{
ApplicationID: 1,
@@ -728,7 +782,45 @@ func TestWellFormedErrors(t *testing.T) {
OnCompletion: UpdateApplicationOC,
},
cv: cv28,
- expectedError: "tx.ExtraProgramPages is immutable",
+ expectedError: "inappropriate non-zero tx.ExtraProgramPages",
+ },
+ {
+ ac: ApplicationCallTxnFields{
+ ApplicationID: 1,
+ ApprovalProgram: v5,
+ ClearStateProgram: v5,
+ ApplicationArgs: [][]byte{
+ []byte("write"),
+ },
+ GlobalStateSchema: basics.StateSchema{NumByteSlice: 1},
+ OnCompletion: UpdateApplicationOC,
+ },
+ cv: cv28,
+ expectedError: "inappropriate non-zero tx.GlobalStateSchema",
+ },
+ {
+ ac: ApplicationCallTxnFields{
+ ApplicationID: 1,
+ ApprovalProgram: v5,
+ ClearStateProgram: v5,
+ ApplicationArgs: [][]byte{
+ []byte("write"),
+ },
+ ExtraProgramPages: 1,
+ OnCompletion: UpdateApplicationOC,
+ },
+ },
+ {
+ ac: ApplicationCallTxnFields{
+ ApplicationID: 1,
+ ApprovalProgram: v5,
+ ClearStateProgram: v5,
+ ApplicationArgs: [][]byte{
+ []byte("write"),
+ },
+ GlobalStateSchema: basics.StateSchema{NumByteSlice: 1},
+ OnCompletion: UpdateApplicationOC,
+ },
},
{
ac: ApplicationCallTxnFields{
diff --git a/data/transactions/asset.go b/data/transactions/asset.go
index dc76d7bb8c..a6cd9ae991 100644
--- a/data/transactions/asset.go
+++ b/data/transactions/asset.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/asset_test.go b/data/transactions/asset_test.go
index b4e1cbf53c..f12f19a716 100644
--- a/data/transactions/asset_test.go
+++ b/data/transactions/asset_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/common_test.go b/data/transactions/common_test.go
index 016973eb3f..6fc9b9a96e 100644
--- a/data/transactions/common_test.go
+++ b/data/transactions/common_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/error.go b/data/transactions/error.go
index 33a279576e..5907715a44 100644
--- a/data/transactions/error.go
+++ b/data/transactions/error.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/heartbeat.go b/data/transactions/heartbeat.go
index e5f6d7faf5..c8cb88a42e 100644
--- a/data/transactions/heartbeat.go
+++ b/data/transactions/heartbeat.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/heartbeat_test.go b/data/transactions/heartbeat_test.go
index 64f637f228..538901dccc 100644
--- a/data/transactions/heartbeat_test.go
+++ b/data/transactions/heartbeat_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/json_test.go b/data/transactions/json_test.go
index b0acc9eeb3..ddaca98413 100644
--- a/data/transactions/json_test.go
+++ b/data/transactions/json_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/keyreg.go b/data/transactions/keyreg.go
index c4d0ed2628..364d1271f4 100644
--- a/data/transactions/keyreg.go
+++ b/data/transactions/keyreg.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/keyreg_test.go b/data/transactions/keyreg_test.go
index fd0d4b4a92..59d5dac223 100644
--- a/data/transactions/keyreg_test.go
+++ b/data/transactions/keyreg_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/Makefile b/data/transactions/logic/Makefile
index 21d72a71ca..c53fd2aee6 100644
--- a/data/transactions/logic/Makefile
+++ b/data/transactions/logic/Makefile
@@ -1,30 +1,33 @@
-all: TEAL_opcodes.md teal.tmLanguage.json README.md fields_string.go
+all: teal.tmLanguage.json README.md fields_string.go
# Location of algorandfoundation/specs repo. (Optional)
SPECS := ../../../../specs
-# Location of algorand/docs repo. (Optional)
-DOCS := ../../../../docs
-TEAL_opcodes.md teal.tmLanguage.json: fields_string.go ../../../cmd/opdoc/opdoc.go ../../../cmd/opdoc/tmLanguage.go eval.go assembler.go doc.go opcodes.go
+teal.tmLanguage.json: fields_string.go ../../../cmd/opdoc/opdoc.go ../../../cmd/opdoc/tmLanguage.go eval.go assembler.go doc.go opcodes.go
go run ../../../cmd/opdoc/opdoc.go ../../../cmd/opdoc/tmLanguage.go
- @cp `ls TEAL_opcodes_v??.md | tail -1` TEAL_opcodes.md
- @if [ -e $(SPECS)/dev/TEAL_opcodes.md ]; then \
- sed '/^$$/q' $(SPECS)/dev/TEAL_opcodes.md | cat - TEAL_opcodes.md > opcodes.spec; \
- mv opcodes.spec $(SPECS)/dev/TEAL_opcodes.md; \
- echo "TEAL_opcodes.md updated in specs repo"; \
+ @cp `ls TEAL_opcodes_v??.md | tail -1` avm-appendix-a.md
+ @if [ -e $(SPECS)/src/avm/avm-appendix-a.md ]; then \
+ cp avm-appendix-a.md $(SPECS)/src/avm/avm-appendix-a.md; \
+ cp avm-stack-types.md $(SPECS)/src/_include/auto/; \
+ cp constants-*.md $(SPECS)/src/_include/auto/; \
+ cp account-access.md $(SPECS)/src/_include/auto/opcodes/; \
+ cp application-access.md $(SPECS)/src/_include/auto/opcodes/; \
+ cp arithmetic.md $(SPECS)/src/_include/auto/opcodes/; \
+ cp asset-access.md $(SPECS)/src/_include/auto/opcodes/; \
+ cp block-access.md $(SPECS)/src/_include/auto/opcodes/; \
+ cp box-access.md $(SPECS)/src/_include/auto/opcodes/; \
+ cp byte-array-arithmetic.md $(SPECS)/src/_include/auto/opcodes/; \
+ cp byte-array-logic.md $(SPECS)/src/_include/auto/opcodes/; \
+ cp byte-array-manipulation.md $(SPECS)/src/_include/auto/opcodes/; \
+ cp cryptography.md $(SPECS)/src/_include/auto/opcodes/; \
+ cp flow-control.md $(SPECS)/src/_include/auto/opcodes/; \
+ cp inner-transactions.md $(SPECS)/src/_include/auto/opcodes/; \
+ cp loading-values.md $(SPECS)/src/_include/auto/opcodes/; \
+ echo "Updates in specs repo."; \
fi
- @rm TEAL_opcodes.md
fields_string.go: fields.go
go generate
-README.md: TEAL_opcodes.md README_in.md
- python3 merge.py > README.md
- @if [ -e $(SPECS)/dev/TEAL.md ]; then \
- sed '/^$$/q' $(SPECS)/dev/TEAL.md | cat - README.md > teal.spec; \
- mv teal.spec $(SPECS)/dev/TEAL.md; \
- echo "TEAL.md updated in specs repo"; \
- fi
-
clean:
rm -f TEAL_opcodes*.md langspec_v*.json README.md fields_string.go
diff --git a/data/transactions/logic/README.md b/data/transactions/logic/README.md
index 41655ff09d..9437dc09a0 100644
--- a/data/transactions/logic/README.md
+++ b/data/transactions/logic/README.md
@@ -48,949 +48,3 @@ named to provide more semantic information in the documentation. They're also us
assembly time to do type checking and to provide more informative error messages.
-#### Definitions
-
-| Name | Bound | AVM Type |
-| ---- | ---- | -------- |
-| []byte | len(x) <= 4096 | []byte |
-| address | len(x) == 32 | []byte |
-| any | | any |
-| bigint | len(x) <= 64 | []byte |
-| bool | x <= 1 | uint64 |
-| boxName | 1 <= len(x) <= 64 | []byte |
-| method | len(x) == 4 | []byte |
-| none | | none |
-| stateKey | len(x) <= 64 | []byte |
-| uint64 | x <= 18446744073709551615 | uint64 |
-
-
-
-## Scratch Space
-
-In addition to the stack there are 256 positions of scratch
-space. Like stack values, scratch locations may be uint64s or
-byte-arrays. Scratch locations are initialized as uint64 zero. Scratch
-space is accessed by the `load(s)` and `store(s)` opcodes which move
-data from or to scratch space, respectively. Application calls may
-inspect the final scratch space of earlier application calls in the
-same group using `gload(s)(s)`
-
-## Versions
-
-In order to maintain existing semantics for previously written
-programs, AVM code is versioned. When new opcodes are introduced, or
-behavior is changed, a new version is introduced. Programs carrying
-old versions are executed with their original semantics. In the AVM
-bytecode, the version is an incrementing integer, currently 12, and
-denoted vX throughout this document.
-
-## Execution Modes
-
-Starting from v2, the AVM can run programs in two modes:
-1. LogicSig or _stateless_ mode, used to execute Smart Signatures
-2. Application or _stateful_ mode, used to execute Smart Contracts
-
-Differences between modes include:
-1. Max program length (consensus parameters LogicSigMaxSize, MaxAppTotalProgramLen & MaxExtraAppProgramPages)
-2. Max program cost (consensus parameters LogicSigMaxCost, MaxAppProgramCost)
-3. Opcode availability. Refer to [opcodes document](TEAL_opcodes.md) for details.
-4. Some global values, such as LatestTimestamp, are only available in stateful mode.
-5. Only Applications can observe transaction effects, such as Logs or IDs allocated to ASAs or new Applications.
-
-## Execution Environment for Smart Signatures
-
-Smart Signatures execute as part of testing a proposed transaction to
-see if it is valid and authorized to be committed into a block. If an
-authorized program executes and finishes with a single non-zero uint64
-value on the stack then that program has validated the transaction it
-is attached to.
-
-The program has access to data from the transaction it is attached to
-(`txn` op), any transactions in a transaction group it is part of
-(`gtxn` op), and a few global values like consensus parameters
-(`global` op). Some "Args" may be attached to a transaction being
-validated by a program. Args are an array of byte strings. A common
-pattern would be to have the key to unlock some contract as an Arg. Be
-aware that Smart Signature Args are recorded on the blockchain and
-publicly visible when the transaction is submitted to the network,
-even before the transaction has been included in a block. These Args
-are _not_ part of the transaction ID nor of the TxGroup hash. They
-also cannot be read from other programs in the group of transactions.
-
-A program can either authorize some delegated action on a normal
-signature-based or multisignature-based account or be wholly in charge
-of a contract account.
-
-* If the account has signed the program (by providing a valid ed25519
- signature or valid multisignature for the authorizer address on the
- string "Program" concatenated with the program bytecode) then: if the
- program returns true the transaction is authorized as if the account
- had signed it. This allows an account to hand out a signed program
- so that other users can carry out delegated actions which are
- approved by the program. Note that Smart Signature Args are _not_
- signed.
-
-* If the SHA512_256 hash of the program (prefixed by "Program") is
- equal to authorizer address of the transaction sender then this is a
- contract account wholly controlled by the program. No other
- signature is necessary or possible. The only way to execute a
- transaction against the contract account is for the program to
- approve it.
-
-The size of a Smart Signature is defined as the length of its bytecode
-plus the length of all its Args. The sum of the sizes of all Smart
-Signatures in a group must not exceed 1000 bytes times the number of
-transactions in the group (1000 bytes is defined in consensus parameter
-`LogicSigMaxSize`).
-
-Each opcode has an associated cost, usually 1, but a few slow operations
-have higher costs. Prior to v4, the program's cost was estimated as the
-static sum of all the opcode costs in the program (whether they were
-actually executed or not). Beginning with v4, the program's cost is
-tracked dynamically while being evaluated. If the program exceeds its
-budget, it fails.
-
-The total program cost of all Smart Signatures in a group must not
-exceed 20,000 (consensus parameter LogicSigMaxCost) times the number
-of transactions in the group.
-
-
-## Execution Environment for Smart Contracts (Applications)
-
-Smart Contracts are executed in ApplicationCall transactions. Like
-Smart Signatures, contracts indicate success by leaving a single
-non-zero integer on the stack. A failed Smart Contract call to an
-ApprovalProgram is not a valid transaction, thus not written to the
-blockchain. An ApplicationCall with OnComplete set to ClearState
-invokes the ClearStateProgram, rather than the usual
-ApprovalProgram. If the ClearStateProgram fails, application state
-changes are rolled back, but the transaction still succeeds, and the
-Sender's local state for the called application is removed.
-
-Smart Contracts have access to everything a Smart Signature may access
-(see previous section), as well as the ability to examine blockchain
-state such as balances and contract state (their own state and the
-state of other contracts). They also have access to some global
-values that are not visible to Smart Signatures because the values
-change over time. Since smart contracts access changing state, nodes
-must rerun their code to determine if the ApplicationCall transactions
-in their pool would still succeed each time a block is added to the
-blockchain.
-
-Smart contracts have limits on their execution cost (700, consensus
-parameter MaxAppProgramCost). Before v4, this was a static limit on
-the cost of all the instructions in the program. Starting in v4, the cost
-is tracked dynamically during execution and must not exceed
-MaxAppProgramCost. Beginning with v5, programs costs are pooled and
-tracked dynamically across app executions in a group. If `n`
-application invocations appear in a group, then the total execution
-cost of all such calls must not exceed `n`*MaxAppProgramCost. In v6, inner
-application calls become possible, and each such call increases the
-pooled budget by MaxAppProgramCost at the time the inner group is submitted
-with `itxn_submit`.
-
-Executions of the ClearStateProgram are more stringent, in order to
-ensure that applications may be closed out, but that applications also
-are assured a chance to clean up their internal state. At the
-beginning of the execution of a ClearStateProgram, the pooled budget
-available must be MaxAppProgramCost or higher. If it is not, the
-containing transaction group fails without clearing the app's
-state. During the execution of the ClearStateProgram, no more than
-MaxAppProgramCost may be drawn. If further execution is attempted, the
-ClearStateProgram fails, and the app's state _is cleared_.
-
-
-### Resource availability
-
-Smart contracts have limits on the amount of blockchain state they may
-examine. These limits are enforced by failing any opcode that
-attempts to access a resource unless the resource is
-_available_. These resources are:
-
- * Accounts, which must be available to access their balance, or other
- account parameters such as voting details.
- * Assets, which must be available to access global asset parameters, such
- the as the asset's URL, Name, or privileged addresses.
- * Holdings, which must be available to access a particular address's
- balance or frozen status for a particular asset.
- * Applications, which must be available to read an application's
- programs, parameters, or global state.
- * Locals, which must be available to read a particular address's local
- state for a particular application.
- * Boxes, which must be available to read or write a box, designated
- by an application and name for the box.
-
-Resources are _available_ based on the contents of the executing
-transaction and, in later versions, the contents of other transactions
-in the same group.
-
- * A resource in the "foreign array" fields of the ApplicationCall
- transaction (`txn.Accounts`, `txn.ForeignAssets`, and
- `txn.ForeignApplications`) is _available_.
-
- * The `txn.Sender`, `global CurrentApplicationID`, and `global
- CurrentApplicationAddress` are _available_.
-
- * In pre-v4 applications, all holdings are _available_ to the
- `asset_holding_get` opcode, and all locals are _available_ to the
- `app_local_get_ex` opcode if the *account* of the resource is
- _available_.
-
- * In v6 and later applications, any asset or application that was
- created earlier in the same transaction group (whether by a
- top-level or inner transaction) is _available_. In addition, any
- account that is the associated account of a contract that was
- created earlier in the group is _available_.
-
- * In v7 and later applications, the account associated with any
- contract present in the `txn.ForeignApplications` field is
- _available_.
-
- * In v4 and above applications, Holdings and Locals are _available_
- if, both components of the resource are available according to the
- above rules.
-
- * In v9 and later applications, there is group-level resource
- sharing. Any resource that is available in _some_ top-level
- transaction in a transaction group is available in _all_ v9 or
- later application calls in the group, whether those application
- calls are top-level or inner.
-
- * v9 and later applications may use the `txn.Access` list instead of
- the foreign arrays. When using `txn.Access` Holdings and Locals are
- no longer made available automatically because their components
- are. Application accounts are also not made available because of
- the availability of their corresponding app. Each resource must be
- listed explicitly. However, `txn.Access` allows for the listing of
- more resources than the foreign arrays. Listed resources become
- available to other (post-v8) applications through group sharing.
-
- * When considering whether an asset holding or application local
- state is available for group-level resource sharing, the holding or
- local state must be available in a top-level transaction based on
- pre-v9 rules. For example, if account A is made available in one
- transaction, and asset X is made available in another, group
- resource sharing does _not_ make A's X holding available.
-
- * Top-level transactions that are not application calls also make
- resources available to group-level resource sharing. The following
- resources are made available by other transaction types.
-
- 1. `pay` - `txn.Sender`, `txn.Receiver`, and
- `txn.CloseRemainderTo` (if set).
-
- 1. `keyreg` - `txn.Sender`
-
- 1. `acfg` - `txn.Sender`, `txn.ConfigAsset`, and the
- `txn.ConfigAsset` holding of `txn.Sender`.
-
- 1. `axfer` - `txn.Sender`, `txn.AssetReceiver`, `txn.AssetSender`
- (if set), `txnAssetCloseTo` (if set), `txn.XferAsset`, and the
- `txn.XferAsset` holding of each of those accounts.
-
- 1. `afrz` - `txn.Sender`, `txn.FreezeAccount`, `txn.FreezeAsset`,
- and the `txn.FreezeAsset` holding of `txn.FreezeAccount`. The
- `txn.FreezeAsset` holding of `txn.Sender` is _not_ made
- available.
-
-
- * A Box is _available_ to an Approval Program if _any_ transaction in
- the same group contains a box reference (in `txn.Boxes` or
- `txn.Access`) that denotes the box. A box reference contains an
- index `i`, and name `n`. The index refers to the `ith` application
- in the transaction's `ForeignApplications` or `Access` array (only
- one of which can be used), with the usual convention that 0
- indicates the application ID of the app called by that
- transaction. No box is ever _available_ to a ClearStateProgram.
-
-Regardless of _availability_, any attempt to access an Asset or
-Application with an ID less than 256 from within a Contract will fail
-immediately. This avoids any ambiguity in opcodes that interpret their
-integer arguments as resource IDs _or_ indexes into the
-`txn.ForeignAssets` or `txn.ForeignApplications` arrays.
-
-It is recommended that contract authors avoid supplying array indexes
-to these opcodes, and always use explicit resource IDs. By using
-explicit IDs, contracts will better take advantage of group resource
-sharing. The array indexing interpretation may be deprecated in a
-future version.
-
-## Constants
-
-Constants can be pushed onto the stack in two different ways:
-
-1. Constants can be pushed directly with `pushint` or
- `pushbytes`. This method is more efficient for constants that are
- only used once.
-
-2. Constants can be loaded into storage separate from the stack and
- scratch space, using two opcodes `intcblock` and
- `bytecblock`. Then, constants from this storage can be
- pushed onto the stack by referring to the type and index using
- `intc`, `intc_[0123]`, `bytec`, and `bytec_[0123]`. This method is
- more efficient for constants that are used multiple times.
-
-The assembler will hide most of this, allowing simple use of `int 1234`
-and `byte 0xcafed00d`. Constants introduced via `int` and `byte` will
-be assembled into appropriate uses of `pushint|pushbytes` and
-`{int|byte}c, {int|byte}c_[0123]` to minimize program size.
-
-
-The opcodes `intcblock` and `bytecblock` use [proto-buf style variable length unsigned int](https://developers.google.com/protocol-buffers/docs/encoding#varint),
-reproduced [here](#varuint). The `intcblock` opcode is followed by a
-varuint specifying the number of integer constants and then that
-number of varuints. The `bytecblock` opcode is followed by a varuint
-specifying the number of byte constants, and then that number of pairs
-of (varuint, bytes) length prefixed byte strings.
-
-### Named Integer Constants
-
-#### OnComplete
-
-An application transaction must indicate the action to be taken following the execution of its approvalProgram or clearStateProgram. The constants below describe the available actions.
-
-| Value | Name | Description |
-| - | ---- | -------- |
-| 0 | NoOp | Only execute the `ApprovalProgram` associated with this application ID, with no additional effects. |
-| 1 | OptIn | Before executing the `ApprovalProgram`, allocate local state for this application into the sender's account data. |
-| 2 | CloseOut | After executing the `ApprovalProgram`, clear any local state for this application out of the sender's account data. |
-| 3 | ClearState | Don't execute the `ApprovalProgram`, and instead execute the `ClearStateProgram` (which may not reject this transaction). Additionally, clear any local state for this application out of the sender's account data as in `CloseOutOC`. |
-| 4 | UpdateApplication | After executing the `ApprovalProgram`, replace the `ApprovalProgram` and `ClearStateProgram` associated with this application ID with the programs specified in this transaction. |
-| 5 | DeleteApplication | After executing the `ApprovalProgram`, delete the application parameters from the account data of the application's creator. |
-
-#### TypeEnum constants
-
-| Value | Name | Description |
-| - | --- | ------ |
-| 0 | unknown | Unknown type. Invalid transaction |
-| 1 | pay | Payment |
-| 2 | keyreg | KeyRegistration |
-| 3 | acfg | AssetConfig |
-| 4 | axfer | AssetTransfer |
-| 5 | afrz | AssetFreeze |
-| 6 | appl | ApplicationCall |
-
-
-## Operations
-
-Most operations work with only one type of argument, uint64 or bytes, and fail if the wrong type value is on the stack.
-
-Many instructions accept values to designate Accounts, Assets, or Applications. Beginning with v4, these values may be given as an _offset_ in the corresponding Txn fields (Txn.Accounts, Txn.ForeignAssets, Txn.ForeignApps) _or_ as the value itself (a byte-array address for Accounts, or a uint64 ID). The values, however, must still be present in the Txn fields. Before v4, most opcodes required the use of an offset, except for reading account local values of assets or applications, which accepted the IDs directly and did not require the ID to be present in the corresponding _Foreign_ array. (Note that beginning with v4, those IDs _are_ required to be present in their corresponding _Foreign_ array.) See individual opcodes for details. In the case of account offsets or application offsets, 0 is specially defined to Txn.Sender or the ID of the current application, respectively.
-
-This summary is supplemented by more detail in the [opcodes document](TEAL_opcodes.md).
-
-Some operations immediately fail the program.
-A transaction checked by a program that fails is not valid.
-An account governed by a buggy program might not have a way to get assets back out of it. Code carefully.
-
-In the documentation for each opcode, the stack arguments that are
-popped are referred to alphabetically, beginning with the deepest
-argument as `A`. These arguments are shown in the opcode description,
-and if the opcode must be of a specific type, it is noted there. All
-opcodes fail if a specified type is incorrect.
-
-If an opcode pushes more than one result, the values are named for
-ease of exposition and clarity concerning their stack positions. When
-an opcode manipulates the stack in such a way that a value changes
-position but is otherwise unchanged, the name of the output on the
-return stack matches the name of the input value.
-
-### Arithmetic and Logic Operations
-
-| Opcode | Description |
-| - | -- |
-| `+` | A plus B. Fail on overflow. |
-| `-` | A minus B. Fail if B > A. |
-| `/` | A divided by B (truncated division). Fail if B == 0. |
-| `*` | A times B. Fail on overflow. |
-| `<` | A less than B => {0 or 1} |
-| `>` | A greater than B => {0 or 1} |
-| `<=` | A less than or equal to B => {0 or 1} |
-| `>=` | A greater than or equal to B => {0 or 1} |
-| `&&` | A is not zero and B is not zero => {0 or 1} |
-| `\|\|` | A is not zero or B is not zero => {0 or 1} |
-| `shl` | A times 2^B, modulo 2^64 |
-| `shr` | A divided by 2^B |
-| `sqrt` | The largest integer I such that I^2 <= A |
-| `bitlen` | The highest set bit in A. If A is a byte-array, it is interpreted as a big-endian unsigned integer. bitlen of 0 is 0, bitlen of 8 is 4 |
-| `exp` | A raised to the Bth power. Fail if A == B == 0 and on overflow |
-| `==` | A is equal to B => {0 or 1} |
-| `!=` | A is not equal to B => {0 or 1} |
-| `!` | A == 0 yields 1; else 0 |
-| `itob` | converts uint64 A to big-endian byte array, always of length 8 |
-| `btoi` | converts big-endian byte array A to uint64. Fails if len(A) > 8. Padded by leading 0s if len(A) < 8. |
-| `%` | A modulo B. Fail if B == 0. |
-| `\|` | A bitwise-or B |
-| `&` | A bitwise-and B |
-| `^` | A bitwise-xor B |
-| `~` | bitwise invert value A |
-| `mulw` | A times B as a 128-bit result in two uint64s. X is the high 64 bits, Y is the low |
-| `addw` | A plus B as a 128-bit result. X is the carry-bit, Y is the low-order 64 bits. |
-| `divw` | A,B / C. Fail if C == 0 or if result overflows. |
-| `divmodw` | W,X = (A,B / C,D); Y,Z = (A,B modulo C,D) |
-| `expw` | A raised to the Bth power as a 128-bit result in two uint64s. X is the high 64 bits, Y is the low. Fail if A == B == 0 or if the results exceeds 2^128-1 |
-
-### Byte Array Manipulation
-
-| Opcode | Description |
-| - | -- |
-| `getbit` | Bth bit of (byte-array or integer) A. If B is greater than or equal to the bit length of the value (8*byte length), the program fails |
-| `setbit` | Copy of (byte-array or integer) A, with the Bth bit set to (0 or 1) C. If B is greater than or equal to the bit length of the value (8*byte length), the program fails |
-| `getbyte` | Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails |
-| `setbyte` | Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails |
-| `concat` | join A and B |
-| `len` | yields length of byte value A |
-| `substring s e` | A range of bytes from A starting at S up to but not including E. If E < S, or either is larger than the array length, the program fails |
-| `substring3` | A range of bytes from A starting at B up to but not including C. If C < B, or either is larger than the array length, the program fails |
-| `extract s l` | A range of bytes from A starting at S up to but not including S+L. If L is 0, then extract to the end of the string. If S or S+L is larger than the array length, the program fails |
-| `extract3` | A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails `extract3` can be called using `extract` with no immediates. |
-| `extract_uint16` | A uint16 formed from a range of big-endian bytes from A starting at B up to but not including B+2. If B+2 is larger than the array length, the program fails |
-| `extract_uint32` | A uint32 formed from a range of big-endian bytes from A starting at B up to but not including B+4. If B+4 is larger than the array length, the program fails |
-| `extract_uint64` | A uint64 formed from a range of big-endian bytes from A starting at B up to but not including B+8. If B+8 is larger than the array length, the program fails |
-| `replace2 s` | Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A) `replace2` can be called using `replace` with 1 immediate. |
-| `replace3` | Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A) `replace3` can be called using `replace` with no immediates. |
-| `base64_decode e` | decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E |
-| `json_ref r` | key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A |
-
-The following opcodes take byte-array values that are interpreted as
-big-endian unsigned integers. For mathematical operators, the
-returned values are the shortest byte-array that can represent the
-returned value. For example, the zero value is the empty
-byte-array. For comparison operators, the returned value is a uint64.
-
-Input lengths are limited to a maximum length of 64 bytes,
-representing a 512 bit unsigned integer. Output lengths are not
-explicitly restricted, though only `b*` and `b+` can produce a larger
-output than their inputs, so there is an implicit length limit of 128
-bytes on outputs.
-
-| Opcode | Description |
-| - | -- |
-| `b+` | A plus B. A and B are interpreted as big-endian unsigned integers |
-| `b-` | A minus B. A and B are interpreted as big-endian unsigned integers. Fail on underflow. |
-| `b/` | A divided by B (truncated division). A and B are interpreted as big-endian unsigned integers. Fail if B is zero. |
-| `b*` | A times B. A and B are interpreted as big-endian unsigned integers. |
-| `b<` | 1 if A is less than B, else 0. A and B are interpreted as big-endian unsigned integers |
-| `b>` | 1 if A is greater than B, else 0. A and B are interpreted as big-endian unsigned integers |
-| `b<=` | 1 if A is less than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers |
-| `b>=` | 1 if A is greater than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers |
-| `b==` | 1 if A is equal to B, else 0. A and B are interpreted as big-endian unsigned integers |
-| `b!=` | 0 if A is equal to B, else 1. A and B are interpreted as big-endian unsigned integers |
-| `b%` | A modulo B. A and B are interpreted as big-endian unsigned integers. Fail if B is zero. |
-| `bsqrt` | The largest integer I such that I^2 <= A. A and I are interpreted as big-endian unsigned integers |
-
-These opcodes operate on the bits of byte-array values. The shorter
-input array is interpreted as though left padded with zeros until it is the
-same length as the other input. The returned values are the same
-length as the longer input. Therefore, unlike array arithmetic,
-these results may contain leading zero bytes.
-
-| Opcode | Description |
-| - | -- |
-| `b\|` | A bitwise-or B. A and B are zero-left extended to the greater of their lengths |
-| `b&` | A bitwise-and B. A and B are zero-left extended to the greater of their lengths |
-| `b^` | A bitwise-xor B. A and B are zero-left extended to the greater of their lengths |
-| `b~` | A with all bits inverted |
-
-### Cryptographic Operations
-
-| Opcode | Description |
-| - | -- |
-| `sha256` | SHA256 hash of value A, yields [32]byte |
-| `keccak256` | Keccak256 hash of value A, yields [32]byte |
-| `sha512_256` | SHA512_256 hash of value A, yields [32]byte |
-| `sha3_256` | SHA3_256 hash of value A, yields [32]byte |
-| `falcon_verify` | for (data A, compressed-format signature B, pubkey C) verify the signature of data against the pubkey => {0 or 1} |
-| `ed25519verify` | for (data A, signature B, pubkey C) verify the signature of ("ProgData" \|\| program_hash \|\| data) against the pubkey => {0 or 1} |
-| `ed25519verify_bare` | for (data A, signature B, pubkey C) verify the signature of the data against the pubkey => {0 or 1} |
-| `ecdsa_verify v` | for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1} |
-| `ecdsa_pk_recover v` | for (data A, recovery id B, signature C, D) recover a public key |
-| `ecdsa_pk_decompress v` | decompress pubkey A into components X, Y |
-| `vrf_verify s` | Verify the proof B of message A against pubkey C. Returns vrf output and verification flag. |
-| `ec_add g` | for curve points A and B, return the curve point A + B |
-| `ec_scalar_mul g` | for curve point A and scalar B, return the curve point BA, the point A multiplied by the scalar B. |
-| `ec_pairing_check g` | 1 if the product of the pairing of each point in A with its respective point in B is equal to the identity element of the target group Gt, else 0 |
-| `ec_multi_scalar_mul g` | for curve points A and scalars B, return curve point B0A0 + B1A1 + B2A2 + ... + BnAn |
-| `ec_subgroup_check g` | 1 if A is in the main prime-order subgroup of G (including the point at infinity) else 0. Program fails if A is not in G at all. |
-| `ec_map_to g` | maps field element A to group G |
-| `mimc c` | MiMC hash of scalars A, using curve and parameters specified by configuration C |
-
-### Loading Values
-
-Opcodes for getting data onto the stack.
-
-Some of these have immediate data in the byte or bytes after the opcode.
-
-| Opcode | Description |
-| - | -- |
-| `intcblock uint ...` | prepare block of uint64 constants for use by intc |
-| `intc i` | Ith constant from intcblock |
-| `intc_0` | constant 0 from intcblock |
-| `intc_1` | constant 1 from intcblock |
-| `intc_2` | constant 2 from intcblock |
-| `intc_3` | constant 3 from intcblock |
-| `pushint uint` | immediate UINT |
-| `pushints uint ...` | push sequence of immediate uints to stack in the order they appear (first uint being deepest) |
-| `bytecblock bytes ...` | prepare block of byte-array constants for use by bytec |
-| `bytec i` | Ith constant from bytecblock |
-| `bytec_0` | constant 0 from bytecblock |
-| `bytec_1` | constant 1 from bytecblock |
-| `bytec_2` | constant 2 from bytecblock |
-| `bytec_3` | constant 3 from bytecblock |
-| `pushbytes bytes` | immediate BYTES |
-| `pushbytess bytes ...` | push sequences of immediate byte arrays to stack (first byte array being deepest) |
-| `bzero` | zero filled byte-array of length A |
-| `arg n` | Nth LogicSig argument |
-| `arg_0` | LogicSig argument 0 |
-| `arg_1` | LogicSig argument 1 |
-| `arg_2` | LogicSig argument 2 |
-| `arg_3` | LogicSig argument 3 |
-| `args` | Ath LogicSig argument |
-| `txn f` | field F of current transaction |
-| `gtxn t f` | field F of the Tth transaction in the current group |
-| `txna f i` | Ith value of the array field F of the current transaction `txna` can be called using `txn` with 2 immediates. |
-| `txnas f` | Ath value of the array field F of the current transaction |
-| `gtxna t f i` | Ith value of the array field F from the Tth transaction in the current group `gtxna` can be called using `gtxn` with 3 immediates. |
-| `gtxnas t f` | Ath value of the array field F from the Tth transaction in the current group |
-| `gtxns f` | field F of the Ath transaction in the current group |
-| `gtxnsa f i` | Ith value of the array field F from the Ath transaction in the current group `gtxnsa` can be called using `gtxns` with 2 immediates. |
-| `gtxnsas f` | Bth value of the array field F from the Ath transaction in the current group |
-| `global f` | global field F |
-| `load i` | Ith scratch space value. All scratch spaces are 0 at program start. |
-| `loads` | Ath scratch space value. All scratch spaces are 0 at program start. |
-| `store i` | store A to the Ith scratch space |
-| `stores` | store B to the Ath scratch space |
-| `gload t i` | Ith scratch space value of the Tth transaction in the current group |
-| `gloads i` | Ith scratch space value of the Ath transaction in the current group |
-| `gloadss` | Bth scratch space value of the Ath transaction in the current group |
-| `gaid t` | ID of the asset or application created in the Tth transaction of the current group |
-| `gaids` | ID of the asset or application created in the Ath transaction of the current group |
-
-#### Transaction Fields
-##### Scalar Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
-| 0 | Sender | address | | 32 byte address |
-| 1 | Fee | uint64 | | microalgos |
-| 2 | FirstValid | uint64 | | round number |
-| 3 | FirstValidTime | uint64 | v7 | UNIX timestamp of block before txn.FirstValid. Fails if negative |
-| 4 | LastValid | uint64 | | round number |
-| 5 | Note | []byte | | Any data up to 1024 bytes |
-| 6 | Lease | [32]byte | | 32 byte lease value |
-| 7 | Receiver | address | | 32 byte address |
-| 8 | Amount | uint64 | | microalgos |
-| 9 | CloseRemainderTo | address | | 32 byte address |
-| 10 | VotePK | [32]byte | | 32 byte address |
-| 11 | SelectionPK | [32]byte | | 32 byte address |
-| 12 | VoteFirst | uint64 | | The first round that the participation key is valid. |
-| 13 | VoteLast | uint64 | | The last round that the participation key is valid. |
-| 14 | VoteKeyDilution | uint64 | | Dilution for the 2-level participation key |
-| 15 | Type | []byte | | Transaction type as bytes |
-| 16 | TypeEnum | uint64 | | Transaction type as integer |
-| 17 | XferAsset | uint64 | | Asset ID |
-| 18 | AssetAmount | uint64 | | value in Asset's units |
-| 19 | AssetSender | address | | 32 byte address. Source of assets if Sender is the Asset's Clawback address. |
-| 20 | AssetReceiver | address | | 32 byte address |
-| 21 | AssetCloseTo | address | | 32 byte address |
-| 22 | GroupIndex | uint64 | | Position of this transaction within an atomic transaction group. A stand-alone transaction is implicitly element 0 in a group of 1 |
-| 23 | TxID | [32]byte | | The computed ID for this transaction. 32 bytes. |
-| 24 | ApplicationID | uint64 | v2 | ApplicationID from ApplicationCall transaction |
-| 25 | OnCompletion | uint64 | v2 | ApplicationCall transaction on completion action |
-| 27 | NumAppArgs | uint64 | v2 | Number of ApplicationArgs |
-| 29 | NumAccounts | uint64 | v2 | Number of Accounts |
-| 30 | ApprovalProgram | []byte | v2 | Approval program |
-| 31 | ClearStateProgram | []byte | v2 | Clear state program |
-| 32 | RekeyTo | address | v2 | 32 byte Sender's new AuthAddr |
-| 33 | ConfigAsset | uint64 | v2 | Asset ID in asset config transaction |
-| 34 | ConfigAssetTotal | uint64 | v2 | Total number of units of this asset created |
-| 35 | ConfigAssetDecimals | uint64 | v2 | Number of digits to display after the decimal place when displaying the asset |
-| 36 | ConfigAssetDefaultFrozen | bool | v2 | Whether the asset's slots are frozen by default or not, 0 or 1 |
-| 37 | ConfigAssetUnitName | []byte | v2 | Unit name of the asset |
-| 38 | ConfigAssetName | []byte | v2 | The asset name |
-| 39 | ConfigAssetURL | []byte | v2 | URL |
-| 40 | ConfigAssetMetadataHash | [32]byte | v2 | 32 byte commitment to unspecified asset metadata |
-| 41 | ConfigAssetManager | address | v2 | 32 byte address |
-| 42 | ConfigAssetReserve | address | v2 | 32 byte address |
-| 43 | ConfigAssetFreeze | address | v2 | 32 byte address |
-| 44 | ConfigAssetClawback | address | v2 | 32 byte address |
-| 45 | FreezeAsset | uint64 | v2 | Asset ID being frozen or un-frozen |
-| 46 | FreezeAssetAccount | address | v2 | 32 byte address of the account whose asset slot is being frozen or un-frozen |
-| 47 | FreezeAssetFrozen | bool | v2 | The new frozen value, 0 or 1 |
-| 49 | NumAssets | uint64 | v3 | Number of Assets |
-| 51 | NumApplications | uint64 | v3 | Number of Applications |
-| 52 | GlobalNumUint | uint64 | v3 | Number of global state integers in ApplicationCall |
-| 53 | GlobalNumByteSlice | uint64 | v3 | Number of global state byteslices in ApplicationCall |
-| 54 | LocalNumUint | uint64 | v3 | Number of local state integers in ApplicationCall |
-| 55 | LocalNumByteSlice | uint64 | v3 | Number of local state byteslices in ApplicationCall |
-| 56 | ExtraProgramPages | uint64 | v4 | Number of additional pages for each of the application's approval and clear state programs. An ExtraProgramPages of 1 means 2048 more total bytes, or 1024 for each program. |
-| 57 | Nonparticipation | bool | v5 | Marks an account nonparticipating for rewards |
-| 59 | NumLogs | uint64 | v5 | Number of Logs (only with `itxn` in v5). Application mode only |
-| 60 | CreatedAssetID | uint64 | v5 | Asset ID allocated by the creation of an ASA (only with `itxn` in v5). Application mode only |
-| 61 | CreatedApplicationID | uint64 | v5 | ApplicationID allocated by the creation of an application (only with `itxn` in v5). Application mode only |
-| 62 | LastLog | []byte | v6 | The last message emitted. Empty bytes if none were emitted. Application mode only |
-| 63 | StateProofPK | [64]byte | v6 | State proof public key |
-| 65 | NumApprovalProgramPages | uint64 | v7 | Number of Approval Program pages |
-| 67 | NumClearStateProgramPages | uint64 | v7 | Number of ClearState Program pages |
-| 68 | RejectVersion | uint64 | v12 | Application version for which the txn must reject |
-
-##### Array Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
-| 26 | ApplicationArgs | []byte | v2 | Arguments passed to the application in the ApplicationCall transaction |
-| 28 | Accounts | address | v2 | Accounts listed in the ApplicationCall transaction |
-| 48 | Assets | uint64 | v3 | Foreign Assets listed in the ApplicationCall transaction |
-| 50 | Applications | uint64 | v3 | Foreign Apps listed in the ApplicationCall transaction |
-| 58 | Logs | []byte | v5 | Log messages emitted by an application call (only with `itxn` in v5). Application mode only |
-| 64 | ApprovalProgramPages | []byte | v7 | Approval Program as an array of pages |
-| 66 | ClearStateProgramPages | []byte | v7 | ClearState Program as an array of pages |
-
-
-Additional details in the [opcodes document](TEAL_opcodes.md#txn) on the `txn` op.
-
-**Global Fields**
-
-Global fields are fields that are common to all the transactions in the group. In particular it includes consensus parameters.
-
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
-| 0 | MinTxnFee | uint64 | | microalgos |
-| 1 | MinBalance | uint64 | | microalgos |
-| 2 | MaxTxnLife | uint64 | | rounds |
-| 3 | ZeroAddress | address | | 32 byte address of all zero bytes |
-| 4 | GroupSize | uint64 | | Number of transactions in this atomic transaction group. At least 1 |
-| 5 | LogicSigVersion | uint64 | v2 | Maximum supported version |
-| 6 | Round | uint64 | v2 | Current round number. Application mode only. |
-| 7 | LatestTimestamp | uint64 | v2 | Last confirmed block UNIX timestamp. Fails if negative. Application mode only. |
-| 8 | CurrentApplicationID | uint64 | v2 | ID of current application executing. Application mode only. |
-| 9 | CreatorAddress | address | v3 | Address of the creator of the current application. Application mode only. |
-| 10 | CurrentApplicationAddress | address | v5 | Address that the current application controls. Application mode only. |
-| 11 | GroupID | [32]byte | v5 | ID of the transaction group. 32 zero bytes if the transaction is not part of a group. |
-| 12 | OpcodeBudget | uint64 | v6 | The remaining cost that can be spent by opcodes in this program. |
-| 13 | CallerApplicationID | uint64 | v6 | The application ID of the application that called this application. 0 if this application is at the top-level. Application mode only. |
-| 14 | CallerApplicationAddress | address | v6 | The application address of the application that called this application. ZeroAddress if this application is at the top-level. Application mode only. |
-| 15 | AssetCreateMinBalance | uint64 | v10 | The additional minimum balance required to create (and opt-in to) an asset. |
-| 16 | AssetOptInMinBalance | uint64 | v10 | The additional minimum balance required to opt-in to an asset. |
-| 17 | GenesisHash | [32]byte | v10 | The Genesis Hash for the network. |
-| 18 | PayoutsEnabled | bool | v11 | Whether block proposal payouts are enabled. |
-| 19 | PayoutsGoOnlineFee | uint64 | v11 | The fee required in a keyreg transaction to make an account incentive eligible. |
-| 20 | PayoutsPercent | uint64 | v11 | The percentage of transaction fees in a block that can be paid to the block proposer. |
-| 21 | PayoutsMinBalance | uint64 | v11 | The minimum balance an account must have in the agreement round to receive block payouts in the proposal round. |
-| 22 | PayoutsMaxBalance | uint64 | v11 | The maximum balance an account can have in the agreement round to receive block payouts in the proposal round. |
-
-
-**Asset Fields**
-
-Asset fields include `AssetHolding` and `AssetParam` fields that are used in the `asset_holding_get` and `asset_params_get` opcodes.
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
-| 0 | AssetBalance | uint64 | Amount of the asset unit held by this account |
-| 1 | AssetFrozen | bool | Is the asset frozen or not |
-
-
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
-| 0 | AssetTotal | uint64 | | Total number of units of this asset |
-| 1 | AssetDecimals | uint64 | | See AssetParams.Decimals |
-| 2 | AssetDefaultFrozen | bool | | Frozen by default or not |
-| 3 | AssetUnitName | []byte | | Asset unit name |
-| 4 | AssetName | []byte | | Asset name |
-| 5 | AssetURL | []byte | | URL with additional info about the asset |
-| 6 | AssetMetadataHash | [32]byte | | Arbitrary commitment |
-| 7 | AssetManager | address | | Manager address |
-| 8 | AssetReserve | address | | Reserve address |
-| 9 | AssetFreeze | address | | Freeze address |
-| 10 | AssetClawback | address | | Clawback address |
-| 11 | AssetCreator | address | v5 | Creator address |
-
-
-**App Fields**
-
-App fields used in the `app_params_get` opcode.
-
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
-| 0 | AppApprovalProgram | []byte | | Bytecode of Approval Program |
-| 1 | AppClearStateProgram | []byte | | Bytecode of Clear State Program |
-| 2 | AppGlobalNumUint | uint64 | | Number of uint64 values allowed in Global State |
-| 3 | AppGlobalNumByteSlice | uint64 | | Number of byte array values allowed in Global State |
-| 4 | AppLocalNumUint | uint64 | | Number of uint64 values allowed in Local State |
-| 5 | AppLocalNumByteSlice | uint64 | | Number of byte array values allowed in Local State |
-| 6 | AppExtraProgramPages | uint64 | | Number of Extra Program Pages of code space |
-| 7 | AppCreator | address | | Creator address |
-| 8 | AppAddress | address | | Address for which this application has authority |
-| 9 | AppVersion | uint64 | v12 | Version of the app, incremented each time the approval or clear program changes |
-
-
-**Account Fields**
-
-Account fields used in the `acct_params_get` opcode.
-
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
-| 0 | AcctBalance | uint64 | | Account balance in microalgos |
-| 1 | AcctMinBalance | uint64 | | Minimum required balance for account, in microalgos |
-| 2 | AcctAuthAddr | address | | Address the account is rekeyed to. |
-| 3 | AcctTotalNumUint | uint64 | v8 | The total number of uint64 values allocated by this account in Global and Local States. |
-| 4 | AcctTotalNumByteSlice | uint64 | v8 | The total number of byte array values allocated by this account in Global and Local States. |
-| 5 | AcctTotalExtraAppPages | uint64 | v8 | The number of extra app code pages used by this account. |
-| 6 | AcctTotalAppsCreated | uint64 | v8 | The number of existing apps created by this account. |
-| 7 | AcctTotalAppsOptedIn | uint64 | v8 | The number of apps this account is opted into. |
-| 8 | AcctTotalAssetsCreated | uint64 | v8 | The number of existing ASAs created by this account. |
-| 9 | AcctTotalAssets | uint64 | v8 | The numbers of ASAs held by this account (including ASAs this account created). |
-| 10 | AcctTotalBoxes | uint64 | v8 | The number of existing boxes created by this account's app. |
-| 11 | AcctTotalBoxBytes | uint64 | v8 | The total number of bytes used by this account's app's box keys and values. |
-| 12 | AcctIncentiveEligible | bool | v11 | Has this account opted into block payouts |
-| 13 | AcctLastProposed | uint64 | v11 | The round number of the last block this account proposed. |
-| 14 | AcctLastHeartbeat | uint64 | v11 | The round number of the last block this account sent a heartbeat. |
-
-
-### Flow Control
-
-| Opcode | Description |
-| - | -- |
-| `err` | Fail immediately. |
-| `bnz target` | branch to TARGET if value A is not zero |
-| `bz target` | branch to TARGET if value A is zero |
-| `b target` | branch unconditionally to TARGET |
-| `return` | use A as success value; end |
-| `pop` | discard A |
-| `popn n` | remove N values from the top of the stack |
-| `dup` | duplicate A |
-| `dup2` | duplicate A and B |
-| `dupn n` | duplicate A, N times |
-| `dig n` | Nth value from the top of the stack. dig 0 is equivalent to dup |
-| `bury n` | replace the Nth value from the top of the stack with A. bury 0 fails. |
-| `cover n` | remove top of stack, and place it deeper in the stack such that N elements are above it. Fails if stack depth <= N. |
-| `uncover n` | remove the value at depth N in the stack and shift above items down so the Nth deep value is on top of the stack. Fails if stack depth <= N. |
-| `frame_dig i` | Nth (signed) value from the frame pointer. |
-| `frame_bury i` | replace the Nth (signed) value from the frame pointer in the stack with A |
-| `swap` | swaps A and B on stack |
-| `select` | selects one of two values based on top-of-stack: B if C != 0, else A |
-| `assert` | immediately fail unless A is a non-zero number |
-| `callsub target` | branch unconditionally to TARGET, saving the next instruction on the call stack |
-| `proto a r` | Prepare top call frame for a retsub that will assume A args and R return values. |
-| `retsub` | pop the top instruction from the call stack and branch to it |
-| `switch target ...` | branch to the Ath label. Continue at following instruction if index A exceeds the number of labels. |
-| `match target ...` | given match cases from A[1] to A[N], branch to the Ith label where A[I] = B. Continue to the following instruction if no matches are found. |
-
-### State Access
-
-| Opcode | Description |
-| - | -- |
-| `balance` | balance for account A, in microalgos. The balance is observed after the effects of previous transactions in the group, and after the fee for the current transaction is deducted. Changes caused by inner transactions are observable immediately following `itxn_submit` |
-| `min_balance` | minimum required balance for account A, in microalgos. Required balance is affected by ASA, App, and Box usage. When creating or opting into an app, the minimum balance grows before the app code runs, therefore the increase is visible there. When deleting or closing out, the minimum balance decreases after the app executes. Changes caused by inner transactions or box usage are observable immediately following the opcode effecting the change. |
-| `app_opted_in` | 1 if account A is opted in to application B, else 0 |
-| `app_local_get` | local state of the key B in the current application in account A |
-| `app_local_get_ex` | X is the local state of application B, key C in account A. Y is 1 if key existed, else 0 |
-| `app_global_get` | global state of the key A in the current application |
-| `app_global_get_ex` | X is the global state of application A, key B. Y is 1 if key existed, else 0 |
-| `app_local_put` | write C to key B in account A's local state of the current application |
-| `app_global_put` | write B to key A in the global state of the current application |
-| `app_local_del` | delete key B from account A's local state of the current application |
-| `app_global_del` | delete key A from the global state of the current application |
-| `asset_holding_get f` | X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0 |
-| `asset_params_get f` | X is field F from asset A. Y is 1 if A exists, else 0 |
-| `app_params_get f` | X is field F from app A. Y is 1 if A exists, else 0 |
-| `acct_params_get f` | X is field F from account A. Y is 1 if A owns positive algos, else 0 |
-| `voter_params_get f` | 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 |
-| `online_stake` | the total online stake in the agreement round |
-| `log` | write A to log state of the current application |
-| `block f` | field F of block A. Fail unless A falls between txn.LastValid-1002 and txn.FirstValid (exclusive) |
-
-### Box Access
-
-Box opcodes that create, delete, or resize boxes affect the minimum
-balance requirement of the calling application's account. The change
-is immediate, and can be observed after exection by using
-`min_balance`. If the account does not possess the new minimum
-balance, the opcode fails.
-
-All box related opcodes fail immediately if used in a
-ClearStateProgram. This behavior is meant to discourage Smart Contract
-authors from depending upon the availability of boxes in a ClearState
-transaction, as accounts using ClearState are under no requirement to
-furnish appropriate Box References. Authors would do well to keep the
-same issue in mind with respect to the availability of Accounts,
-Assets, and Apps though State Access opcodes _are_ allowed in
-ClearState programs because the current application and sender account
-are sure to be _available_.
-
-| Opcode | Description |
-| - | -- |
-| `box_create` | create a box named A, of length B. Fail if the name A is empty or B exceeds 32,768. Returns 0 if A already existed, else 1 |
-| `box_extract` | read C bytes from box A, starting at offset B. Fail if A does not exist, or the byte range is outside A's size. |
-| `box_replace` | write byte-array C into box A, starting at offset B. Fail if A does not exist, or the byte range is outside A's size. |
-| `box_splice` | set box A to contain its previous bytes up to index B, followed by D, followed by the original bytes of A that began at index B+C. |
-| `box_del` | delete box named A if it exists. Return 1 if A existed, 0 otherwise |
-| `box_len` | X is the length of box A if A exists, else 0. Y is 1 if A exists, else 0. |
-| `box_get` | X is the contents of box A if A exists, else ''. Y is 1 if A exists, else 0. |
-| `box_put` | replaces the contents of box A with byte-array B. Fails if A exists and len(B) != len(box A). Creates A if it does not exist |
-| `box_resize` | change the size of box named A to be of length B, adding zero bytes to end or removing bytes from the end, as needed. Fail if the name A is empty, A is not an existing box, or B exceeds 32,768. |
-
-### Inner Transactions
-
-The following opcodes allow for "inner transactions". Inner
-transactions allow stateful applications to have many of the effects
-of a true top-level transaction, programmatically. However, they are
-different in significant ways. The most important differences are
-that they are not signed, duplicates are not rejected, and they do not
-appear in the block in the usual away. Instead, their effects are
-noted in metadata associated with their top-level application
-call transaction. An inner transaction's `Sender` must be the
-SHA512_256 hash of the application ID (prefixed by "appID"), or an
-account that has been rekeyed to that hash.
-
-In v5, inner transactions may perform `pay`, `axfer`, `acfg`, and
-`afrz` effects. After executing an inner transaction with
-`itxn_submit`, the effects of the transaction are visible beginning
-with the next instruction with, for example, `balance` and
-`min_balance` checks. In v6, inner transactions may also perform
-`keyreg` and `appl` effects. Inner `appl` calls fail if they attempt
-to invoke a program with version less than v4, or if they attempt to
-opt-in to an app with a ClearState Program less than v4.
-
-In v5, only a subset of the transaction's header fields may be set: `Type`/`TypeEnum`,
-`Sender`, and `Fee`. In v6, header fields `Note` and `RekeyTo` may
-also be set. For the specific (non-header) fields of each transaction
-type, any field may be set. This allows, for example, clawback
-transactions, asset opt-ins, and asset creates in addition to the more
-common uses of `axfer` and `acfg`. All fields default to the zero
-value, except those described under `itxn_begin`.
-
-Fields may be set multiple times, but may not be read. The most recent
-setting is used when `itxn_submit` executes. For this purpose `Type`
-and `TypeEnum` are considered to be the same field. When using
-`itxn_field` to set an array field (`ApplicationArgs` `Accounts`,
-`Assets`, or `Applications`) each use adds an element to the end of
-the array, rather than setting the entire array at once.
-
-`itxn_field` fails immediately for unsupported fields, unsupported
-transaction types, or improperly typed values for a particular
-field. `itxn_field` makes acceptance decisions entirely from the field
-and value provided, never considering previously set fields. Illegal
-interactions between fields, such as setting fields that belong to two
-different transaction types, are rejected by `itxn_submit`.
-
-| Opcode | Description |
-| - | -- |
-| `itxn_begin` | begin preparation of a new inner transaction in a new transaction group |
-| `itxn_next` | begin preparation of a new inner transaction in the same transaction group |
-| `itxn_field f` | set field F of the current inner transaction to A |
-| `itxn_submit` | execute the current inner transaction group. Fail if executing this group would exceed the inner transaction limit, or if any transaction in the group fails. |
-| `itxn f` | field F of the last inner transaction |
-| `itxna f i` | Ith value of the array field F of the last inner transaction |
-| `itxnas f` | Ath value of the array field F of the last inner transaction |
-| `gitxn t f` | field F of the Tth transaction in the last inner group submitted |
-| `gitxna t f i` | Ith value of the array field F from the Tth transaction in the last inner group submitted |
-| `gitxnas t f` | Ath value of the array field F from the Tth transaction in the last inner group submitted |
-
-
-# Assembler Syntax
-
-The assembler parses line by line. Ops that only take stack arguments
-appear on a line by themselves. Immediate arguments follow the opcode
-on the same line, separated by whitespace.
-
-The first line may contain a special version pragma `#pragma version X`, which directs the assembler to generate bytecode targeting a certain version. For instance, `#pragma version 2` produces bytecode targeting v2. By default, the assembler targets v1.
-
-Subsequent lines may contain other pragma declarations (i.e., `#pragma `), pertaining to checks that the assembler should perform before agreeing to emit the program bytes, specific optimizations, etc. Those declarations are optional and cannot alter the semantics as described in this document.
-
-"`//`" prefixes a line comment.
-
-## Constants and Pseudo-Ops
-
-A few pseudo-ops simplify writing code. `int` and `byte` and `addr` and `method` followed by a constant record the constant to a `intcblock` or `bytecblock` at the beginning of code and insert an `intc` or `bytec` reference where the instruction appears to load that value. `addr` parses an Algorand account address base32 and converts it to a regular bytes constant. `method` is passed a method signature and takes the first four bytes of the hash to convert it to the standard method selector defined in [ARC4](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0004.md)
-
-`byte` constants are:
-```
-byte base64 AAAA...
-byte b64 AAAA...
-byte base64(AAAA...)
-byte b64(AAAA...)
-byte base32 AAAA...
-byte b32 AAAA...
-byte base32(AAAA...)
-byte b32(AAAA...)
-byte 0x0123456789abcdef...
-byte "\x01\x02"
-byte "string literal"
-```
-
-`int` constants may be `0x` prefixed for hex, `0o` or `0` prefixed for
-octal, `0b` for binary, or decimal numbers.
-
-`intcblock` may be explicitly assembled. It will conflict with the assembler gathering `int` pseudo-ops into a `intcblock` program prefix, but may be used if code only has explicit `intc` references. `intcblock` should be followed by space separated int constants all on one line.
-
-`bytecblock` may be explicitly assembled. It will conflict with the assembler if there are any `byte` pseudo-ops but may be used if only explicit `bytec` references are used. `bytecblock` should be followed with byte constants all on one line, either 'encoding value' pairs (`b64 AAA...`) or 0x prefix or function-style values (`base64(...)`) or string literal values.
-
-## Labels and Branches
-
-A label is defined by any string not some other opcode or keyword and ending in ':'. A label can be an argument (without the trailing ':') to a branching instruction.
-
-Example:
-```
-int 1
-bnz safe
-err
-safe:
-pop
-```
-
-# Encoding and Versioning
-
-A compiled program starts with a varuint declaring the version of the compiled code. Any addition, removal, or change of opcode behavior increments the version. For the most part opcode behavior should not change, addition will be infrequent (not likely more often than every three months and less often as the language matures), and removal should be very rare.
-
-For version 1, subsequent bytes after the varuint are program opcode bytes. Future versions could put other metadata following the version identifier.
-
-It is important to prevent newly-introduced transaction types and
-fields from breaking assumptions made by programs written before they
-existed. If one of the transactions in a group will execute a program
-whose version predates a transaction type or field that can violate
-expectations, that transaction type or field must not be used anywhere
-in the transaction group.
-
-Concretely, the above requirement is translated as follows: A v1
-program included in a transaction group that includes a
-ApplicationCall transaction or a non-zero RekeyTo field will fail
-regardless of the program itself.
-
-This requirement is enforced as follows:
-
-* For every transaction, compute the earliest version that supports
- all the fields and values in this transaction.
-
-* Compute the largest version number across all the transactions in a group (of size 1 or more), call it `maxVerNo`. If any transaction in this group has a program with a version smaller than `maxVerNo`, then that program will fail.
-
-In addition, applications must be v4 or greater to be called in an inner transaction.
-
-## Varuint
-
-A '[proto-buf style variable length unsigned int](https://developers.google.com/protocol-buffers/docs/encoding#varint)' is encoded with 7 data bits per byte and the high bit is 1 if there is a following byte and 0 for the last byte. The lowest order 7 bits are in the first byte, followed by successively higher groups of 7 bits.
-
-# What AVM Programs Cannot Do
-
-Design and implementation limitations to be aware of with various versions.
-
-* Stateless programs cannot lookup balances of Algos or other
- assets. (Standard transaction accounting will apply after the Smart
- Signature has authorized a transaction. A transaction could still be
- invalid by other accounting rules just as a standard signed
- transaction could be invalid. e.g. I can't give away money I don't
- have.)
-* Programs cannot access information in previous blocks. Programs
- cannot access information in other transactions in the current
- block, unless they are a part of the same atomic transaction group.
-* Smart Signatures cannot know exactly what round the current transaction
- will commit in (but it is somewhere in FirstValid through
- LastValid).
-* Programs cannot know exactly what time its transaction is committed.
-* Programs cannot loop prior to v4. In v3 and prior, the branch
- instructions `bnz` "branch if not zero", `bz` "branch if zero" and
- `b` "branch" can only branch forward.
-* Until v4, the AVM had no notion of subroutines (and therefore no
- recursion). As of v4, use `callsub` and `retsub`.
-* Programs cannot make indirect jumps. `b`, `bz`, `bnz`, and `callsub`
- jump to an immediately specified address, and `retsub` jumps to the
- address currently on the top of the call stack, which is manipulated
- only by previous calls to `callsub` and `retsub`.
diff --git a/data/transactions/logic/README_in.md b/data/transactions/logic/README_in.md
deleted file mode 100644
index f6391c3c37..0000000000
--- a/data/transactions/logic/README_in.md
+++ /dev/null
@@ -1,618 +0,0 @@
-# The Algorand Virtual Machine (AVM) and TEAL.
-
-The AVM is a bytecode based stack interpreter that executes programs
-associated with Algorand transactions. TEAL is an assembly language
-syntax for specifying a program that is ultimately converted to AVM
-bytecode. These programs can be used to check the parameters of the
-transaction and approve the transaction as if by a signature. This use
-is called a _Smart Signature_. Starting with v2, these programs may
-also execute as _Smart Contracts_, which are often called
-_Applications_. Contract executions are invoked with explicit
-application call transactions.
-
-Programs have read-only access to the transaction they are attached
-to, the other transactions in their atomic transaction group, and a
-few global values. In addition, _Smart Contracts_ have access to
-limited state that is global to the application, per-account local
-state for each account that has opted-in to the application, and
-additional per-application arbitrary state in named _boxes_. For both types of
-program, approval is signaled by finishing with the stack containing a
-single non-zero uint64 value, though `return` can be used to signal an
-early approval which approves based only upon the top stack value
-being a non-zero uint64 value.
-
-## The Stack
-
-The stack starts empty and can contain values of either uint64 or byte-arrays
-(byte-arrays may not exceed
-4096 bytes in length). Most operations act on the stack, popping
-arguments from it and pushing results to it. Some operations have
-_immediate_ arguments that are encoded directly into the instruction,
-rather than coming from the stack.
-
-The maximum stack depth is 1000. If the stack depth is exceeded or if
-a byte-array element exceeds 4096 bytes, the program fails. If an
-opcode is documented to access a position in the stack that does not
-exist, the operation fails. Most often, this is an attempt to access
-an element below the stack -- the simplest example is an operation
-like `concat` which expects two arguments on the stack. If the stack
-has fewer than two elements, the operation fails. Some operations, like
-`frame_dig` and `proto` could fail because of an attempt to access
-above the current stack.
-
-## Stack Types
-
-While every element of the stack is restricted to the types `uint64` and `bytes`,
-the values of these types may be known to be bounded. The more common bounded types are
-named to provide more semantic information in the documentation. They're also used during
-assembly time to do type checking and to provide more informative error messages.
-
-
-@@ named_stack_types.md @@
-
-
-## Scratch Space
-
-In addition to the stack there are 256 positions of scratch
-space. Like stack values, scratch locations may be uint64s or
-byte-arrays. Scratch locations are initialized as uint64 zero. Scratch
-space is accessed by the `load(s)` and `store(s)` opcodes which move
-data from or to scratch space, respectively. Application calls may
-inspect the final scratch space of earlier application calls in the
-same group using `gload(s)(s)`
-
-## Versions
-
-In order to maintain existing semantics for previously written
-programs, AVM code is versioned. When new opcodes are introduced, or
-behavior is changed, a new version is introduced. Programs carrying
-old versions are executed with their original semantics. In the AVM
-bytecode, the version is an incrementing integer, currently 12, and
-denoted vX throughout this document.
-
-## Execution Modes
-
-Starting from v2, the AVM can run programs in two modes:
-1. LogicSig or _stateless_ mode, used to execute Smart Signatures
-2. Application or _stateful_ mode, used to execute Smart Contracts
-
-Differences between modes include:
-1. Max program length (consensus parameters LogicSigMaxSize, MaxAppTotalProgramLen & MaxExtraAppProgramPages)
-2. Max program cost (consensus parameters LogicSigMaxCost, MaxAppProgramCost)
-3. Opcode availability. Refer to [opcodes document](TEAL_opcodes.md) for details.
-4. Some global values, such as LatestTimestamp, are only available in stateful mode.
-5. Only Applications can observe transaction effects, such as Logs or IDs allocated to ASAs or new Applications.
-
-## Execution Environment for Smart Signatures
-
-Smart Signatures execute as part of testing a proposed transaction to
-see if it is valid and authorized to be committed into a block. If an
-authorized program executes and finishes with a single non-zero uint64
-value on the stack then that program has validated the transaction it
-is attached to.
-
-The program has access to data from the transaction it is attached to
-(`txn` op), any transactions in a transaction group it is part of
-(`gtxn` op), and a few global values like consensus parameters
-(`global` op). Some "Args" may be attached to a transaction being
-validated by a program. Args are an array of byte strings. A common
-pattern would be to have the key to unlock some contract as an Arg. Be
-aware that Smart Signature Args are recorded on the blockchain and
-publicly visible when the transaction is submitted to the network,
-even before the transaction has been included in a block. These Args
-are _not_ part of the transaction ID nor of the TxGroup hash. They
-also cannot be read from other programs in the group of transactions.
-
-A program can either authorize some delegated action on a normal
-signature-based or multisignature-based account or be wholly in charge
-of a contract account.
-
-* If the account has signed the program (by providing a valid ed25519
- signature or valid multisignature for the authorizer address on the
- string "Program" concatenated with the program bytecode) then: if the
- program returns true the transaction is authorized as if the account
- had signed it. This allows an account to hand out a signed program
- so that other users can carry out delegated actions which are
- approved by the program. Note that Smart Signature Args are _not_
- signed.
-
-* If the SHA512_256 hash of the program (prefixed by "Program") is
- equal to authorizer address of the transaction sender then this is a
- contract account wholly controlled by the program. No other
- signature is necessary or possible. The only way to execute a
- transaction against the contract account is for the program to
- approve it.
-
-The size of a Smart Signature is defined as the length of its bytecode
-plus the length of all its Args. The sum of the sizes of all Smart
-Signatures in a group must not exceed 1000 bytes times the number of
-transactions in the group (1000 bytes is defined in consensus parameter
-`LogicSigMaxSize`).
-
-Each opcode has an associated cost, usually 1, but a few slow operations
-have higher costs. Prior to v4, the program's cost was estimated as the
-static sum of all the opcode costs in the program (whether they were
-actually executed or not). Beginning with v4, the program's cost is
-tracked dynamically while being evaluated. If the program exceeds its
-budget, it fails.
-
-The total program cost of all Smart Signatures in a group must not
-exceed 20,000 (consensus parameter LogicSigMaxCost) times the number
-of transactions in the group.
-
-
-## Execution Environment for Smart Contracts (Applications)
-
-Smart Contracts are executed in ApplicationCall transactions. Like
-Smart Signatures, contracts indicate success by leaving a single
-non-zero integer on the stack. A failed Smart Contract call to an
-ApprovalProgram is not a valid transaction, thus not written to the
-blockchain. An ApplicationCall with OnComplete set to ClearState
-invokes the ClearStateProgram, rather than the usual
-ApprovalProgram. If the ClearStateProgram fails, application state
-changes are rolled back, but the transaction still succeeds, and the
-Sender's local state for the called application is removed.
-
-Smart Contracts have access to everything a Smart Signature may access
-(see previous section), as well as the ability to examine blockchain
-state such as balances and contract state (their own state and the
-state of other contracts). They also have access to some global
-values that are not visible to Smart Signatures because the values
-change over time. Since smart contracts access changing state, nodes
-must rerun their code to determine if the ApplicationCall transactions
-in their pool would still succeed each time a block is added to the
-blockchain.
-
-Smart contracts have limits on their execution cost (700, consensus
-parameter MaxAppProgramCost). Before v4, this was a static limit on
-the cost of all the instructions in the program. Starting in v4, the cost
-is tracked dynamically during execution and must not exceed
-MaxAppProgramCost. Beginning with v5, programs costs are pooled and
-tracked dynamically across app executions in a group. If `n`
-application invocations appear in a group, then the total execution
-cost of all such calls must not exceed `n`*MaxAppProgramCost. In v6, inner
-application calls become possible, and each such call increases the
-pooled budget by MaxAppProgramCost at the time the inner group is submitted
-with `itxn_submit`.
-
-Executions of the ClearStateProgram are more stringent, in order to
-ensure that applications may be closed out, but that applications also
-are assured a chance to clean up their internal state. At the
-beginning of the execution of a ClearStateProgram, the pooled budget
-available must be MaxAppProgramCost or higher. If it is not, the
-containing transaction group fails without clearing the app's
-state. During the execution of the ClearStateProgram, no more than
-MaxAppProgramCost may be drawn. If further execution is attempted, the
-ClearStateProgram fails, and the app's state _is cleared_.
-
-
-### Resource availability
-
-Smart contracts have limits on the amount of blockchain state they may
-examine. These limits are enforced by failing any opcode that
-attempts to access a resource unless the resource is
-_available_. These resources are:
-
- * Accounts, which must be available to access their balance, or other
- account parameters such as voting details.
- * Assets, which must be available to access global asset parameters, such
- the as the asset's URL, Name, or privileged addresses.
- * Holdings, which must be available to access a particular address's
- balance or frozen status for a particular asset.
- * Applications, which must be available to read an application's
- programs, parameters, or global state.
- * Locals, which must be available to read a particular address's local
- state for a particular application.
- * Boxes, which must be available to read or write a box, designated
- by an application and name for the box.
-
-Resources are _available_ based on the contents of the executing
-transaction and, in later versions, the contents of other transactions
-in the same group.
-
- * A resource in the "foreign array" fields of the ApplicationCall
- transaction (`txn.Accounts`, `txn.ForeignAssets`, and
- `txn.ForeignApplications`) is _available_.
-
- * The `txn.Sender`, `global CurrentApplicationID`, and `global
- CurrentApplicationAddress` are _available_.
-
- * In pre-v4 applications, all holdings are _available_ to the
- `asset_holding_get` opcode, and all locals are _available_ to the
- `app_local_get_ex` opcode if the *account* of the resource is
- _available_.
-
- * In v6 and later applications, any asset or application that was
- created earlier in the same transaction group (whether by a
- top-level or inner transaction) is _available_. In addition, any
- account that is the associated account of a contract that was
- created earlier in the group is _available_.
-
- * In v7 and later applications, the account associated with any
- contract present in the `txn.ForeignApplications` field is
- _available_.
-
- * In v4 and above applications, Holdings and Locals are _available_
- if, both components of the resource are available according to the
- above rules.
-
- * In v9 and later applications, there is group-level resource
- sharing. Any resource that is available in _some_ top-level
- transaction in a transaction group is available in _all_ v9 or
- later application calls in the group, whether those application
- calls are top-level or inner.
-
- * v9 and later applications may use the `txn.Access` list instead of
- the foreign arrays. When using `txn.Access` Holdings and Locals are
- no longer made available automatically because their components
- are. Application accounts are also not made available because of
- the availability of their corresponding app. Each resource must be
- listed explicitly. However, `txn.Access` allows for the listing of
- more resources than the foreign arrays. Listed resources become
- available to other (post-v8) applications through group sharing.
-
- * When considering whether an asset holding or application local
- state is available for group-level resource sharing, the holding or
- local state must be available in a top-level transaction based on
- pre-v9 rules. For example, if account A is made available in one
- transaction, and asset X is made available in another, group
- resource sharing does _not_ make A's X holding available.
-
- * Top-level transactions that are not application calls also make
- resources available to group-level resource sharing. The following
- resources are made available by other transaction types.
-
- 1. `pay` - `txn.Sender`, `txn.Receiver`, and
- `txn.CloseRemainderTo` (if set).
-
- 1. `keyreg` - `txn.Sender`
-
- 1. `acfg` - `txn.Sender`, `txn.ConfigAsset`, and the
- `txn.ConfigAsset` holding of `txn.Sender`.
-
- 1. `axfer` - `txn.Sender`, `txn.AssetReceiver`, `txn.AssetSender`
- (if set), `txnAssetCloseTo` (if set), `txn.XferAsset`, and the
- `txn.XferAsset` holding of each of those accounts.
-
- 1. `afrz` - `txn.Sender`, `txn.FreezeAccount`, `txn.FreezeAsset`,
- and the `txn.FreezeAsset` holding of `txn.FreezeAccount`. The
- `txn.FreezeAsset` holding of `txn.Sender` is _not_ made
- available.
-
-
- * A Box is _available_ to an Approval Program if _any_ transaction in
- the same group contains a box reference (in `txn.Boxes` or
- `txn.Access`) that denotes the box. A box reference contains an
- index `i`, and name `n`. The index refers to the `ith` application
- in the transaction's `ForeignApplications` or `Access` array (only
- one of which can be used), with the usual convention that 0
- indicates the application ID of the app called by that
- transaction. No box is ever _available_ to a ClearStateProgram.
-
-Regardless of _availability_, any attempt to access an Asset or
-Application with an ID less than 256 from within a Contract will fail
-immediately. This avoids any ambiguity in opcodes that interpret their
-integer arguments as resource IDs _or_ indexes into the
-`txn.ForeignAssets` or `txn.ForeignApplications` arrays.
-
-It is recommended that contract authors avoid supplying array indexes
-to these opcodes, and always use explicit resource IDs. By using
-explicit IDs, contracts will better take advantage of group resource
-sharing. The array indexing interpretation may be deprecated in a
-future version.
-
-## Constants
-
-Constants can be pushed onto the stack in two different ways:
-
-1. Constants can be pushed directly with `pushint` or
- `pushbytes`. This method is more efficient for constants that are
- only used once.
-
-2. Constants can be loaded into storage separate from the stack and
- scratch space, using two opcodes `intcblock` and
- `bytecblock`. Then, constants from this storage can be
- pushed onto the stack by referring to the type and index using
- `intc`, `intc_[0123]`, `bytec`, and `bytec_[0123]`. This method is
- more efficient for constants that are used multiple times.
-
-The assembler will hide most of this, allowing simple use of `int 1234`
-and `byte 0xcafed00d`. Constants introduced via `int` and `byte` will
-be assembled into appropriate uses of `pushint|pushbytes` and
-`{int|byte}c, {int|byte}c_[0123]` to minimize program size.
-
-
-The opcodes `intcblock` and `bytecblock` use [proto-buf style variable length unsigned int](https://developers.google.com/protocol-buffers/docs/encoding#varint),
-reproduced [here](#varuint). The `intcblock` opcode is followed by a
-varuint specifying the number of integer constants and then that
-number of varuints. The `bytecblock` opcode is followed by a varuint
-specifying the number of byte constants, and then that number of pairs
-of (varuint, bytes) length prefixed byte strings.
-
-### Named Integer Constants
-
-@@ named_integer_constants.md @@
-
-## Operations
-
-Most operations work with only one type of argument, uint64 or bytes, and fail if the wrong type value is on the stack.
-
-Many instructions accept values to designate Accounts, Assets, or Applications. Beginning with v4, these values may be given as an _offset_ in the corresponding Txn fields (Txn.Accounts, Txn.ForeignAssets, Txn.ForeignApps) _or_ as the value itself (a byte-array address for Accounts, or a uint64 ID). The values, however, must still be present in the Txn fields. Before v4, most opcodes required the use of an offset, except for reading account local values of assets or applications, which accepted the IDs directly and did not require the ID to be present in the corresponding _Foreign_ array. (Note that beginning with v4, those IDs _are_ required to be present in their corresponding _Foreign_ array.) See individual opcodes for details. In the case of account offsets or application offsets, 0 is specially defined to Txn.Sender or the ID of the current application, respectively.
-
-This summary is supplemented by more detail in the [opcodes document](TEAL_opcodes.md).
-
-Some operations immediately fail the program.
-A transaction checked by a program that fails is not valid.
-An account governed by a buggy program might not have a way to get assets back out of it. Code carefully.
-
-In the documentation for each opcode, the stack arguments that are
-popped are referred to alphabetically, beginning with the deepest
-argument as `A`. These arguments are shown in the opcode description,
-and if the opcode must be of a specific type, it is noted there. All
-opcodes fail if a specified type is incorrect.
-
-If an opcode pushes more than one result, the values are named for
-ease of exposition and clarity concerning their stack positions. When
-an opcode manipulates the stack in such a way that a value changes
-position but is otherwise unchanged, the name of the output on the
-return stack matches the name of the input value.
-
-### Arithmetic and Logic Operations
-
-@@ Arithmetic.md @@
-
-### Byte Array Manipulation
-
-@@ Byte_Array_Manipulation.md @@
-
-The following opcodes take byte-array values that are interpreted as
-big-endian unsigned integers. For mathematical operators, the
-returned values are the shortest byte-array that can represent the
-returned value. For example, the zero value is the empty
-byte-array. For comparison operators, the returned value is a uint64.
-
-Input lengths are limited to a maximum length of 64 bytes,
-representing a 512 bit unsigned integer. Output lengths are not
-explicitly restricted, though only `b*` and `b+` can produce a larger
-output than their inputs, so there is an implicit length limit of 128
-bytes on outputs.
-
-@@ Byte_Array_Arithmetic.md @@
-
-These opcodes operate on the bits of byte-array values. The shorter
-input array is interpreted as though left padded with zeros until it is the
-same length as the other input. The returned values are the same
-length as the longer input. Therefore, unlike array arithmetic,
-these results may contain leading zero bytes.
-
-@@ Byte_Array_Logic.md @@
-
-### Cryptographic Operations
-
-@@ Cryptography.md @@
-
-### Loading Values
-
-Opcodes for getting data onto the stack.
-
-Some of these have immediate data in the byte or bytes after the opcode.
-
-@@ Loading_Values.md @@
-
-#### Transaction Fields
-##### Scalar Fields
-@@ txn_fields.md @@
-##### Array Fields
-@@ txna_fields.md @@
-
-Additional details in the [opcodes document](TEAL_opcodes.md#txn) on the `txn` op.
-
-**Global Fields**
-
-Global fields are fields that are common to all the transactions in the group. In particular it includes consensus parameters.
-
-@@ global_fields.md @@
-
-**Asset Fields**
-
-Asset fields include `AssetHolding` and `AssetParam` fields that are used in the `asset_holding_get` and `asset_params_get` opcodes.
-
-@@ asset_holding_fields.md @@
-
-@@ asset_params_fields.md @@
-
-**App Fields**
-
-App fields used in the `app_params_get` opcode.
-
-@@ app_params_fields.md @@
-
-**Account Fields**
-
-Account fields used in the `acct_params_get` opcode.
-
-@@ acct_params_fields.md @@
-
-### Flow Control
-
-@@ Flow_Control.md @@
-
-### State Access
-
-@@ State_Access.md @@
-
-### Box Access
-
-Box opcodes that create, delete, or resize boxes affect the minimum
-balance requirement of the calling application's account. The change
-is immediate, and can be observed after exection by using
-`min_balance`. If the account does not possess the new minimum
-balance, the opcode fails.
-
-All box related opcodes fail immediately if used in a
-ClearStateProgram. This behavior is meant to discourage Smart Contract
-authors from depending upon the availability of boxes in a ClearState
-transaction, as accounts using ClearState are under no requirement to
-furnish appropriate Box References. Authors would do well to keep the
-same issue in mind with respect to the availability of Accounts,
-Assets, and Apps though State Access opcodes _are_ allowed in
-ClearState programs because the current application and sender account
-are sure to be _available_.
-
-@@ Box_Access.md @@
-
-### Inner Transactions
-
-The following opcodes allow for "inner transactions". Inner
-transactions allow stateful applications to have many of the effects
-of a true top-level transaction, programmatically. However, they are
-different in significant ways. The most important differences are
-that they are not signed, duplicates are not rejected, and they do not
-appear in the block in the usual away. Instead, their effects are
-noted in metadata associated with their top-level application
-call transaction. An inner transaction's `Sender` must be the
-SHA512_256 hash of the application ID (prefixed by "appID"), or an
-account that has been rekeyed to that hash.
-
-In v5, inner transactions may perform `pay`, `axfer`, `acfg`, and
-`afrz` effects. After executing an inner transaction with
-`itxn_submit`, the effects of the transaction are visible beginning
-with the next instruction with, for example, `balance` and
-`min_balance` checks. In v6, inner transactions may also perform
-`keyreg` and `appl` effects. Inner `appl` calls fail if they attempt
-to invoke a program with version less than v4, or if they attempt to
-opt-in to an app with a ClearState Program less than v4.
-
-In v5, only a subset of the transaction's header fields may be set: `Type`/`TypeEnum`,
-`Sender`, and `Fee`. In v6, header fields `Note` and `RekeyTo` may
-also be set. For the specific (non-header) fields of each transaction
-type, any field may be set. This allows, for example, clawback
-transactions, asset opt-ins, and asset creates in addition to the more
-common uses of `axfer` and `acfg`. All fields default to the zero
-value, except those described under `itxn_begin`.
-
-Fields may be set multiple times, but may not be read. The most recent
-setting is used when `itxn_submit` executes. For this purpose `Type`
-and `TypeEnum` are considered to be the same field. When using
-`itxn_field` to set an array field (`ApplicationArgs` `Accounts`,
-`Assets`, or `Applications`) each use adds an element to the end of
-the array, rather than setting the entire array at once.
-
-`itxn_field` fails immediately for unsupported fields, unsupported
-transaction types, or improperly typed values for a particular
-field. `itxn_field` makes acceptance decisions entirely from the field
-and value provided, never considering previously set fields. Illegal
-interactions between fields, such as setting fields that belong to two
-different transaction types, are rejected by `itxn_submit`.
-
-@@ Inner_Transactions.md @@
-
-
-# Assembler Syntax
-
-The assembler parses line by line. Ops that only take stack arguments
-appear on a line by themselves. Immediate arguments follow the opcode
-on the same line, separated by whitespace.
-
-The first line may contain a special version pragma `#pragma version X`, which directs the assembler to generate bytecode targeting a certain version. For instance, `#pragma version 2` produces bytecode targeting v2. By default, the assembler targets v1.
-
-Subsequent lines may contain other pragma declarations (i.e., `#pragma `), pertaining to checks that the assembler should perform before agreeing to emit the program bytes, specific optimizations, etc. Those declarations are optional and cannot alter the semantics as described in this document.
-
-"`//`" prefixes a line comment.
-
-## Constants and Pseudo-Ops
-
-A few pseudo-ops simplify writing code. `int` and `byte` and `addr` and `method` followed by a constant record the constant to a `intcblock` or `bytecblock` at the beginning of code and insert an `intc` or `bytec` reference where the instruction appears to load that value. `addr` parses an Algorand account address base32 and converts it to a regular bytes constant. `method` is passed a method signature and takes the first four bytes of the hash to convert it to the standard method selector defined in [ARC4](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0004.md)
-
-`byte` constants are:
-```
-byte base64 AAAA...
-byte b64 AAAA...
-byte base64(AAAA...)
-byte b64(AAAA...)
-byte base32 AAAA...
-byte b32 AAAA...
-byte base32(AAAA...)
-byte b32(AAAA...)
-byte 0x0123456789abcdef...
-byte "\x01\x02"
-byte "string literal"
-```
-
-`int` constants may be `0x` prefixed for hex, `0o` or `0` prefixed for
-octal, `0b` for binary, or decimal numbers.
-
-`intcblock` may be explicitly assembled. It will conflict with the assembler gathering `int` pseudo-ops into a `intcblock` program prefix, but may be used if code only has explicit `intc` references. `intcblock` should be followed by space separated int constants all on one line.
-
-`bytecblock` may be explicitly assembled. It will conflict with the assembler if there are any `byte` pseudo-ops but may be used if only explicit `bytec` references are used. `bytecblock` should be followed with byte constants all on one line, either 'encoding value' pairs (`b64 AAA...`) or 0x prefix or function-style values (`base64(...)`) or string literal values.
-
-## Labels and Branches
-
-A label is defined by any string not some other opcode or keyword and ending in ':'. A label can be an argument (without the trailing ':') to a branching instruction.
-
-Example:
-```
-int 1
-bnz safe
-err
-safe:
-pop
-```
-
-# Encoding and Versioning
-
-A compiled program starts with a varuint declaring the version of the compiled code. Any addition, removal, or change of opcode behavior increments the version. For the most part opcode behavior should not change, addition will be infrequent (not likely more often than every three months and less often as the language matures), and removal should be very rare.
-
-For version 1, subsequent bytes after the varuint are program opcode bytes. Future versions could put other metadata following the version identifier.
-
-It is important to prevent newly-introduced transaction types and
-fields from breaking assumptions made by programs written before they
-existed. If one of the transactions in a group will execute a program
-whose version predates a transaction type or field that can violate
-expectations, that transaction type or field must not be used anywhere
-in the transaction group.
-
-Concretely, the above requirement is translated as follows: A v1
-program included in a transaction group that includes a
-ApplicationCall transaction or a non-zero RekeyTo field will fail
-regardless of the program itself.
-
-This requirement is enforced as follows:
-
-* For every transaction, compute the earliest version that supports
- all the fields and values in this transaction.
-
-* Compute the largest version number across all the transactions in a group (of size 1 or more), call it `maxVerNo`. If any transaction in this group has a program with a version smaller than `maxVerNo`, then that program will fail.
-
-In addition, applications must be v4 or greater to be called in an inner transaction.
-
-## Varuint
-
-A '[proto-buf style variable length unsigned int](https://developers.google.com/protocol-buffers/docs/encoding#varint)' is encoded with 7 data bits per byte and the high bit is 1 if there is a following byte and 0 for the last byte. The lowest order 7 bits are in the first byte, followed by successively higher groups of 7 bits.
-
-# What AVM Programs Cannot Do
-
-Design and implementation limitations to be aware of with various versions.
-
-* Stateless programs cannot lookup balances of Algos or other
- assets. (Standard transaction accounting will apply after the Smart
- Signature has authorized a transaction. A transaction could still be
- invalid by other accounting rules just as a standard signed
- transaction could be invalid. e.g. I can't give away money I don't
- have.)
-* Programs cannot access information in previous blocks. Programs
- cannot access information in other transactions in the current
- block, unless they are a part of the same atomic transaction group.
-* Smart Signatures cannot know exactly what round the current transaction
- will commit in (but it is somewhere in FirstValid through
- LastValid).
-* Programs cannot know exactly what time its transaction is committed.
-* Programs cannot loop prior to v4. In v3 and prior, the branch
- instructions `bnz` "branch if not zero", `bz` "branch if zero" and
- `b` "branch" can only branch forward.
-* Until v4, the AVM had no notion of subroutines (and therefore no
- recursion). As of v4, use `callsub` and `retsub`.
-* Programs cannot make indirect jumps. `b`, `bz`, `bnz`, and `callsub`
- jump to an immediately specified address, and `retsub` jumps to the
- address currently on the top of the call stack, which is manipulated
- only by previous calls to `callsub` and `retsub`.
diff --git a/data/transactions/logic/TEAL_opcodes_v1.md b/data/transactions/logic/TEAL_opcodes_v1.md
index 35bcca9255..03a239b5e7 100644
--- a/data/transactions/logic/TEAL_opcodes_v1.md
+++ b/data/transactions/logic/TEAL_opcodes_v1.md
@@ -1,7 +1,11 @@
-# v1 Opcodes
-Ops have a 'cost' of 1 unless otherwise specified.
+# Version 1 Opcodes
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
## err
@@ -298,17 +302,17 @@ Overflow is an error condition which halts execution and fails the transaction.
## txn
-- Syntax: `txn F` where F: [txn](#field-group-txn)
+- Syntax: `txn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x31 {uint8}
- Stack: ... → ..., any
- field F of current transaction
-### txn
+### txn Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | Sender | address | 32 byte address |
| 1 | Fee | uint64 | microalgos |
| 2 | FirstValid | uint64 | round number |
@@ -333,30 +337,26 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 22 | GroupIndex | uint64 | Position of this transaction within an atomic transaction group. A stand-alone transaction is implicitly element 0 in a group of 1 |
| 23 | TxID | [32]byte | The computed ID for this transaction. 32 bytes. |
-
## global
-- Syntax: `global F` where F: [global](#field-group-global)
+- Syntax: `global F` where F: [global Fields](#global-fields)
- Bytecode: 0x32 {uint8}
- Stack: ... → ..., any
- global field F
-### global
+### global Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | MinTxnFee | uint64 | microalgos |
| 1 | MinBalance | uint64 | microalgos |
| 2 | MaxTxnLife | uint64 | rounds |
| 3 | ZeroAddress | address | 32 byte address of all zero bytes |
| 4 | GroupSize | uint64 | Number of transactions in this atomic transaction group. At least 1 |
-
## gtxn
-- Syntax: `gtxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gtxn T F` where T: transaction group index, F: [txn Fields](#txn-fields)
- Bytecode: 0x33 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the current group
diff --git a/data/transactions/logic/TEAL_opcodes_v10.md b/data/transactions/logic/TEAL_opcodes_v10.md
index bfd2c1e36b..f43c7bfe27 100644
--- a/data/transactions/logic/TEAL_opcodes_v10.md
+++ b/data/transactions/logic/TEAL_opcodes_v10.md
@@ -1,7 +1,11 @@
-# v10 Opcodes
-Ops have a 'cost' of 1 unless otherwise specified.
+# Version 10 Opcodes
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
## err
@@ -41,28 +45,25 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte
## ecdsa_verify
-- Syntax: `ecdsa_verify V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_verify V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x05 {uint8}
- Stack: ..., A: [32]byte, B: [32]byte, C: [32]byte, D: [32]byte, E: [32]byte → ..., bool
- for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1}
- **Cost**: Secp256k1=1700; Secp256r1=2500
- Availability: v5
-### ECDSA
+### ECDSA Curves
-Curves
-
-| Index | Name | In | Notes |
-| - | ------ | - | --------- |
+| INDEX | NAME | IN | NOTES |
+| :-: | :------ |:-:| :--------- |
| 0 | Secp256k1 | | secp256k1 curve, used in Bitcoin |
| 1 | Secp256r1 | v7 | secp256r1 curve, NIST standard |
-
The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.
## ecdsa_pk_decompress
-- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x06 {uint8}
- Stack: ..., A: [33]byte → ..., X: [32]byte, Y: [32]byte
- decompress pubkey A into components X, Y
@@ -73,7 +74,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top
## ecdsa_pk_recover
-- Syntax: `ecdsa_pk_recover V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_recover V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x07 {uint8}
- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: [32]byte, Y: [32]byte
- for (data A, recovery id B, signature C, D) recover a public key
@@ -357,17 +358,17 @@ The notation J,K indicates that two uint64 values J and K are interpreted as a u
## txn
-- Syntax: `txn F` where F: [txn](#field-group-txn)
+- Syntax: `txn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x31 {uint8}
- Stack: ... → ..., any
- field F of current transaction
-### txn
+### txn Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | Sender | address | | 32 byte address |
| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
@@ -430,20 +431,17 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 65 | NumApprovalProgramPages | uint64 | v7 | Number of Approval Program pages |
| 67 | NumClearStateProgramPages | uint64 | v7 | Number of ClearState Program pages |
-
## global
-- Syntax: `global F` where F: [global](#field-group-global)
+- Syntax: `global F` where F: [global Fields](#global-fields)
- Bytecode: 0x32 {uint8}
- Stack: ... → ..., any
- global field F
-### global
-
-Fields
+### global Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | MinTxnFee | uint64 | | microalgos |
| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
@@ -463,10 +461,9 @@ Fields
| 16 | AssetOptInMinBalance | uint64 | v10 | The additional minimum balance required to opt-in to an asset. |
| 17 | GenesisHash | [32]byte | v10 | The Genesis Hash for the network. |
-
## gtxn
-- Syntax: `gtxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gtxn T F` where T: transaction group index, F: [txn Fields](#txn-fields)
- Bytecode: 0x33 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the current group
@@ -489,18 +486,19 @@ for notes on transaction fields available, see `txn`. If this transaction is _i_
## txna
-- Syntax: `txna F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `txna F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x36 {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F of the current transaction `txna` can be called using `txn` with 2 immediates.
+- Ith value of the array field F of the current transaction
+- `txna` can be called by using `txn` with 2 immediates.
- Availability: v2
-### txna
+### txna Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 26 | ApplicationArgs | []byte | v2 | Arguments passed to the application in the ApplicationCall transaction |
| 28 | Accounts | address | v2 | Accounts listed in the ApplicationCall transaction |
| 48 | Assets | uint64 | v3 | Foreign Assets listed in the ApplicationCall transaction |
@@ -509,18 +507,18 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 64 | ApprovalProgramPages | []byte | v7 | Approval Program as an array of pages |
| 66 | ClearStateProgramPages | []byte | v7 | ClearState Program as an array of pages |
-
## gtxna
-- Syntax: `gtxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x37 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F from the Tth transaction in the current group `gtxna` can be called using `gtxn` with 3 immediates.
+- Ith value of the array field F from the Tth transaction in the current group
+- `gtxna` can be called by using `gtxn` with 3 immediates.
- Availability: v2
## gtxns
-- Syntax: `gtxns F` where F: [txn](#field-group-txn)
+- Syntax: `gtxns F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x38 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of the Ath transaction in the current group
@@ -530,10 +528,11 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
## gtxnsa
-- Syntax: `gtxnsa F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxnsa F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x39 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
-- Ith value of the array field F from the Ath transaction in the current group `gtxnsa` can be called using `gtxns` with 2 immediates.
+- Ith value of the array field F from the Ath transaction in the current group
+- `gtxnsa` can be called by using `gtxns` with 2 immediates.
- Availability: v3
## gload
@@ -787,7 +786,8 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Bytecode: 0x58
- Stack: ..., A: []byte, B: uint64, C: uint64 → ..., []byte
-- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails `extract3` can be called using `extract` with no immediates.
+- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails
+- `extract3` can be called by using `extract` with no immediates.
- Availability: v5
## extract_uint16
@@ -816,60 +816,56 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Syntax: `replace2 S` where S: start position
- Bytecode: 0x5c {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
-- Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A) `replace2` can be called using `replace` with 1 immediate.
+- Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)
+- `replace2` can be called by using `replace` with 1 immediate.
- Availability: v7
## replace3
- Bytecode: 0x5d
- Stack: ..., A: []byte, B: uint64, C: []byte → ..., []byte
-- Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A) `replace3` can be called using `replace` with no immediates.
+- Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)
+- `replace3` can be called by using `replace` with no immediates.
- Availability: v7
## base64_decode
-- Syntax: `base64_decode E` where E: [base64](#field-group-base64)
+- Syntax: `base64_decode E` where E: [base64 Encodings](#base64-encodings)
- Bytecode: 0x5e {uint8}
- Stack: ..., A: []byte → ..., []byte
- decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E
- **Cost**: 1 + 1 per 16 bytes of A
- Availability: v7
-### base64
-
-Encodings
+### base64 Encodings
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | URLEncoding | |
| 1 | StdEncoding | |
-
-*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.
+_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.
Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\n` and `\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\r`, or `\n`.
## json_ref
-- Syntax: `json_ref R` where R: [json_ref](#field-group-json_ref)
+- Syntax: `json_ref R` where R: [json_ref Types](#json_ref-types)
- Bytecode: 0x5f {uint8}
- Stack: ..., A: []byte, B: []byte → ..., any
- key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A
- **Cost**: 25 + 2 per 7 bytes of A
- Availability: v7
-### json_ref
+### json_ref Types
-Types
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | JSONString | []byte | |
| 1 | JSONUint64 | uint64 | |
| 2 | JSONObject | []byte | |
-
-*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.
+_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.
Almost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.
@@ -977,40 +973,35 @@ Deleting a key which is already absent has no effect on the application global s
## asset_holding_get
-- Syntax: `asset_holding_get F` where F: [asset_holding](#field-group-asset_holding)
+- Syntax: `asset_holding_get F` where F: [asset_holding Fields](#asset_holding-fields)
- Bytecode: 0x70 {uint8}
- Stack: ..., A, B: uint64 → ..., X: any, Y: bool
- X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0
- Availability: v2
- Mode: Application
-### asset_holding
-
-Fields
+### asset_holding Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetBalance | uint64 | Amount of the asset unit held by this account |
| 1 | AssetFrozen | bool | Is the asset frozen or not |
-
params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## asset_params_get
-- Syntax: `asset_params_get F` where F: [asset_params](#field-group-asset_params)
+- Syntax: `asset_params_get F` where F: [asset_params Fields](#asset_params-fields)
- Bytecode: 0x71 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from asset A. Y is 1 if A exists, else 0
- Availability: v2
- Mode: Application
-### asset_params
-
-Fields
+### asset_params Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AssetTotal | uint64 | | Total number of units of this asset |
| 1 | AssetDecimals | uint64 | | See AssetParams.Decimals |
| 2 | AssetDefaultFrozen | bool | | Frozen by default or not |
@@ -1024,24 +1015,21 @@ Fields
| 10 | AssetClawback | address | | Clawback address |
| 11 | AssetCreator | address | v5 | Creator address |
-
params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## app_params_get
-- Syntax: `app_params_get F` where F: [app_params](#field-group-app_params)
+- Syntax: `app_params_get F` where F: [app_params Fields](#app_params-fields)
- Bytecode: 0x72 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from app A. Y is 1 if A exists, else 0
- Availability: v5
- Mode: Application
-### app_params
-
-Fields
+### app_params Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AppApprovalProgram | []byte | Bytecode of Approval Program |
| 1 | AppClearStateProgram | []byte | Bytecode of Clear State Program |
| 2 | AppGlobalNumUint | uint64 | Number of uint64 values allowed in Global State |
@@ -1052,24 +1040,21 @@ Fields
| 7 | AppCreator | address | Creator address |
| 8 | AppAddress | address | Address for which this application has authority |
-
params: Txn.ForeignApps offset or an _available_ app id. Return: did_exist flag (1 if the application existed and 0 otherwise), value.
## acct_params_get
-- Syntax: `acct_params_get F` where F: [acct_params](#field-group-acct_params)
+- Syntax: `acct_params_get F` where F: [acct_params Fields](#acct_params-fields)
- Bytecode: 0x73 {uint8}
- Stack: ..., A → ..., X: any, Y: bool
- X is field F from account A. Y is 1 if A owns positive algos, else 0
- Availability: v6
- Mode: Application
-### acct_params
-
-Fields
+### acct_params Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AcctBalance | uint64 | | Account balance in microalgos |
| 1 | AcctMinBalance | uint64 | | Minimum required balance for account, in microalgos |
| 2 | AcctAuthAddr | address | | Address the account is rekeyed to. |
@@ -1083,7 +1068,6 @@ Fields
| 10 | AcctTotalBoxes | uint64 | v8 | The number of existing boxes created by this account's app. |
| 11 | AcctTotalBoxBytes | uint64 | v8 | The total number of bytes used by this account's app's box keys and values. |
-
## min_balance
- Bytecode: 0x78
@@ -1419,7 +1403,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn_field
-- Syntax: `itxn_field F` where F: [txn](#field-group-txn)
+- Syntax: `itxn_field F` where F: [txn](#txn)
- Bytecode: 0xb2 {uint8}
- Stack: ..., A → ...
- set field F of the current inner transaction to A
@@ -1440,7 +1424,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn
-- Syntax: `itxn F` where F: [txn](#field-group-txn)
+- Syntax: `itxn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0xb4 {uint8}
- Stack: ... → ..., any
- field F of the last inner transaction
@@ -1449,7 +1433,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxna
-- Syntax: `itxna F I` where F: [txna](#field-group-txna), I: a transaction field array index
+- Syntax: `itxna F I` where F: [txna Fields](#txna-fields), I: a transaction field array index
- Bytecode: 0xb5 {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F of the last inner transaction
@@ -1468,7 +1452,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxn
-- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#txn)
- Bytecode: 0xb7 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the last inner group submitted
@@ -1477,7 +1461,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxna
-- Syntax: `gitxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gitxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0xb8 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F from the Tth transaction in the last inner group submitted
@@ -1548,7 +1532,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## txnas
-- Syntax: `txnas F` where F: [txna](#field-group-txna)
+- Syntax: `txnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc0 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the current transaction
@@ -1556,7 +1540,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gtxnas
-- Syntax: `gtxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gtxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc1 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the current group
@@ -1564,7 +1548,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gtxnsas
-- Syntax: `gtxnsas F` where F: [txna](#field-group-txna)
+- Syntax: `gtxnsas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc2 {uint8}
- Stack: ..., A: uint64, B: uint64 → ..., any
- Bth value of the array field F from the Ath transaction in the current group
@@ -1588,7 +1572,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## itxnas
-- Syntax: `itxnas F` where F: [txna](#field-group-txna)
+- Syntax: `itxnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc5 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the last inner transaction
@@ -1597,7 +1581,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gitxnas
-- Syntax: `gitxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gitxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc6 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the last inner group submitted
@@ -1606,42 +1590,36 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## vrf_verify
-- Syntax: `vrf_verify S` where S: [vrf_verify](#field-group-vrf_verify)
+- Syntax: `vrf_verify S` where S: [vrf_verify Standards](#vrf_verify-standards)
- Bytecode: 0xd0 {uint8}
- Stack: ..., A: []byte, B: [80]byte, C: [32]byte → ..., X: [64]byte, Y: bool
- Verify the proof B of message A against pubkey C. Returns vrf output and verification flag.
- **Cost**: 5700
- Availability: v7
-### vrf_verify
+### vrf_verify Standards
-Standards
-
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | VrfAlgorand | |
-
`VrfAlgorand` is the VRF used in Algorand. It is ECVRF-ED25519-SHA512-Elligator2, specified in the IETF internet draft [draft-irtf-cfrg-vrf-03](https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/03/).
## block
-- Syntax: `block F` where F: [block](#field-group-block)
+- Syntax: `block F` where F: [block Fields](#block-fields)
- Bytecode: 0xd1 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of block A. Fail unless A falls between txn.LastValid-1002 and txn.FirstValid (exclusive)
- Availability: v7
-### block
-
-Fields
+### block Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | BlkSeed | [32]byte | |
| 1 | BlkTimestamp | uint64 | |
-
## box_splice
- Bytecode: 0xd2
@@ -1662,25 +1640,22 @@ Boxes are of constant length. If C < len(D), then len(D)-C bytes will be removed
## ec_add
-- Syntax: `ec_add G` where G: [EC](#field-group-ec)
+- Syntax: `ec_add G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe0 {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
- for curve points A and B, return the curve point A + B
- **Cost**: BN254g1=125; BN254g2=170; BLS12_381g1=205; BLS12_381g2=290
- Availability: v10
-### EC
-
-Groups
+### EC Groups
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | BN254g1 | G1 of the BN254 curve. Points encoded as 32 byte X following by 32 byte Y |
| 1 | BN254g2 | G2 of the BN254 curve. Points encoded as 64 byte X following by 64 byte Y |
| 2 | BLS12_381g1 | G1 of the BLS 12-381 curve. Points encoded as 48 byte X following by 48 byte Y |
| 3 | BLS12_381g2 | G2 of the BLS 12-381 curve. Points encoded as 96 byte X following by 96 byte Y |
-
A and B are curve points in affine representation: field element X concatenated with field element Y. Field element `Z` is encoded as follows.
For the base field elements (Fp), `Z` is encoded as a big-endian number and must be lower than the field modulus.
For the quadratic field extension (Fp2), `Z` is encoded as the concatenation of the individual encoding of the coefficients. For an Fp2 element of the form `Z = Z0 + Z1 i`, where `i` is a formal quadratic non-residue, the encoding of Z is the concatenation of the encoding of `Z0` and `Z1` in this order. (`Z0` and `Z1` must be less than the field modulus).
@@ -1694,7 +1669,7 @@ Does _not_ check if A and B are in the main prime-order subgroup.
## ec_scalar_mul
-- Syntax: `ec_scalar_mul G` where G: [EC](#field-group-ec)
+- Syntax: `ec_scalar_mul G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe1 {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
- for curve point A and scalar B, return the curve point BA, the point A multiplied by the scalar B.
@@ -1705,7 +1680,7 @@ A is a curve point encoded and checked as described in `ec_add`. Scalar B is int
## ec_pairing_check
-- Syntax: `ec_pairing_check G` where G: [EC](#field-group-ec)
+- Syntax: `ec_pairing_check G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe2 {uint8}
- Stack: ..., A: []byte, B: []byte → ..., bool
- 1 if the product of the pairing of each point in A with its respective point in B is equal to the identity element of the target group Gt, else 0
@@ -1716,7 +1691,7 @@ A and B are concatenated points, encoded and checked as described in `ec_add`. A
## ec_multi_scalar_mul
-- Syntax: `ec_multi_scalar_mul G` where G: [EC](#field-group-ec)
+- Syntax: `ec_multi_scalar_mul G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe3 {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
- for curve points A and scalars B, return curve point B0A0 + B1A1 + B2A2 + ... + BnAn
@@ -1728,7 +1703,7 @@ The name `ec_multi_scalar_mul` was chosen to reflect common usage, but a more co
## ec_subgroup_check
-- Syntax: `ec_subgroup_check G` where G: [EC](#field-group-ec)
+- Syntax: `ec_subgroup_check G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe4 {uint8}
- Stack: ..., A: []byte → ..., bool
- 1 if A is in the main prime-order subgroup of G (including the point at infinity) else 0. Program fails if A is not in G at all.
@@ -1737,7 +1712,7 @@ The name `ec_multi_scalar_mul` was chosen to reflect common usage, but a more co
## ec_map_to
-- Syntax: `ec_map_to G` where G: [EC](#field-group-ec)
+- Syntax: `ec_map_to G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe5 {uint8}
- Stack: ..., A: []byte → ..., []byte
- maps field element A to group G
diff --git a/data/transactions/logic/TEAL_opcodes_v11.md b/data/transactions/logic/TEAL_opcodes_v11.md
index 3e38852ed5..c716cadfd8 100644
--- a/data/transactions/logic/TEAL_opcodes_v11.md
+++ b/data/transactions/logic/TEAL_opcodes_v11.md
@@ -1,7 +1,11 @@
-# v11 Opcodes
-Ops have a 'cost' of 1 unless otherwise specified.
+# Version 11 Opcodes
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
## err
@@ -41,28 +45,25 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte
## ecdsa_verify
-- Syntax: `ecdsa_verify V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_verify V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x05 {uint8}
- Stack: ..., A: [32]byte, B: [32]byte, C: [32]byte, D: [32]byte, E: [32]byte → ..., bool
- for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1}
- **Cost**: Secp256k1=1700; Secp256r1=2500
- Availability: v5
-### ECDSA
+### ECDSA Curves
-Curves
-
-| Index | Name | In | Notes |
-| - | ------ | - | --------- |
+| INDEX | NAME | IN | NOTES |
+| :-: | :------ |:-:| :--------- |
| 0 | Secp256k1 | | secp256k1 curve, used in Bitcoin |
| 1 | Secp256r1 | v7 | secp256r1 curve, NIST standard |
-
The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.
## ecdsa_pk_decompress
-- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x06 {uint8}
- Stack: ..., A: [33]byte → ..., X: [32]byte, Y: [32]byte
- decompress pubkey A into components X, Y
@@ -73,7 +74,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top
## ecdsa_pk_recover
-- Syntax: `ecdsa_pk_recover V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_recover V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x07 {uint8}
- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: [32]byte, Y: [32]byte
- for (data A, recovery id B, signature C, D) recover a public key
@@ -357,17 +358,17 @@ The notation J,K indicates that two uint64 values J and K are interpreted as a u
## txn
-- Syntax: `txn F` where F: [txn](#field-group-txn)
+- Syntax: `txn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x31 {uint8}
- Stack: ... → ..., any
- field F of current transaction
-### txn
+### txn Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | Sender | address | | 32 byte address |
| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
@@ -430,20 +431,17 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 65 | NumApprovalProgramPages | uint64 | v7 | Number of Approval Program pages |
| 67 | NumClearStateProgramPages | uint64 | v7 | Number of ClearState Program pages |
-
## global
-- Syntax: `global F` where F: [global](#field-group-global)
+- Syntax: `global F` where F: [global Fields](#global-fields)
- Bytecode: 0x32 {uint8}
- Stack: ... → ..., any
- global field F
-### global
-
-Fields
+### global Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | MinTxnFee | uint64 | | microalgos |
| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
@@ -468,10 +466,9 @@ Fields
| 21 | PayoutsMinBalance | uint64 | v11 | The minimum balance an account must have in the agreement round to receive block payouts in the proposal round. |
| 22 | PayoutsMaxBalance | uint64 | v11 | The maximum balance an account can have in the agreement round to receive block payouts in the proposal round. |
-
## gtxn
-- Syntax: `gtxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gtxn T F` where T: transaction group index, F: [txn Fields](#txn-fields)
- Bytecode: 0x33 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the current group
@@ -494,18 +491,19 @@ for notes on transaction fields available, see `txn`. If this transaction is _i_
## txna
-- Syntax: `txna F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `txna F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x36 {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F of the current transaction `txna` can be called using `txn` with 2 immediates.
+- Ith value of the array field F of the current transaction
+- `txna` can be called by using `txn` with 2 immediates.
- Availability: v2
-### txna
+### txna Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 26 | ApplicationArgs | []byte | v2 | Arguments passed to the application in the ApplicationCall transaction |
| 28 | Accounts | address | v2 | Accounts listed in the ApplicationCall transaction |
| 48 | Assets | uint64 | v3 | Foreign Assets listed in the ApplicationCall transaction |
@@ -514,18 +512,18 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 64 | ApprovalProgramPages | []byte | v7 | Approval Program as an array of pages |
| 66 | ClearStateProgramPages | []byte | v7 | ClearState Program as an array of pages |
-
## gtxna
-- Syntax: `gtxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x37 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F from the Tth transaction in the current group `gtxna` can be called using `gtxn` with 3 immediates.
+- Ith value of the array field F from the Tth transaction in the current group
+- `gtxna` can be called by using `gtxn` with 3 immediates.
- Availability: v2
## gtxns
-- Syntax: `gtxns F` where F: [txn](#field-group-txn)
+- Syntax: `gtxns F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x38 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of the Ath transaction in the current group
@@ -535,10 +533,11 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
## gtxnsa
-- Syntax: `gtxnsa F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxnsa F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x39 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
-- Ith value of the array field F from the Ath transaction in the current group `gtxnsa` can be called using `gtxns` with 2 immediates.
+- Ith value of the array field F from the Ath transaction in the current group
+- `gtxnsa` can be called by using `gtxns` with 2 immediates.
- Availability: v3
## gload
@@ -792,7 +791,8 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Bytecode: 0x58
- Stack: ..., A: []byte, B: uint64, C: uint64 → ..., []byte
-- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails `extract3` can be called using `extract` with no immediates.
+- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails
+- `extract3` can be called by using `extract` with no immediates.
- Availability: v5
## extract_uint16
@@ -821,60 +821,56 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Syntax: `replace2 S` where S: start position
- Bytecode: 0x5c {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
-- Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A) `replace2` can be called using `replace` with 1 immediate.
+- Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)
+- `replace2` can be called by using `replace` with 1 immediate.
- Availability: v7
## replace3
- Bytecode: 0x5d
- Stack: ..., A: []byte, B: uint64, C: []byte → ..., []byte
-- Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A) `replace3` can be called using `replace` with no immediates.
+- Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)
+- `replace3` can be called by using `replace` with no immediates.
- Availability: v7
## base64_decode
-- Syntax: `base64_decode E` where E: [base64](#field-group-base64)
+- Syntax: `base64_decode E` where E: [base64 Encodings](#base64-encodings)
- Bytecode: 0x5e {uint8}
- Stack: ..., A: []byte → ..., []byte
- decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E
- **Cost**: 1 + 1 per 16 bytes of A
- Availability: v7
-### base64
+### base64 Encodings
-Encodings
-
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | URLEncoding | |
| 1 | StdEncoding | |
-
-*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.
+_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.
Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\n` and `\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\r`, or `\n`.
## json_ref
-- Syntax: `json_ref R` where R: [json_ref](#field-group-json_ref)
+- Syntax: `json_ref R` where R: [json_ref Types](#json_ref-types)
- Bytecode: 0x5f {uint8}
- Stack: ..., A: []byte, B: []byte → ..., any
- key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A
- **Cost**: 25 + 2 per 7 bytes of A
- Availability: v7
-### json_ref
+### json_ref Types
-Types
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | JSONString | []byte | |
| 1 | JSONUint64 | uint64 | |
| 2 | JSONObject | []byte | |
-
-*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.
+_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.
Almost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.
@@ -982,40 +978,35 @@ Deleting a key which is already absent has no effect on the application global s
## asset_holding_get
-- Syntax: `asset_holding_get F` where F: [asset_holding](#field-group-asset_holding)
+- Syntax: `asset_holding_get F` where F: [asset_holding Fields](#asset_holding-fields)
- Bytecode: 0x70 {uint8}
- Stack: ..., A, B: uint64 → ..., X: any, Y: bool
- X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0
- Availability: v2
- Mode: Application
-### asset_holding
+### asset_holding Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetBalance | uint64 | Amount of the asset unit held by this account |
| 1 | AssetFrozen | bool | Is the asset frozen or not |
-
params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## asset_params_get
-- Syntax: `asset_params_get F` where F: [asset_params](#field-group-asset_params)
+- Syntax: `asset_params_get F` where F: [asset_params Fields](#asset_params-fields)
- Bytecode: 0x71 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from asset A. Y is 1 if A exists, else 0
- Availability: v2
- Mode: Application
-### asset_params
-
-Fields
+### asset_params Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AssetTotal | uint64 | | Total number of units of this asset |
| 1 | AssetDecimals | uint64 | | See AssetParams.Decimals |
| 2 | AssetDefaultFrozen | bool | | Frozen by default or not |
@@ -1029,24 +1020,21 @@ Fields
| 10 | AssetClawback | address | | Clawback address |
| 11 | AssetCreator | address | v5 | Creator address |
-
params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## app_params_get
-- Syntax: `app_params_get F` where F: [app_params](#field-group-app_params)
+- Syntax: `app_params_get F` where F: [app_params Fields](#app_params-fields)
- Bytecode: 0x72 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from app A. Y is 1 if A exists, else 0
- Availability: v5
- Mode: Application
-### app_params
-
-Fields
+### app_params Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AppApprovalProgram | []byte | Bytecode of Approval Program |
| 1 | AppClearStateProgram | []byte | Bytecode of Clear State Program |
| 2 | AppGlobalNumUint | uint64 | Number of uint64 values allowed in Global State |
@@ -1057,24 +1045,21 @@ Fields
| 7 | AppCreator | address | Creator address |
| 8 | AppAddress | address | Address for which this application has authority |
-
params: Txn.ForeignApps offset or an _available_ app id. Return: did_exist flag (1 if the application existed and 0 otherwise), value.
## acct_params_get
-- Syntax: `acct_params_get F` where F: [acct_params](#field-group-acct_params)
+- Syntax: `acct_params_get F` where F: [acct_params Fields](#acct_params-fields)
- Bytecode: 0x73 {uint8}
- Stack: ..., A → ..., X: any, Y: bool
- X is field F from account A. Y is 1 if A owns positive algos, else 0
- Availability: v6
- Mode: Application
-### acct_params
-
-Fields
+### acct_params Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AcctBalance | uint64 | | Account balance in microalgos |
| 1 | AcctMinBalance | uint64 | | Minimum required balance for account, in microalgos |
| 2 | AcctAuthAddr | address | | Address the account is rekeyed to. |
@@ -1091,26 +1076,22 @@ Fields
| 13 | AcctLastProposed | uint64 | v11 | The round number of the last block this account proposed. |
| 14 | AcctLastHeartbeat | uint64 | v11 | The round number of the last block this account sent a heartbeat. |
-
## voter_params_get
-- Syntax: `voter_params_get F` where F: [voter_params](#field-group-voter_params)
+- Syntax: `voter_params_get F` where F: [voter_params Fields](#voter_params-fields)
- Bytecode: 0x74 {uint8}
- Stack: ..., A → ..., X: any, Y: bool
- 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
- Availability: v11
- Mode: Application
-### voter_params
-
-Fields
+### voter_params Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | VoterBalance | uint64 | Online stake in microalgos |
| 1 | VoterIncentiveEligible | bool | Had this account opted into block payouts |
-
## online_stake
- Bytecode: 0x75
@@ -1454,7 +1435,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn_field
-- Syntax: `itxn_field F` where F: [txn](#field-group-txn)
+- Syntax: `itxn_field F` where F: [txn](#txn)
- Bytecode: 0xb2 {uint8}
- Stack: ..., A → ...
- set field F of the current inner transaction to A
@@ -1475,7 +1456,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn
-- Syntax: `itxn F` where F: [txn](#field-group-txn)
+- Syntax: `itxn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0xb4 {uint8}
- Stack: ... → ..., any
- field F of the last inner transaction
@@ -1484,7 +1465,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxna
-- Syntax: `itxna F I` where F: [txna](#field-group-txna), I: a transaction field array index
+- Syntax: `itxna F I` where F: [txna Fields](#txna-fields), I: a transaction field array index
- Bytecode: 0xb5 {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F of the last inner transaction
@@ -1503,7 +1484,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxn
-- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#txn)
- Bytecode: 0xb7 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the last inner group submitted
@@ -1512,7 +1493,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxna
-- Syntax: `gitxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gitxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0xb8 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F from the Tth transaction in the last inner group submitted
@@ -1583,7 +1564,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## txnas
-- Syntax: `txnas F` where F: [txna](#field-group-txna)
+- Syntax: `txnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc0 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the current transaction
@@ -1591,7 +1572,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gtxnas
-- Syntax: `gtxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gtxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc1 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the current group
@@ -1599,7 +1580,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gtxnsas
-- Syntax: `gtxnsas F` where F: [txna](#field-group-txna)
+- Syntax: `gtxnsas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc2 {uint8}
- Stack: ..., A: uint64, B: uint64 → ..., any
- Bth value of the array field F from the Ath transaction in the current group
@@ -1623,7 +1604,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## itxnas
-- Syntax: `itxnas F` where F: [txna](#field-group-txna)
+- Syntax: `itxnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc5 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the last inner transaction
@@ -1632,7 +1613,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gitxnas
-- Syntax: `gitxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gitxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc6 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the last inner group submitted
@@ -1641,38 +1622,33 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## vrf_verify
-- Syntax: `vrf_verify S` where S: [vrf_verify](#field-group-vrf_verify)
+- Syntax: `vrf_verify S` where S: [vrf_verify Standards](#vrf_verify-standards)
- Bytecode: 0xd0 {uint8}
- Stack: ..., A: []byte, B: [80]byte, C: [32]byte → ..., X: [64]byte, Y: bool
- Verify the proof B of message A against pubkey C. Returns vrf output and verification flag.
- **Cost**: 5700
- Availability: v7
-### vrf_verify
-
-Standards
+### vrf_verify Standards
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | VrfAlgorand | |
-
`VrfAlgorand` is the VRF used in Algorand. It is ECVRF-ED25519-SHA512-Elligator2, specified in the IETF internet draft [draft-irtf-cfrg-vrf-03](https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/03/).
## block
-- Syntax: `block F` where F: [block](#field-group-block)
+- Syntax: `block F` where F: [block Fields](#block-fields)
- Bytecode: 0xd1 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of block A. Fail unless A falls between txn.LastValid-1002 and txn.FirstValid (exclusive)
- Availability: v7
-### block
-
-Fields
+### block Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | BlkSeed | [32]byte | | |
| 1 | BlkTimestamp | uint64 | | |
| 2 | BlkProposer | address | v11 | |
@@ -1684,7 +1660,6 @@ Fields
| 8 | BlkTxnCounter | uint64 | v11 | |
| 9 | BlkProposerPayout | uint64 | v11 | |
-
## box_splice
- Bytecode: 0xd2
@@ -1705,25 +1680,22 @@ Boxes are of constant length. If C < len(D), then len(D)-C bytes will be removed
## ec_add
-- Syntax: `ec_add G` where G: [EC](#field-group-ec)
+- Syntax: `ec_add G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe0 {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
- for curve points A and B, return the curve point A + B
- **Cost**: BN254g1=125; BN254g2=170; BLS12_381g1=205; BLS12_381g2=290
- Availability: v10
-### EC
-
-Groups
+### EC Groups
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | BN254g1 | G1 of the BN254 curve. Points encoded as 32 byte X following by 32 byte Y |
| 1 | BN254g2 | G2 of the BN254 curve. Points encoded as 64 byte X following by 64 byte Y |
| 2 | BLS12_381g1 | G1 of the BLS 12-381 curve. Points encoded as 48 byte X following by 48 byte Y |
| 3 | BLS12_381g2 | G2 of the BLS 12-381 curve. Points encoded as 96 byte X following by 96 byte Y |
-
A and B are curve points in affine representation: field element X concatenated with field element Y. Field element `Z` is encoded as follows.
For the base field elements (Fp), `Z` is encoded as a big-endian number and must be lower than the field modulus.
For the quadratic field extension (Fp2), `Z` is encoded as the concatenation of the individual encoding of the coefficients. For an Fp2 element of the form `Z = Z0 + Z1 i`, where `i` is a formal quadratic non-residue, the encoding of Z is the concatenation of the encoding of `Z0` and `Z1` in this order. (`Z0` and `Z1` must be less than the field modulus).
@@ -1737,7 +1709,7 @@ Does _not_ check if A and B are in the main prime-order subgroup.
## ec_scalar_mul
-- Syntax: `ec_scalar_mul G` where G: [EC](#field-group-ec)
+- Syntax: `ec_scalar_mul G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe1 {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
- for curve point A and scalar B, return the curve point BA, the point A multiplied by the scalar B.
@@ -1748,7 +1720,7 @@ A is a curve point encoded and checked as described in `ec_add`. Scalar B is int
## ec_pairing_check
-- Syntax: `ec_pairing_check G` where G: [EC](#field-group-ec)
+- Syntax: `ec_pairing_check G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe2 {uint8}
- Stack: ..., A: []byte, B: []byte → ..., bool
- 1 if the product of the pairing of each point in A with its respective point in B is equal to the identity element of the target group Gt, else 0
@@ -1759,7 +1731,7 @@ A and B are concatenated points, encoded and checked as described in `ec_add`. A
## ec_multi_scalar_mul
-- Syntax: `ec_multi_scalar_mul G` where G: [EC](#field-group-ec)
+- Syntax: `ec_multi_scalar_mul G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe3 {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
- for curve points A and scalars B, return curve point B0A0 + B1A1 + B2A2 + ... + BnAn
@@ -1771,7 +1743,7 @@ The name `ec_multi_scalar_mul` was chosen to reflect common usage, but a more co
## ec_subgroup_check
-- Syntax: `ec_subgroup_check G` where G: [EC](#field-group-ec)
+- Syntax: `ec_subgroup_check G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe4 {uint8}
- Stack: ..., A: []byte → ..., bool
- 1 if A is in the main prime-order subgroup of G (including the point at infinity) else 0. Program fails if A is not in G at all.
@@ -1780,7 +1752,7 @@ The name `ec_multi_scalar_mul` was chosen to reflect common usage, but a more co
## ec_map_to
-- Syntax: `ec_map_to G` where G: [EC](#field-group-ec)
+- Syntax: `ec_map_to G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe5 {uint8}
- Stack: ..., A: []byte → ..., []byte
- maps field element A to group G
@@ -1792,23 +1764,20 @@ G1 element inputs are base field elements and G2 element inputs are quadratic fi
## mimc
-- Syntax: `mimc C` where C: [Mimc Configurations](#field-group-mimc configurations)
+- Syntax: `mimc C` where C: [MimcConfigurations Parameters](#mimcconfigurations-parameters)
- Bytecode: 0xe6 {uint8}
- Stack: ..., A: []byte → ..., [32]byte
- MiMC hash of scalars A, using curve and parameters specified by configuration C
- **Cost**: BN254Mp110=10 + 550 per 32 bytes of A; BLS12_381Mp111=10 + 550 per 32 bytes of A
- Availability: v11
-### Mimc Configurations
-
-Parameters
+### MimcConfigurations Parameters
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | BN254Mp110 | MiMC configuration for the BN254 curve with Miyaguchi-Preneel mode, 110 rounds, exponent 5, seed "seed" |
| 1 | BLS12_381Mp111 | MiMC configuration for the BLS12-381 curve with Miyaguchi-Preneel mode, 111 rounds, exponent 5, seed "seed" |
-
A is a list of concatenated 32 byte big-endian unsigned integer scalars. Fail if A's length is not a multiple of 32 or any element exceeds the curve modulus.
The MiMC hash function has known collisions since any input which is a multiple of the elliptic curve modulus will hash to the same value. MiMC is thus not a general purpose hash function, but meant to be used in zero knowledge applications to match a zk-circuit implementation.
diff --git a/data/transactions/logic/TEAL_opcodes_v12.md b/data/transactions/logic/TEAL_opcodes_v12.md
index 6586f11a5e..bde4cc61d1 100644
--- a/data/transactions/logic/TEAL_opcodes_v12.md
+++ b/data/transactions/logic/TEAL_opcodes_v12.md
@@ -1,7 +1,11 @@
-# v12 Opcodes
-Ops have a 'cost' of 1 unless otherwise specified.
+# Version 12 Opcodes
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
## err
@@ -41,28 +45,25 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte
## ecdsa_verify
-- Syntax: `ecdsa_verify V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_verify V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x05 {uint8}
- Stack: ..., A: [32]byte, B: [32]byte, C: [32]byte, D: [32]byte, E: [32]byte → ..., bool
- for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1}
- **Cost**: Secp256k1=1700; Secp256r1=2500
- Availability: v5
-### ECDSA
+### ECDSA Curves
-Curves
-
-| Index | Name | In | Notes |
-| - | ------ | - | --------- |
+| INDEX | NAME | IN | NOTES |
+| :-: | :------ |:-:| :--------- |
| 0 | Secp256k1 | | secp256k1 curve, used in Bitcoin |
| 1 | Secp256r1 | v7 | secp256r1 curve, NIST standard |
-
The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.
## ecdsa_pk_decompress
-- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x06 {uint8}
- Stack: ..., A: [33]byte → ..., X: [32]byte, Y: [32]byte
- decompress pubkey A into components X, Y
@@ -73,7 +74,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top
## ecdsa_pk_recover
-- Syntax: `ecdsa_pk_recover V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_recover V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x07 {uint8}
- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: [32]byte, Y: [32]byte
- for (data A, recovery id B, signature C, D) recover a public key
@@ -357,17 +358,17 @@ The notation J,K indicates that two uint64 values J and K are interpreted as a u
## txn
-- Syntax: `txn F` where F: [txn](#field-group-txn)
+- Syntax: `txn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x31 {uint8}
- Stack: ... → ..., any
- field F of current transaction
-### txn
+### txn Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | Sender | address | | 32 byte address |
| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
@@ -431,20 +432,17 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 67 | NumClearStateProgramPages | uint64 | v7 | Number of ClearState Program pages |
| 68 | RejectVersion | uint64 | v12 | Application version for which the txn must reject |
-
## global
-- Syntax: `global F` where F: [global](#field-group-global)
+- Syntax: `global F` where F: [global Fields](#global-fields)
- Bytecode: 0x32 {uint8}
- Stack: ... → ..., any
- global field F
-### global
-
-Fields
+### global Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | MinTxnFee | uint64 | | microalgos |
| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
@@ -469,10 +467,9 @@ Fields
| 21 | PayoutsMinBalance | uint64 | v11 | The minimum balance an account must have in the agreement round to receive block payouts in the proposal round. |
| 22 | PayoutsMaxBalance | uint64 | v11 | The maximum balance an account can have in the agreement round to receive block payouts in the proposal round. |
-
## gtxn
-- Syntax: `gtxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gtxn T F` where T: transaction group index, F: [txn Fields](#txn-fields)
- Bytecode: 0x33 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the current group
@@ -495,18 +492,19 @@ for notes on transaction fields available, see `txn`. If this transaction is _i_
## txna
-- Syntax: `txna F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `txna F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x36 {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F of the current transaction `txna` can be called using `txn` with 2 immediates.
+- Ith value of the array field F of the current transaction
+- `txna` can be called by using `txn` with 2 immediates.
- Availability: v2
-### txna
+### txna Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 26 | ApplicationArgs | []byte | v2 | Arguments passed to the application in the ApplicationCall transaction |
| 28 | Accounts | address | v2 | Accounts listed in the ApplicationCall transaction |
| 48 | Assets | uint64 | v3 | Foreign Assets listed in the ApplicationCall transaction |
@@ -515,18 +513,18 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 64 | ApprovalProgramPages | []byte | v7 | Approval Program as an array of pages |
| 66 | ClearStateProgramPages | []byte | v7 | ClearState Program as an array of pages |
-
## gtxna
-- Syntax: `gtxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x37 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F from the Tth transaction in the current group `gtxna` can be called using `gtxn` with 3 immediates.
+- Ith value of the array field F from the Tth transaction in the current group
+- `gtxna` can be called by using `gtxn` with 3 immediates.
- Availability: v2
## gtxns
-- Syntax: `gtxns F` where F: [txn](#field-group-txn)
+- Syntax: `gtxns F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x38 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of the Ath transaction in the current group
@@ -536,10 +534,11 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
## gtxnsa
-- Syntax: `gtxnsa F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxnsa F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x39 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
-- Ith value of the array field F from the Ath transaction in the current group `gtxnsa` can be called using `gtxns` with 2 immediates.
+- Ith value of the array field F from the Ath transaction in the current group
+- `gtxnsa` can be called by using `gtxns` with 2 immediates.
- Availability: v3
## gload
@@ -793,7 +792,8 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Bytecode: 0x58
- Stack: ..., A: []byte, B: uint64, C: uint64 → ..., []byte
-- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails `extract3` can be called using `extract` with no immediates.
+- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails
+- `extract3` can be called by using `extract` with no immediates.
- Availability: v5
## extract_uint16
@@ -822,60 +822,56 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Syntax: `replace2 S` where S: start position
- Bytecode: 0x5c {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
-- Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A) `replace2` can be called using `replace` with 1 immediate.
+- Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)
+- `replace2` can be called by using `replace` with 1 immediate.
- Availability: v7
## replace3
- Bytecode: 0x5d
- Stack: ..., A: []byte, B: uint64, C: []byte → ..., []byte
-- Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A) `replace3` can be called using `replace` with no immediates.
+- Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)
+- `replace3` can be called by using `replace` with no immediates.
- Availability: v7
## base64_decode
-- Syntax: `base64_decode E` where E: [base64](#field-group-base64)
+- Syntax: `base64_decode E` where E: [base64 Encodings](#base64-encodings)
- Bytecode: 0x5e {uint8}
- Stack: ..., A: []byte → ..., []byte
- decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E
- **Cost**: 1 + 1 per 16 bytes of A
- Availability: v7
-### base64
+### base64 Encodings
-Encodings
-
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | URLEncoding | |
| 1 | StdEncoding | |
-
-*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.
+_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.
Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\n` and `\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\r`, or `\n`.
## json_ref
-- Syntax: `json_ref R` where R: [json_ref](#field-group-json_ref)
+- Syntax: `json_ref R` where R: [json_ref Types](#json_ref-types)
- Bytecode: 0x5f {uint8}
- Stack: ..., A: []byte, B: []byte → ..., any
- key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A
- **Cost**: 25 + 2 per 7 bytes of A
- Availability: v7
-### json_ref
+### json_ref Types
-Types
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | JSONString | []byte | |
| 1 | JSONUint64 | uint64 | |
| 2 | JSONObject | []byte | |
-
-*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.
+_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.
Almost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.
@@ -983,40 +979,35 @@ Deleting a key which is already absent has no effect on the application global s
## asset_holding_get
-- Syntax: `asset_holding_get F` where F: [asset_holding](#field-group-asset_holding)
+- Syntax: `asset_holding_get F` where F: [asset_holding Fields](#asset_holding-fields)
- Bytecode: 0x70 {uint8}
- Stack: ..., A, B: uint64 → ..., X: any, Y: bool
- X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0
- Availability: v2
- Mode: Application
-### asset_holding
+### asset_holding Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetBalance | uint64 | Amount of the asset unit held by this account |
| 1 | AssetFrozen | bool | Is the asset frozen or not |
-
params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## asset_params_get
-- Syntax: `asset_params_get F` where F: [asset_params](#field-group-asset_params)
+- Syntax: `asset_params_get F` where F: [asset_params Fields](#asset_params-fields)
- Bytecode: 0x71 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from asset A. Y is 1 if A exists, else 0
- Availability: v2
- Mode: Application
-### asset_params
-
-Fields
+### asset_params Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AssetTotal | uint64 | | Total number of units of this asset |
| 1 | AssetDecimals | uint64 | | See AssetParams.Decimals |
| 2 | AssetDefaultFrozen | bool | | Frozen by default or not |
@@ -1030,24 +1021,21 @@ Fields
| 10 | AssetClawback | address | | Clawback address |
| 11 | AssetCreator | address | v5 | Creator address |
-
params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## app_params_get
-- Syntax: `app_params_get F` where F: [app_params](#field-group-app_params)
+- Syntax: `app_params_get F` where F: [app_params Fields](#app_params-fields)
- Bytecode: 0x72 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from app A. Y is 1 if A exists, else 0
- Availability: v5
- Mode: Application
-### app_params
-
-Fields
+### app_params Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AppApprovalProgram | []byte | | Bytecode of Approval Program |
| 1 | AppClearStateProgram | []byte | | Bytecode of Clear State Program |
| 2 | AppGlobalNumUint | uint64 | | Number of uint64 values allowed in Global State |
@@ -1059,24 +1047,21 @@ Fields
| 8 | AppAddress | address | | Address for which this application has authority |
| 9 | AppVersion | uint64 | v12 | Version of the app, incremented each time the approval or clear program changes |
-
params: Txn.ForeignApps offset or an _available_ app id. Return: did_exist flag (1 if the application existed and 0 otherwise), value.
## acct_params_get
-- Syntax: `acct_params_get F` where F: [acct_params](#field-group-acct_params)
+- Syntax: `acct_params_get F` where F: [acct_params Fields](#acct_params-fields)
- Bytecode: 0x73 {uint8}
- Stack: ..., A → ..., X: any, Y: bool
- X is field F from account A. Y is 1 if A owns positive algos, else 0
- Availability: v6
- Mode: Application
-### acct_params
-
-Fields
+### acct_params Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AcctBalance | uint64 | | Account balance in microalgos |
| 1 | AcctMinBalance | uint64 | | Minimum required balance for account, in microalgos |
| 2 | AcctAuthAddr | address | | Address the account is rekeyed to. |
@@ -1093,26 +1078,22 @@ Fields
| 13 | AcctLastProposed | uint64 | v11 | The round number of the last block this account proposed. |
| 14 | AcctLastHeartbeat | uint64 | v11 | The round number of the last block this account sent a heartbeat. |
-
## voter_params_get
-- Syntax: `voter_params_get F` where F: [voter_params](#field-group-voter_params)
+- Syntax: `voter_params_get F` where F: [voter_params Fields](#voter_params-fields)
- Bytecode: 0x74 {uint8}
- Stack: ..., A → ..., X: any, Y: bool
- 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
- Availability: v11
- Mode: Application
-### voter_params
-
-Fields
+### voter_params Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | VoterBalance | uint64 | Online stake in microalgos |
| 1 | VoterIncentiveEligible | bool | Had this account opted into block payouts |
-
## online_stake
- Bytecode: 0x75
@@ -1464,7 +1445,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn_field
-- Syntax: `itxn_field F` where F: [txn](#field-group-txn)
+- Syntax: `itxn_field F` where F: [txn](#txn)
- Bytecode: 0xb2 {uint8}
- Stack: ..., A → ...
- set field F of the current inner transaction to A
@@ -1485,7 +1466,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn
-- Syntax: `itxn F` where F: [txn](#field-group-txn)
+- Syntax: `itxn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0xb4 {uint8}
- Stack: ... → ..., any
- field F of the last inner transaction
@@ -1494,7 +1475,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxna
-- Syntax: `itxna F I` where F: [txna](#field-group-txna), I: a transaction field array index
+- Syntax: `itxna F I` where F: [txna Fields](#txna-fields), I: a transaction field array index
- Bytecode: 0xb5 {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F of the last inner transaction
@@ -1513,7 +1494,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxn
-- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#txn)
- Bytecode: 0xb7 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the last inner group submitted
@@ -1522,7 +1503,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxna
-- Syntax: `gitxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gitxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0xb8 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F from the Tth transaction in the last inner group submitted
@@ -1593,7 +1574,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## txnas
-- Syntax: `txnas F` where F: [txna](#field-group-txna)
+- Syntax: `txnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc0 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the current transaction
@@ -1601,7 +1582,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gtxnas
-- Syntax: `gtxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gtxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc1 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the current group
@@ -1609,7 +1590,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gtxnsas
-- Syntax: `gtxnsas F` where F: [txna](#field-group-txna)
+- Syntax: `gtxnsas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc2 {uint8}
- Stack: ..., A: uint64, B: uint64 → ..., any
- Bth value of the array field F from the Ath transaction in the current group
@@ -1633,7 +1614,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## itxnas
-- Syntax: `itxnas F` where F: [txna](#field-group-txna)
+- Syntax: `itxnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc5 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the last inner transaction
@@ -1642,7 +1623,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gitxnas
-- Syntax: `gitxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gitxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc6 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the last inner group submitted
@@ -1651,38 +1632,33 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## vrf_verify
-- Syntax: `vrf_verify S` where S: [vrf_verify](#field-group-vrf_verify)
+- Syntax: `vrf_verify S` where S: [vrf_verify Standards](#vrf_verify-standards)
- Bytecode: 0xd0 {uint8}
- Stack: ..., A: []byte, B: [80]byte, C: [32]byte → ..., X: [64]byte, Y: bool
- Verify the proof B of message A against pubkey C. Returns vrf output and verification flag.
- **Cost**: 5700
- Availability: v7
-### vrf_verify
-
-Standards
+### vrf_verify Standards
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | VrfAlgorand | |
-
`VrfAlgorand` is the VRF used in Algorand. It is ECVRF-ED25519-SHA512-Elligator2, specified in the IETF internet draft [draft-irtf-cfrg-vrf-03](https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/03/).
## block
-- Syntax: `block F` where F: [block](#field-group-block)
+- Syntax: `block F` where F: [block Fields](#block-fields)
- Bytecode: 0xd1 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of block A. Fail unless A falls between txn.LastValid-1002 and txn.FirstValid (exclusive)
- Availability: v7
-### block
-
-Fields
+### block Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | BlkSeed | [32]byte | | |
| 1 | BlkTimestamp | uint64 | | |
| 2 | BlkProposer | address | v11 | |
@@ -1694,7 +1670,6 @@ Fields
| 8 | BlkTxnCounter | uint64 | v11 | |
| 9 | BlkProposerPayout | uint64 | v11 | |
-
## box_splice
- Bytecode: 0xd2
@@ -1715,25 +1690,22 @@ Boxes are of constant length. If C < len(D), then len(D)-C bytes will be removed
## ec_add
-- Syntax: `ec_add G` where G: [EC](#field-group-ec)
+- Syntax: `ec_add G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe0 {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
- for curve points A and B, return the curve point A + B
- **Cost**: BN254g1=125; BN254g2=170; BLS12_381g1=205; BLS12_381g2=290
- Availability: v10
-### EC
-
-Groups
+### EC Groups
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | BN254g1 | G1 of the BN254 curve. Points encoded as 32 byte X following by 32 byte Y |
| 1 | BN254g2 | G2 of the BN254 curve. Points encoded as 64 byte X following by 64 byte Y |
| 2 | BLS12_381g1 | G1 of the BLS 12-381 curve. Points encoded as 48 byte X following by 48 byte Y |
| 3 | BLS12_381g2 | G2 of the BLS 12-381 curve. Points encoded as 96 byte X following by 96 byte Y |
-
A and B are curve points in affine representation: field element X concatenated with field element Y. Field element `Z` is encoded as follows.
For the base field elements (Fp), `Z` is encoded as a big-endian number and must be lower than the field modulus.
For the quadratic field extension (Fp2), `Z` is encoded as the concatenation of the individual encoding of the coefficients. For an Fp2 element of the form `Z = Z0 + Z1 i`, where `i` is a formal quadratic non-residue, the encoding of Z is the concatenation of the encoding of `Z0` and `Z1` in this order. (`Z0` and `Z1` must be less than the field modulus).
@@ -1747,7 +1719,7 @@ Does _not_ check if A and B are in the main prime-order subgroup.
## ec_scalar_mul
-- Syntax: `ec_scalar_mul G` where G: [EC](#field-group-ec)
+- Syntax: `ec_scalar_mul G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe1 {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
- for curve point A and scalar B, return the curve point BA, the point A multiplied by the scalar B.
@@ -1758,7 +1730,7 @@ A is a curve point encoded and checked as described in `ec_add`. Scalar B is int
## ec_pairing_check
-- Syntax: `ec_pairing_check G` where G: [EC](#field-group-ec)
+- Syntax: `ec_pairing_check G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe2 {uint8}
- Stack: ..., A: []byte, B: []byte → ..., bool
- 1 if the product of the pairing of each point in A with its respective point in B is equal to the identity element of the target group Gt, else 0
@@ -1769,7 +1741,7 @@ A and B are concatenated points, encoded and checked as described in `ec_add`. A
## ec_multi_scalar_mul
-- Syntax: `ec_multi_scalar_mul G` where G: [EC](#field-group-ec)
+- Syntax: `ec_multi_scalar_mul G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe3 {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
- for curve points A and scalars B, return curve point B0A0 + B1A1 + B2A2 + ... + BnAn
@@ -1781,7 +1753,7 @@ The name `ec_multi_scalar_mul` was chosen to reflect common usage, but a more co
## ec_subgroup_check
-- Syntax: `ec_subgroup_check G` where G: [EC](#field-group-ec)
+- Syntax: `ec_subgroup_check G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe4 {uint8}
- Stack: ..., A: []byte → ..., bool
- 1 if A is in the main prime-order subgroup of G (including the point at infinity) else 0. Program fails if A is not in G at all.
@@ -1790,7 +1762,7 @@ The name `ec_multi_scalar_mul` was chosen to reflect common usage, but a more co
## ec_map_to
-- Syntax: `ec_map_to G` where G: [EC](#field-group-ec)
+- Syntax: `ec_map_to G` where G: [EC Groups](#ec-groups)
- Bytecode: 0xe5 {uint8}
- Stack: ..., A: []byte → ..., []byte
- maps field element A to group G
@@ -1802,23 +1774,20 @@ G1 element inputs are base field elements and G2 element inputs are quadratic fi
## mimc
-- Syntax: `mimc C` where C: [Mimc Configurations](#field-group-mimc configurations)
+- Syntax: `mimc C` where C: [MimcConfigurations Parameters](#mimcconfigurations-parameters)
- Bytecode: 0xe6 {uint8}
- Stack: ..., A: []byte → ..., [32]byte
- MiMC hash of scalars A, using curve and parameters specified by configuration C
- **Cost**: BN254Mp110=10 + 550 per 32 bytes of A; BLS12_381Mp111=10 + 550 per 32 bytes of A
- Availability: v11
-### Mimc Configurations
-
-Parameters
+### MimcConfigurations Parameters
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | BN254Mp110 | MiMC configuration for the BN254 curve with Miyaguchi-Preneel mode, 110 rounds, exponent 5, seed "seed" |
| 1 | BLS12_381Mp111 | MiMC configuration for the BLS12-381 curve with Miyaguchi-Preneel mode, 111 rounds, exponent 5, seed "seed" |
-
A is a list of concatenated 32 byte big-endian unsigned integer scalars. Fail if A's length is not a multiple of 32 or any element exceeds the curve modulus.
The MiMC hash function has known collisions since any input which is a multiple of the elliptic curve modulus will hash to the same value. MiMC is thus not a general purpose hash function, but meant to be used in zero knowledge applications to match a zk-circuit implementation.
diff --git a/data/transactions/logic/TEAL_opcodes_v2.md b/data/transactions/logic/TEAL_opcodes_v2.md
index 84d21cb744..f15a46aa3f 100644
--- a/data/transactions/logic/TEAL_opcodes_v2.md
+++ b/data/transactions/logic/TEAL_opcodes_v2.md
@@ -1,7 +1,11 @@
-# v2 Opcodes
-Ops have a 'cost' of 1 unless otherwise specified.
+# Version 2 Opcodes
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
## err
@@ -305,17 +309,17 @@ Overflow is an error condition which halts execution and fails the transaction.
## txn
-- Syntax: `txn F` where F: [txn](#field-group-txn)
+- Syntax: `txn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x31 {uint8}
- Stack: ... → ..., any
- field F of current transaction
-### txn
+### txn Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | Sender | address | | 32 byte address |
| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
@@ -362,20 +366,17 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 46 | FreezeAssetAccount | address | v2 | 32 byte address of the account whose asset slot is being frozen or un-frozen |
| 47 | FreezeAssetFrozen | bool | v2 | The new frozen value, 0 or 1 |
-
## global
-- Syntax: `global F` where F: [global](#field-group-global)
+- Syntax: `global F` where F: [global Fields](#global-fields)
- Bytecode: 0x32 {uint8}
- Stack: ... → ..., any
- global field F
-### global
+### global Fields
-Fields
-
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | MinTxnFee | uint64 | | microalgos |
| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
@@ -386,10 +387,9 @@ Fields
| 7 | LatestTimestamp | uint64 | v2 | Last confirmed block UNIX timestamp. Fails if negative. Application mode only. |
| 8 | CurrentApplicationID | uint64 | v2 | ID of current application executing. Application mode only. |
-
## gtxn
-- Syntax: `gtxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gtxn T F` where T: transaction group index, F: [txn Fields](#txn-fields)
- Bytecode: 0x33 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the current group
@@ -412,28 +412,29 @@ for notes on transaction fields available, see `txn`. If this transaction is _i_
## txna
-- Syntax: `txna F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `txna F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x36 {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F of the current transaction `txna` can be called using `txn` with 2 immediates.
+- Ith value of the array field F of the current transaction
+- `txna` can be called by using `txn` with 2 immediates.
- Availability: v2
-### txna
+### txna Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 26 | ApplicationArgs | []byte | Arguments passed to the application in the ApplicationCall transaction |
| 28 | Accounts | address | Accounts listed in the ApplicationCall transaction |
-
## gtxna
-- Syntax: `gtxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x37 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F from the Tth transaction in the current group `gtxna` can be called using `gtxn` with 3 immediates.
+- Ith value of the array field F from the Tth transaction in the current group
+- `gtxna` can be called by using `gtxn` with 3 immediates.
- Availability: v2
## bnz
@@ -621,40 +622,35 @@ Deleting a key which is already absent has no effect on the application global s
## asset_holding_get
-- Syntax: `asset_holding_get F` where F: [asset_holding](#field-group-asset_holding)
+- Syntax: `asset_holding_get F` where F: [asset_holding Fields](#asset_holding-fields)
- Bytecode: 0x70 {uint8}
- Stack: ..., A: uint64, B: uint64 → ..., X: any, Y: bool
- X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0
- Availability: v2
- Mode: Application
-### asset_holding
-
-Fields
+### asset_holding Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetBalance | uint64 | Amount of the asset unit held by this account |
| 1 | AssetFrozen | bool | Is the asset frozen or not |
-
params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## asset_params_get
-- Syntax: `asset_params_get F` where F: [asset_params](#field-group-asset_params)
+- Syntax: `asset_params_get F` where F: [asset_params Fields](#asset_params-fields)
- Bytecode: 0x71 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from asset A. Y is 1 if A exists, else 0
- Availability: v2
- Mode: Application
-### asset_params
+### asset_params Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetTotal | uint64 | Total number of units of this asset |
| 1 | AssetDecimals | uint64 | See AssetParams.Decimals |
| 2 | AssetDefaultFrozen | bool | Frozen by default or not |
@@ -667,5 +663,4 @@ Fields
| 9 | AssetFreeze | address | Freeze address |
| 10 | AssetClawback | address | Clawback address |
-
params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
diff --git a/data/transactions/logic/TEAL_opcodes_v3.md b/data/transactions/logic/TEAL_opcodes_v3.md
index b9b21b141f..903bd0c0a2 100644
--- a/data/transactions/logic/TEAL_opcodes_v3.md
+++ b/data/transactions/logic/TEAL_opcodes_v3.md
@@ -1,7 +1,11 @@
-# v3 Opcodes
-Ops have a 'cost' of 1 unless otherwise specified.
+# Version 3 Opcodes
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
## err
@@ -305,17 +309,17 @@ Overflow is an error condition which halts execution and fails the transaction.
## txn
-- Syntax: `txn F` where F: [txn](#field-group-txn)
+- Syntax: `txn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x31 {uint8}
- Stack: ... → ..., any
- field F of current transaction
-### txn
+### txn Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | Sender | address | | 32 byte address |
| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
@@ -368,20 +372,17 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 54 | LocalNumUint | uint64 | v3 | Number of local state integers in ApplicationCall |
| 55 | LocalNumByteSlice | uint64 | v3 | Number of local state byteslices in ApplicationCall |
-
## global
-- Syntax: `global F` where F: [global](#field-group-global)
+- Syntax: `global F` where F: [global Fields](#global-fields)
- Bytecode: 0x32 {uint8}
- Stack: ... → ..., any
- global field F
-### global
+### global Fields
-Fields
-
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | MinTxnFee | uint64 | | microalgos |
| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
@@ -393,10 +394,9 @@ Fields
| 8 | CurrentApplicationID | uint64 | v2 | ID of current application executing. Application mode only. |
| 9 | CreatorAddress | address | v3 | Address of the creator of the current application. Application mode only. |
-
## gtxn
-- Syntax: `gtxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gtxn T F` where T: transaction group index, F: [txn Fields](#txn-fields)
- Bytecode: 0x33 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the current group
@@ -419,35 +419,36 @@ for notes on transaction fields available, see `txn`. If this transaction is _i_
## txna
-- Syntax: `txna F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `txna F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x36 {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F of the current transaction `txna` can be called using `txn` with 2 immediates.
+- Ith value of the array field F of the current transaction
+- `txna` can be called by using `txn` with 2 immediates.
- Availability: v2
-### txna
+### txna Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 26 | ApplicationArgs | []byte | v2 | Arguments passed to the application in the ApplicationCall transaction |
| 28 | Accounts | address | v2 | Accounts listed in the ApplicationCall transaction |
| 48 | Assets | uint64 | v3 | Foreign Assets listed in the ApplicationCall transaction |
| 50 | Applications | uint64 | v3 | Foreign Apps listed in the ApplicationCall transaction |
-
## gtxna
-- Syntax: `gtxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x37 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F from the Tth transaction in the current group `gtxna` can be called using `gtxn` with 3 immediates.
+- Ith value of the array field F from the Tth transaction in the current group
+- `gtxna` can be called by using `gtxn` with 3 immediates.
- Availability: v2
## gtxns
-- Syntax: `gtxns F` where F: [txn](#field-group-txn)
+- Syntax: `gtxns F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x38 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of the Ath transaction in the current group
@@ -457,10 +458,11 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
## gtxnsa
-- Syntax: `gtxnsa F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxnsa F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x39 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
-- Ith value of the array field F from the Ath transaction in the current group `gtxnsa` can be called using `gtxns` with 2 immediates.
+- Ith value of the array field F from the Ath transaction in the current group
+- `gtxnsa` can be called by using `gtxns` with 2 immediates.
- Availability: v3
## bnz
@@ -709,40 +711,35 @@ Deleting a key which is already absent has no effect on the application global s
## asset_holding_get
-- Syntax: `asset_holding_get F` where F: [asset_holding](#field-group-asset_holding)
+- Syntax: `asset_holding_get F` where F: [asset_holding Fields](#asset_holding-fields)
- Bytecode: 0x70 {uint8}
- Stack: ..., A: uint64, B: uint64 → ..., X: any, Y: bool
- X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0
- Availability: v2
- Mode: Application
-### asset_holding
-
-Fields
+### asset_holding Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetBalance | uint64 | Amount of the asset unit held by this account |
| 1 | AssetFrozen | bool | Is the asset frozen or not |
-
params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## asset_params_get
-- Syntax: `asset_params_get F` where F: [asset_params](#field-group-asset_params)
+- Syntax: `asset_params_get F` where F: [asset_params Fields](#asset_params-fields)
- Bytecode: 0x71 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from asset A. Y is 1 if A exists, else 0
- Availability: v2
- Mode: Application
-### asset_params
+### asset_params Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetTotal | uint64 | Total number of units of this asset |
| 1 | AssetDecimals | uint64 | See AssetParams.Decimals |
| 2 | AssetDefaultFrozen | bool | Frozen by default or not |
@@ -755,7 +752,6 @@ Fields
| 9 | AssetFreeze | address | Freeze address |
| 10 | AssetClawback | address | Clawback address |
-
params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## min_balance
diff --git a/data/transactions/logic/TEAL_opcodes_v4.md b/data/transactions/logic/TEAL_opcodes_v4.md
index 2fb554bed1..dd6447575e 100644
--- a/data/transactions/logic/TEAL_opcodes_v4.md
+++ b/data/transactions/logic/TEAL_opcodes_v4.md
@@ -1,7 +1,11 @@
-# v4 Opcodes
-Ops have a 'cost' of 1 unless otherwise specified.
+# Version 4 Opcodes
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
## err
@@ -315,17 +319,17 @@ The notation J,K indicates that two uint64 values J and K are interpreted as a u
## txn
-- Syntax: `txn F` where F: [txn](#field-group-txn)
+- Syntax: `txn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x31 {uint8}
- Stack: ... → ..., any
- field F of current transaction
-### txn
+### txn Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | Sender | address | | 32 byte address |
| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
@@ -379,20 +383,17 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 55 | LocalNumByteSlice | uint64 | v3 | Number of local state byteslices in ApplicationCall |
| 56 | ExtraProgramPages | uint64 | v4 | Number of additional pages for each of the application's approval and clear state programs. An ExtraProgramPages of 1 means 2048 more total bytes, or 1024 for each program. |
-
## global
-- Syntax: `global F` where F: [global](#field-group-global)
+- Syntax: `global F` where F: [global Fields](#global-fields)
- Bytecode: 0x32 {uint8}
- Stack: ... → ..., any
- global field F
-### global
+### global Fields
-Fields
-
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | MinTxnFee | uint64 | | microalgos |
| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
@@ -404,10 +405,9 @@ Fields
| 8 | CurrentApplicationID | uint64 | v2 | ID of current application executing. Application mode only. |
| 9 | CreatorAddress | address | v3 | Address of the creator of the current application. Application mode only. |
-
## gtxn
-- Syntax: `gtxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gtxn T F` where T: transaction group index, F: [txn Fields](#txn-fields)
- Bytecode: 0x33 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the current group
@@ -430,35 +430,36 @@ for notes on transaction fields available, see `txn`. If this transaction is _i_
## txna
-- Syntax: `txna F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `txna F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x36 {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F of the current transaction `txna` can be called using `txn` with 2 immediates.
+- Ith value of the array field F of the current transaction
+- `txna` can be called by using `txn` with 2 immediates.
- Availability: v2
-### txna
+### txna Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 26 | ApplicationArgs | []byte | v2 | Arguments passed to the application in the ApplicationCall transaction |
| 28 | Accounts | address | v2 | Accounts listed in the ApplicationCall transaction |
| 48 | Assets | uint64 | v3 | Foreign Assets listed in the ApplicationCall transaction |
| 50 | Applications | uint64 | v3 | Foreign Apps listed in the ApplicationCall transaction |
-
## gtxna
-- Syntax: `gtxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x37 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F from the Tth transaction in the current group `gtxna` can be called using `gtxn` with 3 immediates.
+- Ith value of the array field F from the Tth transaction in the current group
+- `gtxna` can be called by using `gtxn` with 3 immediates.
- Availability: v2
## gtxns
-- Syntax: `gtxns F` where F: [txn](#field-group-txn)
+- Syntax: `gtxns F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x38 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of the Ath transaction in the current group
@@ -468,10 +469,11 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
## gtxnsa
-- Syntax: `gtxnsa F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxnsa F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x39 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
-- Ith value of the array field F from the Ath transaction in the current group `gtxnsa` can be called using `gtxns` with 2 immediates.
+- Ith value of the array field F from the Ath transaction in the current group
+- `gtxnsa` can be called by using `gtxns` with 2 immediates.
- Availability: v3
## gload
@@ -763,40 +765,35 @@ Deleting a key which is already absent has no effect on the application global s
## asset_holding_get
-- Syntax: `asset_holding_get F` where F: [asset_holding](#field-group-asset_holding)
+- Syntax: `asset_holding_get F` where F: [asset_holding Fields](#asset_holding-fields)
- Bytecode: 0x70 {uint8}
- Stack: ..., A, B: uint64 → ..., X: any, Y: bool
- X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0
- Availability: v2
- Mode: Application
-### asset_holding
-
-Fields
+### asset_holding Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetBalance | uint64 | Amount of the asset unit held by this account |
| 1 | AssetFrozen | bool | Is the asset frozen or not |
-
params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## asset_params_get
-- Syntax: `asset_params_get F` where F: [asset_params](#field-group-asset_params)
+- Syntax: `asset_params_get F` where F: [asset_params Fields](#asset_params-fields)
- Bytecode: 0x71 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from asset A. Y is 1 if A exists, else 0
- Availability: v2
- Mode: Application
-### asset_params
+### asset_params Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetTotal | uint64 | Total number of units of this asset |
| 1 | AssetDecimals | uint64 | See AssetParams.Decimals |
| 2 | AssetDefaultFrozen | bool | Frozen by default or not |
@@ -809,7 +806,6 @@ Fields
| 9 | AssetFreeze | address | Freeze address |
| 10 | AssetClawback | address | Clawback address |
-
params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## min_balance
diff --git a/data/transactions/logic/TEAL_opcodes_v5.md b/data/transactions/logic/TEAL_opcodes_v5.md
index 92f52f59a2..4d57f30520 100644
--- a/data/transactions/logic/TEAL_opcodes_v5.md
+++ b/data/transactions/logic/TEAL_opcodes_v5.md
@@ -1,7 +1,11 @@
-# v5 Opcodes
-Ops have a 'cost' of 1 unless otherwise specified.
+# Version 5 Opcodes
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
## err
@@ -41,27 +45,24 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte
## ecdsa_verify
-- Syntax: `ecdsa_verify V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_verify V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x05 {uint8}
- Stack: ..., A: [32]byte, B: [32]byte, C: [32]byte, D: [32]byte, E: [32]byte → ..., bool
- for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1}
- **Cost**: Secp256k1=1700
- Availability: v5
-### ECDSA
+### ECDSA Curves
-Curves
-
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | Secp256k1 | secp256k1 curve, used in Bitcoin |
-
The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.
## ecdsa_pk_decompress
-- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x06 {uint8}
- Stack: ..., A: [33]byte → ..., X: [32]byte, Y: [32]byte
- decompress pubkey A into components X, Y
@@ -72,7 +73,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top
## ecdsa_pk_recover
-- Syntax: `ecdsa_pk_recover V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_recover V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x07 {uint8}
- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: [32]byte, Y: [32]byte
- for (data A, recovery id B, signature C, D) recover a public key
@@ -356,17 +357,17 @@ The notation J,K indicates that two uint64 values J and K are interpreted as a u
## txn
-- Syntax: `txn F` where F: [txn](#field-group-txn)
+- Syntax: `txn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x31 {uint8}
- Stack: ... → ..., any
- field F of current transaction
-### txn
+### txn Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | Sender | address | | 32 byte address |
| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
@@ -424,20 +425,17 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 60 | CreatedAssetID | uint64 | v5 | Asset ID allocated by the creation of an ASA (only with `itxn` in v5). Application mode only |
| 61 | CreatedApplicationID | uint64 | v5 | ApplicationID allocated by the creation of an application (only with `itxn` in v5). Application mode only |
-
## global
-- Syntax: `global F` where F: [global](#field-group-global)
+- Syntax: `global F` where F: [global Fields](#global-fields)
- Bytecode: 0x32 {uint8}
- Stack: ... → ..., any
- global field F
-### global
-
-Fields
+### global Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | MinTxnFee | uint64 | | microalgos |
| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
@@ -451,10 +449,9 @@ Fields
| 10 | CurrentApplicationAddress | address | v5 | Address that the current application controls. Application mode only. |
| 11 | GroupID | [32]byte | v5 | ID of the transaction group. 32 zero bytes if the transaction is not part of a group. |
-
## gtxn
-- Syntax: `gtxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gtxn T F` where T: transaction group index, F: [txn Fields](#txn-fields)
- Bytecode: 0x33 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the current group
@@ -477,36 +474,37 @@ for notes on transaction fields available, see `txn`. If this transaction is _i_
## txna
-- Syntax: `txna F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `txna F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x36 {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F of the current transaction `txna` can be called using `txn` with 2 immediates.
+- Ith value of the array field F of the current transaction
+- `txna` can be called by using `txn` with 2 immediates.
- Availability: v2
-### txna
+### txna Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 26 | ApplicationArgs | []byte | v2 | Arguments passed to the application in the ApplicationCall transaction |
| 28 | Accounts | address | v2 | Accounts listed in the ApplicationCall transaction |
| 48 | Assets | uint64 | v3 | Foreign Assets listed in the ApplicationCall transaction |
| 50 | Applications | uint64 | v3 | Foreign Apps listed in the ApplicationCall transaction |
| 58 | Logs | []byte | v5 | Log messages emitted by an application call (only with `itxn` in v5). Application mode only |
-
## gtxna
-- Syntax: `gtxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x37 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F from the Tth transaction in the current group `gtxna` can be called using `gtxn` with 3 immediates.
+- Ith value of the array field F from the Tth transaction in the current group
+- `gtxna` can be called by using `gtxn` with 3 immediates.
- Availability: v2
## gtxns
-- Syntax: `gtxns F` where F: [txn](#field-group-txn)
+- Syntax: `gtxns F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x38 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of the Ath transaction in the current group
@@ -516,10 +514,11 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
## gtxnsa
-- Syntax: `gtxnsa F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxnsa F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x39 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
-- Ith value of the array field F from the Ath transaction in the current group `gtxnsa` can be called using `gtxns` with 2 immediates.
+- Ith value of the array field F from the Ath transaction in the current group
+- `gtxnsa` can be called by using `gtxns` with 2 immediates.
- Availability: v3
## gload
@@ -749,7 +748,8 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Bytecode: 0x58
- Stack: ..., A: []byte, B: uint64, C: uint64 → ..., []byte
-- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails `extract3` can be called using `extract` with no immediates.
+- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails
+- `extract3` can be called by using `extract` with no immediates.
- Availability: v5
## extract_uint16
@@ -877,40 +877,35 @@ Deleting a key which is already absent has no effect on the application global s
## asset_holding_get
-- Syntax: `asset_holding_get F` where F: [asset_holding](#field-group-asset_holding)
+- Syntax: `asset_holding_get F` where F: [asset_holding Fields](#asset_holding-fields)
- Bytecode: 0x70 {uint8}
- Stack: ..., A, B: uint64 → ..., X: any, Y: bool
- X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0
- Availability: v2
- Mode: Application
-### asset_holding
-
-Fields
+### asset_holding Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetBalance | uint64 | Amount of the asset unit held by this account |
| 1 | AssetFrozen | bool | Is the asset frozen or not |
-
params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## asset_params_get
-- Syntax: `asset_params_get F` where F: [asset_params](#field-group-asset_params)
+- Syntax: `asset_params_get F` where F: [asset_params Fields](#asset_params-fields)
- Bytecode: 0x71 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from asset A. Y is 1 if A exists, else 0
- Availability: v2
- Mode: Application
-### asset_params
-
-Fields
+### asset_params Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AssetTotal | uint64 | | Total number of units of this asset |
| 1 | AssetDecimals | uint64 | | See AssetParams.Decimals |
| 2 | AssetDefaultFrozen | bool | | Frozen by default or not |
@@ -924,24 +919,21 @@ Fields
| 10 | AssetClawback | address | | Clawback address |
| 11 | AssetCreator | address | v5 | Creator address |
-
params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## app_params_get
-- Syntax: `app_params_get F` where F: [app_params](#field-group-app_params)
+- Syntax: `app_params_get F` where F: [app_params Fields](#app_params-fields)
- Bytecode: 0x72 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from app A. Y is 1 if A exists, else 0
- Availability: v5
- Mode: Application
-### app_params
-
-Fields
+### app_params Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AppApprovalProgram | []byte | Bytecode of Approval Program |
| 1 | AppClearStateProgram | []byte | Bytecode of Clear State Program |
| 2 | AppGlobalNumUint | uint64 | Number of uint64 values allowed in Global State |
@@ -952,7 +944,6 @@ Fields
| 7 | AppCreator | address | Creator address |
| 8 | AppAddress | address | Address for which this application has authority |
-
params: Txn.ForeignApps offset or an _available_ app id. Return: did_exist flag (1 if the application existed and 0 otherwise), value.
## min_balance
@@ -1193,7 +1184,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
## itxn_field
-- Syntax: `itxn_field F` where F: [txn](#field-group-txn)
+- Syntax: `itxn_field F` where F: [txn](#txn)
- Bytecode: 0xb2 {uint8}
- Stack: ..., A → ...
- set field F of the current inner transaction to A
@@ -1214,7 +1205,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
## itxn
-- Syntax: `itxn F` where F: [txn](#field-group-txn)
+- Syntax: `itxn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0xb4 {uint8}
- Stack: ... → ..., any
- field F of the last inner transaction
@@ -1223,7 +1214,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
## itxna
-- Syntax: `itxna F I` where F: [txna](#field-group-txna), I: a transaction field array index
+- Syntax: `itxna F I` where F: [txna Fields](#txna-fields), I: a transaction field array index
- Bytecode: 0xb5 {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F of the last inner transaction
@@ -1232,7 +1223,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
## txnas
-- Syntax: `txnas F` where F: [txna](#field-group-txna)
+- Syntax: `txnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc0 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the current transaction
@@ -1240,7 +1231,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
## gtxnas
-- Syntax: `gtxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gtxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc1 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the current group
@@ -1248,7 +1239,7 @@ bitlen interprets arrays as big-endian integers, unlike setbit/getbit
## gtxnsas
-- Syntax: `gtxnsas F` where F: [txna](#field-group-txna)
+- Syntax: `gtxnsas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc2 {uint8}
- Stack: ..., A: uint64, B: uint64 → ..., any
- Bth value of the array field F from the Ath transaction in the current group
diff --git a/data/transactions/logic/TEAL_opcodes_v6.md b/data/transactions/logic/TEAL_opcodes_v6.md
index 6621c3c84a..43fd1b9aa2 100644
--- a/data/transactions/logic/TEAL_opcodes_v6.md
+++ b/data/transactions/logic/TEAL_opcodes_v6.md
@@ -1,7 +1,11 @@
-# v6 Opcodes
-Ops have a 'cost' of 1 unless otherwise specified.
+# Version 6 Opcodes
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
## err
@@ -41,27 +45,24 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte
## ecdsa_verify
-- Syntax: `ecdsa_verify V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_verify V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x05 {uint8}
- Stack: ..., A: [32]byte, B: [32]byte, C: [32]byte, D: [32]byte, E: [32]byte → ..., bool
- for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1}
- **Cost**: Secp256k1=1700
- Availability: v5
-### ECDSA
+### ECDSA Curves
-Curves
-
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | Secp256k1 | secp256k1 curve, used in Bitcoin |
-
The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.
## ecdsa_pk_decompress
-- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x06 {uint8}
- Stack: ..., A: [33]byte → ..., X: [32]byte, Y: [32]byte
- decompress pubkey A into components X, Y
@@ -72,7 +73,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top
## ecdsa_pk_recover
-- Syntax: `ecdsa_pk_recover V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_recover V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x07 {uint8}
- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: [32]byte, Y: [32]byte
- for (data A, recovery id B, signature C, D) recover a public key
@@ -356,17 +357,17 @@ The notation J,K indicates that two uint64 values J and K are interpreted as a u
## txn
-- Syntax: `txn F` where F: [txn](#field-group-txn)
+- Syntax: `txn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x31 {uint8}
- Stack: ... → ..., any
- field F of current transaction
-### txn
+### txn Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | Sender | address | | 32 byte address |
| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
@@ -426,20 +427,17 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 62 | LastLog | []byte | v6 | The last message emitted. Empty bytes if none were emitted. Application mode only |
| 63 | StateProofPK | [64]byte | v6 | State proof public key |
-
## global
-- Syntax: `global F` where F: [global](#field-group-global)
+- Syntax: `global F` where F: [global Fields](#global-fields)
- Bytecode: 0x32 {uint8}
- Stack: ... → ..., any
- global field F
-### global
-
-Fields
+### global Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | MinTxnFee | uint64 | | microalgos |
| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
@@ -456,10 +454,9 @@ Fields
| 13 | CallerApplicationID | uint64 | v6 | The application ID of the application that called this application. 0 if this application is at the top-level. Application mode only. |
| 14 | CallerApplicationAddress | address | v6 | The application address of the application that called this application. ZeroAddress if this application is at the top-level. Application mode only. |
-
## gtxn
-- Syntax: `gtxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gtxn T F` where T: transaction group index, F: [txn Fields](#txn-fields)
- Bytecode: 0x33 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the current group
@@ -482,36 +479,37 @@ for notes on transaction fields available, see `txn`. If this transaction is _i_
## txna
-- Syntax: `txna F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `txna F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x36 {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F of the current transaction `txna` can be called using `txn` with 2 immediates.
+- Ith value of the array field F of the current transaction
+- `txna` can be called by using `txn` with 2 immediates.
- Availability: v2
-### txna
+### txna Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 26 | ApplicationArgs | []byte | v2 | Arguments passed to the application in the ApplicationCall transaction |
| 28 | Accounts | address | v2 | Accounts listed in the ApplicationCall transaction |
| 48 | Assets | uint64 | v3 | Foreign Assets listed in the ApplicationCall transaction |
| 50 | Applications | uint64 | v3 | Foreign Apps listed in the ApplicationCall transaction |
| 58 | Logs | []byte | v5 | Log messages emitted by an application call (only with `itxn` in v5). Application mode only |
-
## gtxna
-- Syntax: `gtxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x37 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F from the Tth transaction in the current group `gtxna` can be called using `gtxn` with 3 immediates.
+- Ith value of the array field F from the Tth transaction in the current group
+- `gtxna` can be called by using `gtxn` with 3 immediates.
- Availability: v2
## gtxns
-- Syntax: `gtxns F` where F: [txn](#field-group-txn)
+- Syntax: `gtxns F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x38 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of the Ath transaction in the current group
@@ -521,10 +519,11 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
## gtxnsa
-- Syntax: `gtxnsa F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxnsa F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x39 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
-- Ith value of the array field F from the Ath transaction in the current group `gtxnsa` can be called using `gtxns` with 2 immediates.
+- Ith value of the array field F from the Ath transaction in the current group
+- `gtxnsa` can be called by using `gtxns` with 2 immediates.
- Availability: v3
## gload
@@ -754,7 +753,8 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Bytecode: 0x58
- Stack: ..., A: []byte, B: uint64, C: uint64 → ..., []byte
-- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails `extract3` can be called using `extract` with no immediates.
+- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails
+- `extract3` can be called by using `extract` with no immediates.
- Availability: v5
## extract_uint16
@@ -882,40 +882,35 @@ Deleting a key which is already absent has no effect on the application global s
## asset_holding_get
-- Syntax: `asset_holding_get F` where F: [asset_holding](#field-group-asset_holding)
+- Syntax: `asset_holding_get F` where F: [asset_holding Fields](#asset_holding-fields)
- Bytecode: 0x70 {uint8}
- Stack: ..., A, B: uint64 → ..., X: any, Y: bool
- X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0
- Availability: v2
- Mode: Application
-### asset_holding
+### asset_holding Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetBalance | uint64 | Amount of the asset unit held by this account |
| 1 | AssetFrozen | bool | Is the asset frozen or not |
-
params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## asset_params_get
-- Syntax: `asset_params_get F` where F: [asset_params](#field-group-asset_params)
+- Syntax: `asset_params_get F` where F: [asset_params Fields](#asset_params-fields)
- Bytecode: 0x71 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from asset A. Y is 1 if A exists, else 0
- Availability: v2
- Mode: Application
-### asset_params
+### asset_params Fields
-Fields
-
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AssetTotal | uint64 | | Total number of units of this asset |
| 1 | AssetDecimals | uint64 | | See AssetParams.Decimals |
| 2 | AssetDefaultFrozen | bool | | Frozen by default or not |
@@ -929,24 +924,21 @@ Fields
| 10 | AssetClawback | address | | Clawback address |
| 11 | AssetCreator | address | v5 | Creator address |
-
params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## app_params_get
-- Syntax: `app_params_get F` where F: [app_params](#field-group-app_params)
+- Syntax: `app_params_get F` where F: [app_params Fields](#app_params-fields)
- Bytecode: 0x72 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from app A. Y is 1 if A exists, else 0
- Availability: v5
- Mode: Application
-### app_params
+### app_params Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AppApprovalProgram | []byte | Bytecode of Approval Program |
| 1 | AppClearStateProgram | []byte | Bytecode of Clear State Program |
| 2 | AppGlobalNumUint | uint64 | Number of uint64 values allowed in Global State |
@@ -957,29 +949,25 @@ Fields
| 7 | AppCreator | address | Creator address |
| 8 | AppAddress | address | Address for which this application has authority |
-
params: Txn.ForeignApps offset or an _available_ app id. Return: did_exist flag (1 if the application existed and 0 otherwise), value.
## acct_params_get
-- Syntax: `acct_params_get F` where F: [acct_params](#field-group-acct_params)
+- Syntax: `acct_params_get F` where F: [acct_params Fields](#acct_params-fields)
- Bytecode: 0x73 {uint8}
- Stack: ..., A → ..., X: any, Y: bool
- X is field F from account A. Y is 1 if A owns positive algos, else 0
- Availability: v6
- Mode: Application
-### acct_params
+### acct_params Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AcctBalance | uint64 | Account balance in microalgos |
| 1 | AcctMinBalance | uint64 | Minimum required balance for account, in microalgos |
| 2 | AcctAuthAddr | address | Address the account is rekeyed to. |
-
## min_balance
- Bytecode: 0x78
@@ -1235,7 +1223,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn_field
-- Syntax: `itxn_field F` where F: [txn](#field-group-txn)
+- Syntax: `itxn_field F` where F: [txn](#txn)
- Bytecode: 0xb2 {uint8}
- Stack: ..., A → ...
- set field F of the current inner transaction to A
@@ -1256,7 +1244,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn
-- Syntax: `itxn F` where F: [txn](#field-group-txn)
+- Syntax: `itxn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0xb4 {uint8}
- Stack: ... → ..., any
- field F of the last inner transaction
@@ -1265,7 +1253,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxna
-- Syntax: `itxna F I` where F: [txna](#field-group-txna), I: a transaction field array index
+- Syntax: `itxna F I` where F: [txna Fields](#txna-fields), I: a transaction field array index
- Bytecode: 0xb5 {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F of the last inner transaction
@@ -1284,7 +1272,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxn
-- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#txn)
- Bytecode: 0xb7 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the last inner group submitted
@@ -1293,7 +1281,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxna
-- Syntax: `gitxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gitxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0xb8 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F from the Tth transaction in the last inner group submitted
@@ -1302,7 +1290,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## txnas
-- Syntax: `txnas F` where F: [txna](#field-group-txna)
+- Syntax: `txnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc0 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the current transaction
@@ -1310,7 +1298,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gtxnas
-- Syntax: `gtxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gtxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc1 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the current group
@@ -1318,7 +1306,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gtxnsas
-- Syntax: `gtxnsas F` where F: [txna](#field-group-txna)
+- Syntax: `gtxnsas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc2 {uint8}
- Stack: ..., A: uint64, B: uint64 → ..., any
- Bth value of the array field F from the Ath transaction in the current group
@@ -1342,7 +1330,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxnas
-- Syntax: `itxnas F` where F: [txna](#field-group-txna)
+- Syntax: `itxnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc5 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the last inner transaction
@@ -1351,7 +1339,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxnas
-- Syntax: `gitxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gitxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc6 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the last inner group submitted
diff --git a/data/transactions/logic/TEAL_opcodes_v7.md b/data/transactions/logic/TEAL_opcodes_v7.md
index 46752e9121..5eee8e4940 100644
--- a/data/transactions/logic/TEAL_opcodes_v7.md
+++ b/data/transactions/logic/TEAL_opcodes_v7.md
@@ -1,7 +1,11 @@
-# v7 Opcodes
-Ops have a 'cost' of 1 unless otherwise specified.
+# Version 7 Opcodes
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
## err
@@ -41,28 +45,25 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte
## ecdsa_verify
-- Syntax: `ecdsa_verify V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_verify V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x05 {uint8}
- Stack: ..., A: [32]byte, B: [32]byte, C: [32]byte, D: [32]byte, E: [32]byte → ..., bool
- for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1}
- **Cost**: Secp256k1=1700; Secp256r1=2500
- Availability: v5
-### ECDSA
-
-Curves
+### ECDSA Curves
-| Index | Name | In | Notes |
-| - | ------ | - | --------- |
+| INDEX | NAME | IN | NOTES |
+| :-: | :------ |:-:| :--------- |
| 0 | Secp256k1 | | secp256k1 curve, used in Bitcoin |
| 1 | Secp256r1 | v7 | secp256r1 curve, NIST standard |
-
The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.
## ecdsa_pk_decompress
-- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x06 {uint8}
- Stack: ..., A: [33]byte → ..., X: [32]byte, Y: [32]byte
- decompress pubkey A into components X, Y
@@ -73,7 +74,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top
## ecdsa_pk_recover
-- Syntax: `ecdsa_pk_recover V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_recover V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x07 {uint8}
- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: [32]byte, Y: [32]byte
- for (data A, recovery id B, signature C, D) recover a public key
@@ -357,17 +358,17 @@ The notation J,K indicates that two uint64 values J and K are interpreted as a u
## txn
-- Syntax: `txn F` where F: [txn](#field-group-txn)
+- Syntax: `txn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x31 {uint8}
- Stack: ... → ..., any
- field F of current transaction
-### txn
+### txn Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | Sender | address | | 32 byte address |
| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
@@ -430,20 +431,17 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 65 | NumApprovalProgramPages | uint64 | v7 | Number of Approval Program pages |
| 67 | NumClearStateProgramPages | uint64 | v7 | Number of ClearState Program pages |
-
## global
-- Syntax: `global F` where F: [global](#field-group-global)
+- Syntax: `global F` where F: [global Fields](#global-fields)
- Bytecode: 0x32 {uint8}
- Stack: ... → ..., any
- global field F
-### global
-
-Fields
+### global Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | MinTxnFee | uint64 | | microalgos |
| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
@@ -460,10 +458,9 @@ Fields
| 13 | CallerApplicationID | uint64 | v6 | The application ID of the application that called this application. 0 if this application is at the top-level. Application mode only. |
| 14 | CallerApplicationAddress | address | v6 | The application address of the application that called this application. ZeroAddress if this application is at the top-level. Application mode only. |
-
## gtxn
-- Syntax: `gtxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gtxn T F` where T: transaction group index, F: [txn Fields](#txn-fields)
- Bytecode: 0x33 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the current group
@@ -486,18 +483,19 @@ for notes on transaction fields available, see `txn`. If this transaction is _i_
## txna
-- Syntax: `txna F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `txna F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x36 {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F of the current transaction `txna` can be called using `txn` with 2 immediates.
+- Ith value of the array field F of the current transaction
+- `txna` can be called by using `txn` with 2 immediates.
- Availability: v2
-### txna
+### txna Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 26 | ApplicationArgs | []byte | v2 | Arguments passed to the application in the ApplicationCall transaction |
| 28 | Accounts | address | v2 | Accounts listed in the ApplicationCall transaction |
| 48 | Assets | uint64 | v3 | Foreign Assets listed in the ApplicationCall transaction |
@@ -506,18 +504,18 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 64 | ApprovalProgramPages | []byte | v7 | Approval Program as an array of pages |
| 66 | ClearStateProgramPages | []byte | v7 | ClearState Program as an array of pages |
-
## gtxna
-- Syntax: `gtxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x37 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F from the Tth transaction in the current group `gtxna` can be called using `gtxn` with 3 immediates.
+- Ith value of the array field F from the Tth transaction in the current group
+- `gtxna` can be called by using `gtxn` with 3 immediates.
- Availability: v2
## gtxns
-- Syntax: `gtxns F` where F: [txn](#field-group-txn)
+- Syntax: `gtxns F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x38 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of the Ath transaction in the current group
@@ -527,10 +525,11 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
## gtxnsa
-- Syntax: `gtxnsa F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxnsa F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x39 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
-- Ith value of the array field F from the Ath transaction in the current group `gtxnsa` can be called using `gtxns` with 2 immediates.
+- Ith value of the array field F from the Ath transaction in the current group
+- `gtxnsa` can be called by using `gtxns` with 2 immediates.
- Availability: v3
## gload
@@ -760,7 +759,8 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Bytecode: 0x58
- Stack: ..., A: []byte, B: uint64, C: uint64 → ..., []byte
-- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails `extract3` can be called using `extract` with no immediates.
+- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails
+- `extract3` can be called by using `extract` with no immediates.
- Availability: v5
## extract_uint16
@@ -789,60 +789,56 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Syntax: `replace2 S` where S: start position
- Bytecode: 0x5c {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
-- Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A) `replace2` can be called using `replace` with 1 immediate.
+- Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)
+- `replace2` can be called by using `replace` with 1 immediate.
- Availability: v7
## replace3
- Bytecode: 0x5d
- Stack: ..., A: []byte, B: uint64, C: []byte → ..., []byte
-- Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A) `replace3` can be called using `replace` with no immediates.
+- Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)
+- `replace3` can be called by using `replace` with no immediates.
- Availability: v7
## base64_decode
-- Syntax: `base64_decode E` where E: [base64](#field-group-base64)
+- Syntax: `base64_decode E` where E: [base64 Encodings](#base64-encodings)
- Bytecode: 0x5e {uint8}
- Stack: ..., A: []byte → ..., []byte
- decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E
- **Cost**: 1 + 1 per 16 bytes of A
- Availability: v7
-### base64
-
-Encodings
+### base64 Encodings
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | URLEncoding | |
| 1 | StdEncoding | |
-
-*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.
+_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.
Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\n` and `\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\r`, or `\n`.
## json_ref
-- Syntax: `json_ref R` where R: [json_ref](#field-group-json_ref)
+- Syntax: `json_ref R` where R: [json_ref Types](#json_ref-types)
- Bytecode: 0x5f {uint8}
- Stack: ..., A: []byte, B: []byte → ..., any
- key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A
- **Cost**: 25 + 2 per 7 bytes of A
- Availability: v7
-### json_ref
-
-Types
+### json_ref Types
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | JSONString | []byte | |
| 1 | JSONUint64 | uint64 | |
| 2 | JSONObject | []byte | |
-
-*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.
+_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.
Almost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.
@@ -950,40 +946,35 @@ Deleting a key which is already absent has no effect on the application global s
## asset_holding_get
-- Syntax: `asset_holding_get F` where F: [asset_holding](#field-group-asset_holding)
+- Syntax: `asset_holding_get F` where F: [asset_holding Fields](#asset_holding-fields)
- Bytecode: 0x70 {uint8}
- Stack: ..., A, B: uint64 → ..., X: any, Y: bool
- X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0
- Availability: v2
- Mode: Application
-### asset_holding
+### asset_holding Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetBalance | uint64 | Amount of the asset unit held by this account |
| 1 | AssetFrozen | bool | Is the asset frozen or not |
-
params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## asset_params_get
-- Syntax: `asset_params_get F` where F: [asset_params](#field-group-asset_params)
+- Syntax: `asset_params_get F` where F: [asset_params Fields](#asset_params-fields)
- Bytecode: 0x71 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from asset A. Y is 1 if A exists, else 0
- Availability: v2
- Mode: Application
-### asset_params
-
-Fields
+### asset_params Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AssetTotal | uint64 | | Total number of units of this asset |
| 1 | AssetDecimals | uint64 | | See AssetParams.Decimals |
| 2 | AssetDefaultFrozen | bool | | Frozen by default or not |
@@ -997,24 +988,21 @@ Fields
| 10 | AssetClawback | address | | Clawback address |
| 11 | AssetCreator | address | v5 | Creator address |
-
params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## app_params_get
-- Syntax: `app_params_get F` where F: [app_params](#field-group-app_params)
+- Syntax: `app_params_get F` where F: [app_params Fields](#app_params-fields)
- Bytecode: 0x72 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from app A. Y is 1 if A exists, else 0
- Availability: v5
- Mode: Application
-### app_params
-
-Fields
+### app_params Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AppApprovalProgram | []byte | Bytecode of Approval Program |
| 1 | AppClearStateProgram | []byte | Bytecode of Clear State Program |
| 2 | AppGlobalNumUint | uint64 | Number of uint64 values allowed in Global State |
@@ -1025,29 +1013,25 @@ Fields
| 7 | AppCreator | address | Creator address |
| 8 | AppAddress | address | Address for which this application has authority |
-
params: Txn.ForeignApps offset or an _available_ app id. Return: did_exist flag (1 if the application existed and 0 otherwise), value.
## acct_params_get
-- Syntax: `acct_params_get F` where F: [acct_params](#field-group-acct_params)
+- Syntax: `acct_params_get F` where F: [acct_params Fields](#acct_params-fields)
- Bytecode: 0x73 {uint8}
- Stack: ..., A → ..., X: any, Y: bool
- X is field F from account A. Y is 1 if A owns positive algos, else 0
- Availability: v6
- Mode: Application
-### acct_params
+### acct_params Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AcctBalance | uint64 | Account balance in microalgos |
| 1 | AcctMinBalance | uint64 | Minimum required balance for account, in microalgos |
| 2 | AcctAuthAddr | address | Address the account is rekeyed to. |
-
## min_balance
- Bytecode: 0x78
@@ -1319,7 +1303,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn_field
-- Syntax: `itxn_field F` where F: [txn](#field-group-txn)
+- Syntax: `itxn_field F` where F: [txn](#txn)
- Bytecode: 0xb2 {uint8}
- Stack: ..., A → ...
- set field F of the current inner transaction to A
@@ -1340,7 +1324,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn
-- Syntax: `itxn F` where F: [txn](#field-group-txn)
+- Syntax: `itxn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0xb4 {uint8}
- Stack: ... → ..., any
- field F of the last inner transaction
@@ -1349,7 +1333,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxna
-- Syntax: `itxna F I` where F: [txna](#field-group-txna), I: a transaction field array index
+- Syntax: `itxna F I` where F: [txna Fields](#txna-fields), I: a transaction field array index
- Bytecode: 0xb5 {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F of the last inner transaction
@@ -1368,7 +1352,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxn
-- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#txn)
- Bytecode: 0xb7 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the last inner group submitted
@@ -1377,7 +1361,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxna
-- Syntax: `gitxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gitxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0xb8 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F from the Tth transaction in the last inner group submitted
@@ -1386,7 +1370,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## txnas
-- Syntax: `txnas F` where F: [txna](#field-group-txna)
+- Syntax: `txnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc0 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the current transaction
@@ -1394,7 +1378,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gtxnas
-- Syntax: `gtxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gtxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc1 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the current group
@@ -1402,7 +1386,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gtxnsas
-- Syntax: `gtxnsas F` where F: [txna](#field-group-txna)
+- Syntax: `gtxnsas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc2 {uint8}
- Stack: ..., A: uint64, B: uint64 → ..., any
- Bth value of the array field F from the Ath transaction in the current group
@@ -1426,7 +1410,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxnas
-- Syntax: `itxnas F` where F: [txna](#field-group-txna)
+- Syntax: `itxnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc5 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the last inner transaction
@@ -1435,7 +1419,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxnas
-- Syntax: `gitxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gitxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc6 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the last inner group submitted
@@ -1444,38 +1428,32 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## vrf_verify
-- Syntax: `vrf_verify S` where S: [vrf_verify](#field-group-vrf_verify)
+- Syntax: `vrf_verify S` where S: [vrf_verify Standards](#vrf_verify-standards)
- Bytecode: 0xd0 {uint8}
- Stack: ..., A: []byte, B: [80]byte, C: [32]byte → ..., X: [64]byte, Y: bool
- Verify the proof B of message A against pubkey C. Returns vrf output and verification flag.
- **Cost**: 5700
- Availability: v7
-### vrf_verify
-
-Standards
+### vrf_verify Standards
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | VrfAlgorand | |
-
`VrfAlgorand` is the VRF used in Algorand. It is ECVRF-ED25519-SHA512-Elligator2, specified in the IETF internet draft [draft-irtf-cfrg-vrf-03](https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/03/).
## block
-- Syntax: `block F` where F: [block](#field-group-block)
+- Syntax: `block F` where F: [block Fields](#block-fields)
- Bytecode: 0xd1 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of block A. Fail unless A falls between txn.LastValid-1002 and txn.FirstValid (exclusive)
- Availability: v7
-### block
-
-Fields
+### block Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | BlkSeed | [32]byte | |
| 1 | BlkTimestamp | uint64 | |
-
diff --git a/data/transactions/logic/TEAL_opcodes_v8.md b/data/transactions/logic/TEAL_opcodes_v8.md
index 2c94de5a56..7f49549189 100644
--- a/data/transactions/logic/TEAL_opcodes_v8.md
+++ b/data/transactions/logic/TEAL_opcodes_v8.md
@@ -1,7 +1,11 @@
-# v8 Opcodes
-Ops have a 'cost' of 1 unless otherwise specified.
+# Version 8 Opcodes
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
## err
@@ -41,28 +45,25 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte
## ecdsa_verify
-- Syntax: `ecdsa_verify V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_verify V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x05 {uint8}
- Stack: ..., A: [32]byte, B: [32]byte, C: [32]byte, D: [32]byte, E: [32]byte → ..., bool
- for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1}
- **Cost**: Secp256k1=1700; Secp256r1=2500
- Availability: v5
-### ECDSA
-
-Curves
+### ECDSA Curves
-| Index | Name | In | Notes |
-| - | ------ | - | --------- |
+| INDEX | NAME | IN | NOTES |
+| :-: | :------ |:-:| :--------- |
| 0 | Secp256k1 | | secp256k1 curve, used in Bitcoin |
| 1 | Secp256r1 | v7 | secp256r1 curve, NIST standard |
-
The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.
## ecdsa_pk_decompress
-- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x06 {uint8}
- Stack: ..., A: [33]byte → ..., X: [32]byte, Y: [32]byte
- decompress pubkey A into components X, Y
@@ -73,7 +74,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top
## ecdsa_pk_recover
-- Syntax: `ecdsa_pk_recover V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_recover V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x07 {uint8}
- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: [32]byte, Y: [32]byte
- for (data A, recovery id B, signature C, D) recover a public key
@@ -357,17 +358,17 @@ The notation J,K indicates that two uint64 values J and K are interpreted as a u
## txn
-- Syntax: `txn F` where F: [txn](#field-group-txn)
+- Syntax: `txn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x31 {uint8}
- Stack: ... → ..., any
- field F of current transaction
-### txn
+### txn Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | Sender | address | | 32 byte address |
| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
@@ -430,20 +431,17 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 65 | NumApprovalProgramPages | uint64 | v7 | Number of Approval Program pages |
| 67 | NumClearStateProgramPages | uint64 | v7 | Number of ClearState Program pages |
-
## global
-- Syntax: `global F` where F: [global](#field-group-global)
+- Syntax: `global F` where F: [global Fields](#global-fields)
- Bytecode: 0x32 {uint8}
- Stack: ... → ..., any
- global field F
-### global
-
-Fields
+### global Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | MinTxnFee | uint64 | | microalgos |
| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
@@ -460,10 +458,9 @@ Fields
| 13 | CallerApplicationID | uint64 | v6 | The application ID of the application that called this application. 0 if this application is at the top-level. Application mode only. |
| 14 | CallerApplicationAddress | address | v6 | The application address of the application that called this application. ZeroAddress if this application is at the top-level. Application mode only. |
-
## gtxn
-- Syntax: `gtxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gtxn T F` where T: transaction group index, F: [txn Fields](#txn-fields)
- Bytecode: 0x33 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the current group
@@ -486,18 +483,19 @@ for notes on transaction fields available, see `txn`. If this transaction is _i_
## txna
-- Syntax: `txna F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `txna F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x36 {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F of the current transaction `txna` can be called using `txn` with 2 immediates.
+- Ith value of the array field F of the current transaction
+- `txna` can be called by using `txn` with 2 immediates.
- Availability: v2
-### txna
+### txna Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 26 | ApplicationArgs | []byte | v2 | Arguments passed to the application in the ApplicationCall transaction |
| 28 | Accounts | address | v2 | Accounts listed in the ApplicationCall transaction |
| 48 | Assets | uint64 | v3 | Foreign Assets listed in the ApplicationCall transaction |
@@ -506,18 +504,18 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 64 | ApprovalProgramPages | []byte | v7 | Approval Program as an array of pages |
| 66 | ClearStateProgramPages | []byte | v7 | ClearState Program as an array of pages |
-
## gtxna
-- Syntax: `gtxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x37 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F from the Tth transaction in the current group `gtxna` can be called using `gtxn` with 3 immediates.
+- Ith value of the array field F from the Tth transaction in the current group
+- `gtxna` can be called by using `gtxn` with 3 immediates.
- Availability: v2
## gtxns
-- Syntax: `gtxns F` where F: [txn](#field-group-txn)
+- Syntax: `gtxns F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x38 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of the Ath transaction in the current group
@@ -527,10 +525,11 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
## gtxnsa
-- Syntax: `gtxnsa F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxnsa F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x39 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
-- Ith value of the array field F from the Ath transaction in the current group `gtxnsa` can be called using `gtxns` with 2 immediates.
+- Ith value of the array field F from the Ath transaction in the current group
+- `gtxnsa` can be called by using `gtxns` with 2 immediates.
- Availability: v3
## gload
@@ -784,7 +783,8 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Bytecode: 0x58
- Stack: ..., A: []byte, B: uint64, C: uint64 → ..., []byte
-- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails `extract3` can be called using `extract` with no immediates.
+- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails
+- `extract3` can be called by using `extract` with no immediates.
- Availability: v5
## extract_uint16
@@ -813,60 +813,56 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Syntax: `replace2 S` where S: start position
- Bytecode: 0x5c {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
-- Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A) `replace2` can be called using `replace` with 1 immediate.
+- Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)
+- `replace2` can be called by using `replace` with 1 immediate.
- Availability: v7
## replace3
- Bytecode: 0x5d
- Stack: ..., A: []byte, B: uint64, C: []byte → ..., []byte
-- Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A) `replace3` can be called using `replace` with no immediates.
+- Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)
+- `replace3` can be called by using `replace` with no immediates.
- Availability: v7
## base64_decode
-- Syntax: `base64_decode E` where E: [base64](#field-group-base64)
+- Syntax: `base64_decode E` where E: [base64 Encodings](#base64-encodings)
- Bytecode: 0x5e {uint8}
- Stack: ..., A: []byte → ..., []byte
- decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E
- **Cost**: 1 + 1 per 16 bytes of A
- Availability: v7
-### base64
-
-Encodings
+### base64 Encodings
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | URLEncoding | |
| 1 | StdEncoding | |
-
-*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.
+_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.
Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\n` and `\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\r`, or `\n`.
## json_ref
-- Syntax: `json_ref R` where R: [json_ref](#field-group-json_ref)
+- Syntax: `json_ref R` where R: [json_ref Types](#json_ref-types)
- Bytecode: 0x5f {uint8}
- Stack: ..., A: []byte, B: []byte → ..., any
- key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A
- **Cost**: 25 + 2 per 7 bytes of A
- Availability: v7
-### json_ref
-
-Types
+### json_ref Types
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | JSONString | []byte | |
| 1 | JSONUint64 | uint64 | |
| 2 | JSONObject | []byte | |
-
-*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.
+_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.
Almost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.
@@ -974,40 +970,35 @@ Deleting a key which is already absent has no effect on the application global s
## asset_holding_get
-- Syntax: `asset_holding_get F` where F: [asset_holding](#field-group-asset_holding)
+- Syntax: `asset_holding_get F` where F: [asset_holding Fields](#asset_holding-fields)
- Bytecode: 0x70 {uint8}
- Stack: ..., A, B: uint64 → ..., X: any, Y: bool
- X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0
- Availability: v2
- Mode: Application
-### asset_holding
+### asset_holding Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetBalance | uint64 | Amount of the asset unit held by this account |
| 1 | AssetFrozen | bool | Is the asset frozen or not |
-
params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## asset_params_get
-- Syntax: `asset_params_get F` where F: [asset_params](#field-group-asset_params)
+- Syntax: `asset_params_get F` where F: [asset_params Fields](#asset_params-fields)
- Bytecode: 0x71 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from asset A. Y is 1 if A exists, else 0
- Availability: v2
- Mode: Application
-### asset_params
-
-Fields
+### asset_params Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AssetTotal | uint64 | | Total number of units of this asset |
| 1 | AssetDecimals | uint64 | | See AssetParams.Decimals |
| 2 | AssetDefaultFrozen | bool | | Frozen by default or not |
@@ -1021,24 +1012,21 @@ Fields
| 10 | AssetClawback | address | | Clawback address |
| 11 | AssetCreator | address | v5 | Creator address |
-
params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## app_params_get
-- Syntax: `app_params_get F` where F: [app_params](#field-group-app_params)
+- Syntax: `app_params_get F` where F: [app_params Fields](#app_params-fields)
- Bytecode: 0x72 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from app A. Y is 1 if A exists, else 0
- Availability: v5
- Mode: Application
-### app_params
-
-Fields
+### app_params Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AppApprovalProgram | []byte | Bytecode of Approval Program |
| 1 | AppClearStateProgram | []byte | Bytecode of Clear State Program |
| 2 | AppGlobalNumUint | uint64 | Number of uint64 values allowed in Global State |
@@ -1049,24 +1037,21 @@ Fields
| 7 | AppCreator | address | Creator address |
| 8 | AppAddress | address | Address for which this application has authority |
-
params: Txn.ForeignApps offset or an _available_ app id. Return: did_exist flag (1 if the application existed and 0 otherwise), value.
## acct_params_get
-- Syntax: `acct_params_get F` where F: [acct_params](#field-group-acct_params)
+- Syntax: `acct_params_get F` where F: [acct_params Fields](#acct_params-fields)
- Bytecode: 0x73 {uint8}
- Stack: ..., A → ..., X: any, Y: bool
- X is field F from account A. Y is 1 if A owns positive algos, else 0
- Availability: v6
- Mode: Application
-### acct_params
+### acct_params Fields
-Fields
-
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AcctBalance | uint64 | | Account balance in microalgos |
| 1 | AcctMinBalance | uint64 | | Minimum required balance for account, in microalgos |
| 2 | AcctAuthAddr | address | | Address the account is rekeyed to. |
@@ -1080,7 +1065,6 @@ Fields
| 10 | AcctTotalBoxes | uint64 | v8 | The number of existing boxes created by this account's app. |
| 11 | AcctTotalBoxBytes | uint64 | v8 | The total number of bytes used by this account's app's box keys and values. |
-
## min_balance
- Bytecode: 0x78
@@ -1416,7 +1400,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn_field
-- Syntax: `itxn_field F` where F: [txn](#field-group-txn)
+- Syntax: `itxn_field F` where F: [txn](#txn)
- Bytecode: 0xb2 {uint8}
- Stack: ..., A → ...
- set field F of the current inner transaction to A
@@ -1437,7 +1421,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn
-- Syntax: `itxn F` where F: [txn](#field-group-txn)
+- Syntax: `itxn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0xb4 {uint8}
- Stack: ... → ..., any
- field F of the last inner transaction
@@ -1446,7 +1430,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxna
-- Syntax: `itxna F I` where F: [txna](#field-group-txna), I: a transaction field array index
+- Syntax: `itxna F I` where F: [txna Fields](#txna-fields), I: a transaction field array index
- Bytecode: 0xb5 {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F of the last inner transaction
@@ -1465,7 +1449,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxn
-- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#txn)
- Bytecode: 0xb7 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the last inner group submitted
@@ -1474,7 +1458,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxna
-- Syntax: `gitxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gitxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0xb8 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F from the Tth transaction in the last inner group submitted
@@ -1545,7 +1529,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## txnas
-- Syntax: `txnas F` where F: [txna](#field-group-txna)
+- Syntax: `txnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc0 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the current transaction
@@ -1553,7 +1537,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gtxnas
-- Syntax: `gtxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gtxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc1 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the current group
@@ -1561,7 +1545,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gtxnsas
-- Syntax: `gtxnsas F` where F: [txna](#field-group-txna)
+- Syntax: `gtxnsas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc2 {uint8}
- Stack: ..., A: uint64, B: uint64 → ..., any
- Bth value of the array field F from the Ath transaction in the current group
@@ -1585,7 +1569,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## itxnas
-- Syntax: `itxnas F` where F: [txna](#field-group-txna)
+- Syntax: `itxnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc5 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the last inner transaction
@@ -1594,7 +1578,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gitxnas
-- Syntax: `gitxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gitxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc6 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the last inner group submitted
@@ -1603,38 +1587,32 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## vrf_verify
-- Syntax: `vrf_verify S` where S: [vrf_verify](#field-group-vrf_verify)
+- Syntax: `vrf_verify S` where S: [vrf_verify Standards](#vrf_verify-standards)
- Bytecode: 0xd0 {uint8}
- Stack: ..., A: []byte, B: [80]byte, C: [32]byte → ..., X: [64]byte, Y: bool
- Verify the proof B of message A against pubkey C. Returns vrf output and verification flag.
- **Cost**: 5700
- Availability: v7
-### vrf_verify
-
-Standards
+### vrf_verify Standards
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | VrfAlgorand | |
-
`VrfAlgorand` is the VRF used in Algorand. It is ECVRF-ED25519-SHA512-Elligator2, specified in the IETF internet draft [draft-irtf-cfrg-vrf-03](https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/03/).
## block
-- Syntax: `block F` where F: [block](#field-group-block)
+- Syntax: `block F` where F: [block Fields](#block-fields)
- Bytecode: 0xd1 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of block A. Fail unless A falls between txn.LastValid-1002 and txn.FirstValid (exclusive)
- Availability: v7
-### block
-
-Fields
+### block Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | BlkSeed | [32]byte | |
| 1 | BlkTimestamp | uint64 | |
-
diff --git a/data/transactions/logic/TEAL_opcodes_v9.md b/data/transactions/logic/TEAL_opcodes_v9.md
index 68afbe47ee..ed5344ff82 100644
--- a/data/transactions/logic/TEAL_opcodes_v9.md
+++ b/data/transactions/logic/TEAL_opcodes_v9.md
@@ -1,7 +1,11 @@
-# v9 Opcodes
-Ops have a 'cost' of 1 unless otherwise specified.
+# Version 9 Opcodes
+Opcodes have a cost of 1 unless otherwise specified.
+
+
+
+
## err
@@ -41,28 +45,25 @@ The 32 byte public key is the last element on the stack, preceded by the 64 byte
## ecdsa_verify
-- Syntax: `ecdsa_verify V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_verify V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x05 {uint8}
- Stack: ..., A: [32]byte, B: [32]byte, C: [32]byte, D: [32]byte, E: [32]byte → ..., bool
- for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1}
- **Cost**: Secp256k1=1700; Secp256r1=2500
- Availability: v5
-### ECDSA
-
-Curves
+### ECDSA Curves
-| Index | Name | In | Notes |
-| - | ------ | - | --------- |
+| INDEX | NAME | IN | NOTES |
+| :-: | :------ |:-:| :--------- |
| 0 | Secp256k1 | | secp256k1 curve, used in Bitcoin |
| 1 | Secp256r1 | v7 | secp256r1 curve, NIST standard |
-
The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.
## ecdsa_pk_decompress
-- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_decompress V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x06 {uint8}
- Stack: ..., A: [33]byte → ..., X: [32]byte, Y: [32]byte
- decompress pubkey A into components X, Y
@@ -73,7 +74,7 @@ The 33 byte public key in a compressed form to be decompressed into X and Y (top
## ecdsa_pk_recover
-- Syntax: `ecdsa_pk_recover V` where V: [ECDSA](#field-group-ecdsa)
+- Syntax: `ecdsa_pk_recover V` where V: [ECDSA Curves](#ecdsa-curves)
- Bytecode: 0x07 {uint8}
- Stack: ..., A: [32]byte, B: uint64, C: [32]byte, D: [32]byte → ..., X: [32]byte, Y: [32]byte
- for (data A, recovery id B, signature C, D) recover a public key
@@ -357,17 +358,17 @@ The notation J,K indicates that two uint64 values J and K are interpreted as a u
## txn
-- Syntax: `txn F` where F: [txn](#field-group-txn)
+- Syntax: `txn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x31 {uint8}
- Stack: ... → ..., any
- field F of current transaction
-### txn
+### txn Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | Sender | address | | 32 byte address |
| 1 | Fee | uint64 | | microalgos |
| 2 | FirstValid | uint64 | | round number |
@@ -430,20 +431,17 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 65 | NumApprovalProgramPages | uint64 | v7 | Number of Approval Program pages |
| 67 | NumClearStateProgramPages | uint64 | v7 | Number of ClearState Program pages |
-
## global
-- Syntax: `global F` where F: [global](#field-group-global)
+- Syntax: `global F` where F: [global Fields](#global-fields)
- Bytecode: 0x32 {uint8}
- Stack: ... → ..., any
- global field F
-### global
-
-Fields
+### global Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | MinTxnFee | uint64 | | microalgos |
| 1 | MinBalance | uint64 | | microalgos |
| 2 | MaxTxnLife | uint64 | | rounds |
@@ -460,10 +458,9 @@ Fields
| 13 | CallerApplicationID | uint64 | v6 | The application ID of the application that called this application. 0 if this application is at the top-level. Application mode only. |
| 14 | CallerApplicationAddress | address | v6 | The application address of the application that called this application. ZeroAddress if this application is at the top-level. Application mode only. |
-
## gtxn
-- Syntax: `gtxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gtxn T F` where T: transaction group index, F: [txn Fields](#txn-fields)
- Bytecode: 0x33 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the current group
@@ -486,18 +483,19 @@ for notes on transaction fields available, see `txn`. If this transaction is _i_
## txna
-- Syntax: `txna F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `txna F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x36 {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F of the current transaction `txna` can be called using `txn` with 2 immediates.
+- Ith value of the array field F of the current transaction
+- `txna` can be called by using `txn` with 2 immediates.
- Availability: v2
-### txna
+### txna Fields
Fields (see [transaction reference](https://developer.algorand.org/docs/reference/transactions/))
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 26 | ApplicationArgs | []byte | v2 | Arguments passed to the application in the ApplicationCall transaction |
| 28 | Accounts | address | v2 | Accounts listed in the ApplicationCall transaction |
| 48 | Assets | uint64 | v3 | Foreign Assets listed in the ApplicationCall transaction |
@@ -506,18 +504,18 @@ Fields (see [transaction reference](https://developer.algorand.org/docs/referenc
| 64 | ApprovalProgramPages | []byte | v7 | Approval Program as an array of pages |
| 66 | ClearStateProgramPages | []byte | v7 | ClearState Program as an array of pages |
-
## gtxna
-- Syntax: `gtxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x37 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
-- Ith value of the array field F from the Tth transaction in the current group `gtxna` can be called using `gtxn` with 3 immediates.
+- Ith value of the array field F from the Tth transaction in the current group
+- `gtxna` can be called by using `gtxn` with 3 immediates.
- Availability: v2
## gtxns
-- Syntax: `gtxns F` where F: [txn](#field-group-txn)
+- Syntax: `gtxns F` where F: [txn Fields](#txn-fields)
- Bytecode: 0x38 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of the Ath transaction in the current group
@@ -527,10 +525,11 @@ for notes on transaction fields available, see `txn`. If top of stack is _i_, `g
## gtxnsa
-- Syntax: `gtxnsa F I` where F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gtxnsa F I` where F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0x39 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
-- Ith value of the array field F from the Ath transaction in the current group `gtxnsa` can be called using `gtxns` with 2 immediates.
+- Ith value of the array field F from the Ath transaction in the current group
+- `gtxnsa` can be called by using `gtxns` with 2 immediates.
- Availability: v3
## gload
@@ -784,7 +783,8 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Bytecode: 0x58
- Stack: ..., A: []byte, B: uint64, C: uint64 → ..., []byte
-- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails `extract3` can be called using `extract` with no immediates.
+- A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails
+- `extract3` can be called by using `extract` with no immediates.
- Availability: v5
## extract_uint16
@@ -813,60 +813,56 @@ When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on
- Syntax: `replace2 S` where S: start position
- Bytecode: 0x5c {uint8}
- Stack: ..., A: []byte, B: []byte → ..., []byte
-- Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A) `replace2` can be called using `replace` with 1 immediate.
+- Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)
+- `replace2` can be called by using `replace` with 1 immediate.
- Availability: v7
## replace3
- Bytecode: 0x5d
- Stack: ..., A: []byte, B: uint64, C: []byte → ..., []byte
-- Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A) `replace3` can be called using `replace` with no immediates.
+- Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)
+- `replace3` can be called by using `replace` with no immediates.
- Availability: v7
## base64_decode
-- Syntax: `base64_decode E` where E: [base64](#field-group-base64)
+- Syntax: `base64_decode E` where E: [base64 Encodings](#base64-encodings)
- Bytecode: 0x5e {uint8}
- Stack: ..., A: []byte → ..., []byte
- decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E
- **Cost**: 1 + 1 per 16 bytes of A
- Availability: v7
-### base64
-
-Encodings
+### base64 Encodings
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | URLEncoding | |
| 1 | StdEncoding | |
-
-*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.
+_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.
Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\n` and `\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\r`, or `\n`.
## json_ref
-- Syntax: `json_ref R` where R: [json_ref](#field-group-json_ref)
+- Syntax: `json_ref R` where R: [json_ref Types](#json_ref-types)
- Bytecode: 0x5f {uint8}
- Stack: ..., A: []byte, B: []byte → ..., any
- key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A
- **Cost**: 25 + 2 per 7 bytes of A
- Availability: v7
-### json_ref
-
-Types
+### json_ref Types
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | JSONString | []byte | |
| 1 | JSONUint64 | uint64 | |
| 2 | JSONObject | []byte | |
-
-*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.
+_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.
Almost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.
@@ -974,40 +970,35 @@ Deleting a key which is already absent has no effect on the application global s
## asset_holding_get
-- Syntax: `asset_holding_get F` where F: [asset_holding](#field-group-asset_holding)
+- Syntax: `asset_holding_get F` where F: [asset_holding Fields](#asset_holding-fields)
- Bytecode: 0x70 {uint8}
- Stack: ..., A, B: uint64 → ..., X: any, Y: bool
- X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0
- Availability: v2
- Mode: Application
-### asset_holding
+### asset_holding Fields
-Fields
-
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AssetBalance | uint64 | Amount of the asset unit held by this account |
| 1 | AssetFrozen | bool | Is the asset frozen or not |
-
params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## asset_params_get
-- Syntax: `asset_params_get F` where F: [asset_params](#field-group-asset_params)
+- Syntax: `asset_params_get F` where F: [asset_params Fields](#asset_params-fields)
- Bytecode: 0x71 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from asset A. Y is 1 if A exists, else 0
- Availability: v2
- Mode: Application
-### asset_params
-
-Fields
+### asset_params Fields
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AssetTotal | uint64 | | Total number of units of this asset |
| 1 | AssetDecimals | uint64 | | See AssetParams.Decimals |
| 2 | AssetDefaultFrozen | bool | | Frozen by default or not |
@@ -1021,24 +1012,21 @@ Fields
| 10 | AssetClawback | address | | Clawback address |
| 11 | AssetCreator | address | v5 | Creator address |
-
params: Txn.ForeignAssets offset (or, since v4, an _available_ asset id. Return: did_exist flag (1 if the asset existed and 0 otherwise), value.
## app_params_get
-- Syntax: `app_params_get F` where F: [app_params](#field-group-app_params)
+- Syntax: `app_params_get F` where F: [app_params Fields](#app_params-fields)
- Bytecode: 0x72 {uint8}
- Stack: ..., A: uint64 → ..., X: any, Y: bool
- X is field F from app A. Y is 1 if A exists, else 0
- Availability: v5
- Mode: Application
-### app_params
-
-Fields
+### app_params Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | AppApprovalProgram | []byte | Bytecode of Approval Program |
| 1 | AppClearStateProgram | []byte | Bytecode of Clear State Program |
| 2 | AppGlobalNumUint | uint64 | Number of uint64 values allowed in Global State |
@@ -1049,24 +1037,21 @@ Fields
| 7 | AppCreator | address | Creator address |
| 8 | AppAddress | address | Address for which this application has authority |
-
params: Txn.ForeignApps offset or an _available_ app id. Return: did_exist flag (1 if the application existed and 0 otherwise), value.
## acct_params_get
-- Syntax: `acct_params_get F` where F: [acct_params](#field-group-acct_params)
+- Syntax: `acct_params_get F` where F: [acct_params Fields](#acct_params-fields)
- Bytecode: 0x73 {uint8}
- Stack: ..., A → ..., X: any, Y: bool
- X is field F from account A. Y is 1 if A owns positive algos, else 0
- Availability: v6
- Mode: Application
-### acct_params
+### acct_params Fields
-Fields
-
-| Index | Name | Type | In | Notes |
-| - | ------ | -- | - | --------- |
+| INDEX | NAME | TYPE | IN | NOTES |
+| :-: | :------ |:--:|:-:| :--------- |
| 0 | AcctBalance | uint64 | | Account balance in microalgos |
| 1 | AcctMinBalance | uint64 | | Minimum required balance for account, in microalgos |
| 2 | AcctAuthAddr | address | | Address the account is rekeyed to. |
@@ -1080,7 +1065,6 @@ Fields
| 10 | AcctTotalBoxes | uint64 | v8 | The number of existing boxes created by this account's app. |
| 11 | AcctTotalBoxBytes | uint64 | v8 | The total number of bytes used by this account's app's box keys and values. |
-
## min_balance
- Bytecode: 0x78
@@ -1416,7 +1400,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn_field
-- Syntax: `itxn_field F` where F: [txn](#field-group-txn)
+- Syntax: `itxn_field F` where F: [txn](#txn)
- Bytecode: 0xb2 {uint8}
- Stack: ..., A → ...
- set field F of the current inner transaction to A
@@ -1437,7 +1421,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxn
-- Syntax: `itxn F` where F: [txn](#field-group-txn)
+- Syntax: `itxn F` where F: [txn Fields](#txn-fields)
- Bytecode: 0xb4 {uint8}
- Stack: ... → ..., any
- field F of the last inner transaction
@@ -1446,7 +1430,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## itxna
-- Syntax: `itxna F I` where F: [txna](#field-group-txna), I: a transaction field array index
+- Syntax: `itxna F I` where F: [txna Fields](#txna-fields), I: a transaction field array index
- Bytecode: 0xb5 {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F of the last inner transaction
@@ -1465,7 +1449,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxn
-- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#field-group-txn)
+- Syntax: `gitxn T F` where T: transaction group index, F: [txn](#txn)
- Bytecode: 0xb7 {uint8}, {uint8}
- Stack: ... → ..., any
- field F of the Tth transaction in the last inner group submitted
@@ -1474,7 +1458,7 @@ The notation A,B indicates that A and B are interpreted as a uint128 value, with
## gitxna
-- Syntax: `gitxna T F I` where T: transaction group index, F: [txna](#field-group-txna), I: transaction field array index
+- Syntax: `gitxna T F I` where T: transaction group index, F: [txna Fields](#txna-fields), I: transaction field array index
- Bytecode: 0xb8 {uint8}, {uint8}, {uint8}
- Stack: ... → ..., any
- Ith value of the array field F from the Tth transaction in the last inner group submitted
@@ -1545,7 +1529,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## txnas
-- Syntax: `txnas F` where F: [txna](#field-group-txna)
+- Syntax: `txnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc0 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the current transaction
@@ -1553,7 +1537,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gtxnas
-- Syntax: `gtxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gtxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc1 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the current group
@@ -1561,7 +1545,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gtxnsas
-- Syntax: `gtxnsas F` where F: [txna](#field-group-txna)
+- Syntax: `gtxnsas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc2 {uint8}
- Stack: ..., A: uint64, B: uint64 → ..., any
- Bth value of the array field F from the Ath transaction in the current group
@@ -1585,7 +1569,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## itxnas
-- Syntax: `itxnas F` where F: [txna](#field-group-txna)
+- Syntax: `itxnas F` where F: [txna Fields](#txna-fields)
- Bytecode: 0xc5 {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F of the last inner transaction
@@ -1594,7 +1578,7 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## gitxnas
-- Syntax: `gitxnas T F` where T: transaction group index, F: [txna](#field-group-txna)
+- Syntax: `gitxnas T F` where T: transaction group index, F: [txna Fields](#txna-fields)
- Bytecode: 0xc6 {uint8}, {uint8}
- Stack: ..., A: uint64 → ..., any
- Ath value of the array field F from the Tth transaction in the last inner group submitted
@@ -1603,38 +1587,32 @@ For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `bo
## vrf_verify
-- Syntax: `vrf_verify S` where S: [vrf_verify](#field-group-vrf_verify)
+- Syntax: `vrf_verify S` where S: [vrf_verify Standards](#vrf_verify-standards)
- Bytecode: 0xd0 {uint8}
- Stack: ..., A: []byte, B: [80]byte, C: [32]byte → ..., X: [64]byte, Y: bool
- Verify the proof B of message A against pubkey C. Returns vrf output and verification flag.
- **Cost**: 5700
- Availability: v7
-### vrf_verify
-
-Standards
+### vrf_verify Standards
-| Index | Name | Notes |
-| - | ------ | --------- |
+| INDEX | NAME | NOTES |
+| :-: | :------ | :--------- |
| 0 | VrfAlgorand | |
-
`VrfAlgorand` is the VRF used in Algorand. It is ECVRF-ED25519-SHA512-Elligator2, specified in the IETF internet draft [draft-irtf-cfrg-vrf-03](https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/03/).
## block
-- Syntax: `block F` where F: [block](#field-group-block)
+- Syntax: `block F` where F: [block Fields](#block-fields)
- Bytecode: 0xd1 {uint8}
- Stack: ..., A: uint64 → ..., any
- field F of block A. Fail unless A falls between txn.LastValid-1002 and txn.FirstValid (exclusive)
- Availability: v7
-### block
-
-Fields
+### block Fields
-| Index | Name | Type | Notes |
-| - | ------ | -- | --------- |
+| INDEX | NAME | TYPE | NOTES |
+| :-: | :------ |:--:| :--------- |
| 0 | BlkSeed | [32]byte | |
| 1 | BlkTimestamp | uint64 | |
-
diff --git a/data/transactions/logic/assembler.go b/data/transactions/logic/assembler.go
index 42d46b50cf..aba822b138 100644
--- a/data/transactions/logic/assembler.go
+++ b/data/transactions/logic/assembler.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -1735,12 +1735,8 @@ func addPseudoDocTags() {
if spec.Name == name || i == anyImmediates {
continue
}
- msg := fmt.Sprintf("`%s` can be called using `%s` with %s.", spec.Name, name, joinIntsOnOr("immediate", i))
desc := opDescByName[spec.Name]
- if desc.Short == "" {
- panic(spec.Name)
- }
- desc.Short = desc.Short + " " + msg
+ desc.Sugar = fmt.Sprintf("`%s` can be called by using `%s` with %s.", spec.Name, name, joinIntsOnOr("immediate", i))
opDescByName[spec.Name] = desc
}
}
diff --git a/data/transactions/logic/assembler_test.go b/data/transactions/logic/assembler_test.go
index 455a287836..7db33fc5f0 100644
--- a/data/transactions/logic/assembler_test.go
+++ b/data/transactions/logic/assembler_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -3123,9 +3123,6 @@ func TestReplacePseudo(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
- require.Contains(t, opDescByName["replace3"].Short, "`replace3` can be called using `replace` with no immediates.")
- require.Contains(t, opDescByName["replace2"].Short, "`replace2` can be called using `replace` with 1 immediate.")
-
replaceVersion := 7
for v := uint64(replaceVersion); v <= AssemblerMaxVersion; v++ {
testProg(t, "byte 0x0000; byte 0x1234; replace 0", v)
diff --git a/data/transactions/logic/backwardCompat_test.go b/data/transactions/logic/backwardCompat_test.go
index 9d3ca14d2b..7aab034ccb 100644
--- a/data/transactions/logic/backwardCompat_test.go
+++ b/data/transactions/logic/backwardCompat_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/blackbox_test.go b/data/transactions/logic/blackbox_test.go
index 7a32ef3833..473d449584 100644
--- a/data/transactions/logic/blackbox_test.go
+++ b/data/transactions/logic/blackbox_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -43,13 +43,13 @@ func TestNewAppEvalParams(t *testing.T) {
Sender: basics.Address{1, 2, 3, 4},
Receiver: basics.Address{4, 3, 2, 1},
Amount: 100,
- }.SignedTxnWithAD()
+ }.SignedTxn().WithAD()
appcall1 := txntest.Txn{
Type: protocol.ApplicationCallTx,
Sender: basics.Address{1, 2, 3, 4},
ApplicationID: basics.AppIndex(1),
- }.SignedTxnWithAD()
+ }.SignedTxn().WithAD()
appcall2 := appcall1
appcall2.Txn.ApplicationID = basics.AppIndex(2)
diff --git a/data/transactions/logic/box.go b/data/transactions/logic/box.go
index a4e7845ff0..fdb922dd1f 100644
--- a/data/transactions/logic/box.go
+++ b/data/transactions/logic/box.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -52,7 +52,7 @@ func (cx *EvalContext) availableBox(name string, operation BoxOperation, createS
// we don't have to go to the disk. but we only allow one such access for
// each spare (empty) box ref. that way, we can't end up needing to write
// many separate newly created boxes.
- if !ok && cx.Proto.EnableUnnamedBoxAccessInNewApps {
+ if !ok {
if _, newAppAccess = cx.available.createdApps[cx.appID]; newAppAccess {
if cx.available.unnamedAccess > 0 {
ok = true // allow it
diff --git a/data/transactions/logic/box_test.go b/data/transactions/logic/box_test.go
index bfe23b9c54..123f23746e 100644
--- a/data/transactions/logic/box_test.go
+++ b/data/transactions/logic/box_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/crypto.go b/data/transactions/logic/crypto.go
index b0acc75c00..f3e05ee120 100644
--- a/data/transactions/logic/crypto.go
+++ b/data/transactions/logic/crypto.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/crypto_test.go b/data/transactions/logic/crypto_test.go
index 6d5cba7eb4..ae53acf680 100644
--- a/data/transactions/logic/crypto_test.go
+++ b/data/transactions/logic/crypto_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -258,7 +258,7 @@ func TestVrfVerify(t *testing.T) {
testLogic(t, source, LogicVersion, ep)
}
-// BenchMarkVerify is useful to see relative speeds of various crypto verify functions
+// BenchmarkVerify is useful to see relative speeds of various crypto verify functions
func BenchmarkVerify(b *testing.B) {
benches := [][]string{
{"pop", "", "int 1234576; int 6712; pop; pop", "int 1"},
diff --git a/data/transactions/logic/debugger.go b/data/transactions/logic/debugger.go
index f929e1b2be..ea7935e698 100644
--- a/data/transactions/logic/debugger.go
+++ b/data/transactions/logic/debugger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -253,7 +253,7 @@ func (sv stackValue) toEncodedTealValue() basics.TealValue {
return basics.TealValue{Type: basics.TealUintType, Uint: sv.Uint}
}
-// parseCallStack initializes an array of CallFrame objects from the raw
+// parseCallstack initializes an array of CallFrame objects from the raw
// callstack.
func (d *DebugState) parseCallstack(callstack []frame) []CallFrame {
callFrames := make([]CallFrame, 0)
diff --git a/data/transactions/logic/debugger_eval_test.go b/data/transactions/logic/debugger_eval_test.go
index 12a300c4f4..d2e6bf6efb 100644
--- a/data/transactions/logic/debugger_eval_test.go
+++ b/data/transactions/logic/debugger_eval_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/debugger_test.go b/data/transactions/logic/debugger_test.go
index 31eeed1e0a..fedf24bd9c 100644
--- a/data/transactions/logic/debugger_test.go
+++ b/data/transactions/logic/debugger_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/doc.go b/data/transactions/logic/doc.go
index 80a3f0e943..c0f27e397c 100644
--- a/data/transactions/logic/doc.go
+++ b/data/transactions/logic/doc.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -28,32 +28,33 @@ type OpDesc struct {
Short string
Extra string
Immediates []string
+ Sugar string // pseudo calling information
}
var opDescByName = map[string]OpDesc{
- "err": {"Fail immediately.", "", nil},
+ "err": {"Fail immediately.", "", nil, ""},
- "sha256": {"SHA256 hash of value A, yields [32]byte", "", nil},
- "keccak256": {"Keccak256 hash of value A, yields [32]byte", "", nil},
- "sha512_256": {"SHA512_256 hash of value A, yields [32]byte", "", nil},
- "sha3_256": {"SHA3_256 hash of value A, yields [32]byte", "", nil},
- "sha512": {"SHA512 of value A, yields [64]byte", "", nil},
+ "sha256": {"SHA256 hash of value A, yields [32]byte", "", nil, ""},
+ "keccak256": {"Keccak256 hash of value A, yields [32]byte", "", nil, ""},
+ "sha512_256": {"SHA512_256 hash of value A, yields [32]byte", "", nil, ""},
+ "sha3_256": {"SHA3_256 hash of value A, yields [32]byte", "", nil, ""},
+ "sha512": {"SHA512 of value A, yields [64]byte", "", nil, ""},
- "sumhash512": {"sumhash512 of value A, yields [64]byte", "", nil},
- "falcon_verify": {"for (data A, compressed-format signature B, pubkey C) verify the signature of data against the pubkey => {0 or 1}", "", nil},
+ "sumhash512": {"sumhash512 of value A, yields [64]byte", "", nil, ""},
+ "falcon_verify": {"for (data A, compressed-format signature B, pubkey C) verify the signature of data against the pubkey => {0 or 1}", "", nil, ""},
"mimc": {"MiMC hash of scalars A, using curve and parameters specified by configuration C", "" +
"A is a list of concatenated 32 byte big-endian unsigned integer scalars. Fail if A's length is not a multiple of 32 or any element exceeds the curve modulus.\n\n" +
"The MiMC hash function has known collisions since any input which is a multiple of the elliptic curve modulus will hash to the same value. " +
"MiMC is thus not a general purpose hash function, but meant to be used in zero knowledge applications to match a zk-circuit implementation.",
- []string{"configuration index"},
+ []string{"configuration index"}, "",
},
- "ed25519verify": {"for (data A, signature B, pubkey C) verify the signature of (\"ProgData\" || program_hash || data) against the pubkey => {0 or 1}", "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", nil},
- "ed25519verify_bare": {"for (data A, signature B, pubkey C) verify the signature of the data against the pubkey => {0 or 1}", "", nil},
- "ecdsa_verify": {"for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1}", "The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.", []string{"curve index"}},
- "ecdsa_pk_decompress": {"decompress pubkey A into components X, Y", "The 33 byte public key in a compressed form to be decompressed into X and Y (top) components. All values are big-endian encoded.", []string{"curve index"}},
- "ecdsa_pk_recover": {"for (data A, recovery id B, signature C, D) recover a public key", "S (top) and R elements of a signature, recovery id and data (bottom) are expected on the stack and used to deriver a public key. All values are big-endian encoded. The signed data must be 32 bytes long.", []string{"curve index"}},
+ "ed25519verify": {"for (data A, signature B, pubkey C) verify the signature of (\"ProgData\" || program_hash || data) against the pubkey => {0 or 1}", "The 32 byte public key is the last element on the stack, preceded by the 64 byte signature at the second-to-last element on the stack, preceded by the data which was signed at the third-to-last element on the stack.", nil, ""},
+ "ed25519verify_bare": {"for (data A, signature B, pubkey C) verify the signature of the data against the pubkey => {0 or 1}", "", nil, ""},
+ "ecdsa_verify": {"for (data A, signature B, C and pubkey D, E) verify the signature of the data against the pubkey => {0 or 1}", "The 32 byte Y-component of a public key is the last element on the stack, preceded by X-component of a pubkey, preceded by S and R components of a signature, preceded by the data that is fifth element on the stack. All values are big-endian encoded. The signed data must be 32 bytes long, and signatures in lower-S form are only accepted.", []string{"curve index"}, ""},
+ "ecdsa_pk_decompress": {"decompress pubkey A into components X, Y", "The 33 byte public key in a compressed form to be decompressed into X and Y (top) components. All values are big-endian encoded.", []string{"curve index"}, ""},
+ "ecdsa_pk_recover": {"for (data A, recovery id B, signature C, D) recover a public key", "S (top) and R elements of a signature, recovery id and data (bottom) are expected on the stack and used to deriver a public key. All values are big-endian encoded. The signed data must be 32 bytes long.", []string{"curve index"}, ""},
"ec_add": {"for curve points A and B, return the curve point A + B", "" +
"A and B are curve points in affine representation: field element X concatenated with field element Y. " +
@@ -66,253 +67,253 @@ var opDescByName = map[string]OpDesc{
"Fails if A or B is not in G.\n" +
"A and/or B are allowed to be the point at infinity.\n" +
"Does _not_ check if A and B are in the main prime-order subgroup.",
- []string{"curve index"},
+ []string{"curve index"}, "",
},
"ec_scalar_mul": {"for curve point A and scalar B, return the curve point BA, the point A multiplied by the scalar B.",
"A is a curve point encoded and checked as described in `ec_add`. Scalar B is interpreted as a big-endian unsigned integer. Fails if B exceeds 32 bytes.",
- []string{"curve index"},
+ []string{"curve index"}, "",
},
"ec_pairing_check": {"1 if the product of the pairing of each point in A with its respective point in B is equal to the identity element of the target group Gt, else 0",
"A and B are concatenated points, encoded and checked as described in `ec_add`. A contains points of the group G, B contains points of the associated group (G2 if G is G1, and vice versa). Fails if A and B have a different number of points, or if any point is not in its described group or outside the main prime-order subgroup - a stronger condition than other opcodes. AVM values are limited to 4096 bytes, so `ec_pairing_check` is limited by the size of the points in the groups being operated upon.",
- []string{"curve index"},
+ []string{"curve index"}, "",
},
"ec_multi_scalar_mul": {"for curve points A and scalars B, return curve point B0A0 + B1A1 + B2A2 + ... + BnAn",
"A is a list of concatenated points, encoded and checked as described in `ec_add`. B is a list of concatenated scalars which, unlike ec_scalar_mul, must all be exactly 32 bytes long.\nThe name `ec_multi_scalar_mul` was chosen to reflect common usage, but a more consistent name would be `ec_multi_scalar_mul`. AVM values are limited to 4096 bytes, so `ec_multi_scalar_mul` is limited by the size of the points in the group being operated upon.",
- []string{"curve index"},
+ []string{"curve index"}, "",
},
- "ec_subgroup_check": {"1 if A is in the main prime-order subgroup of G (including the point at infinity) else 0. Program fails if A is not in G at all.", "", []string{"curve index"}},
+ "ec_subgroup_check": {"1 if A is in the main prime-order subgroup of G (including the point at infinity) else 0. Program fails if A is not in G at all.", "", []string{"curve index"}, ""},
"ec_map_to": {"maps field element A to group G", "" +
"BN254 points are mapped by the SVDW map. BLS12-381 points are mapped by the SSWU map.\n" +
"G1 element inputs are base field elements and G2 element inputs are quadratic field elements, with nearly the same encoding rules (for field elements) as defined in `ec_add`. There is one difference of encoding rule: G1 element inputs do not need to be 0-padded if they fit in less than 32 bytes for BN254 and less than 48 bytes for BLS12-381. (As usual, the empty byte array represents 0.) G2 elements inputs need to be always have the required size.",
- []string{"curve index"},
+ []string{"curve index"}, "",
},
- "+": {"A plus B. Fail on overflow.", "Overflow is an error condition which halts execution and fails the transaction. Full precision is available from `addw`.", nil},
- "-": {"A minus B. Fail if B > A.", "", nil},
- "/": {"A divided by B (truncated division). Fail if B == 0.", "`divmodw` is available to divide the two-element values produced by `mulw` and `addw`.", nil},
- "*": {"A times B. Fail on overflow.", "Overflow is an error condition which halts execution and fails the transaction. Full precision is available from `mulw`.", nil},
- "<": {"A less than B => {0 or 1}", "", nil},
- ">": {"A greater than B => {0 or 1}", "", nil},
- "<=": {"A less than or equal to B => {0 or 1}", "", nil},
- ">=": {"A greater than or equal to B => {0 or 1}", "", nil},
- "&&": {"A is not zero and B is not zero => {0 or 1}", "", nil},
- "||": {"A is not zero or B is not zero => {0 or 1}", "", nil},
- "==": {"A is equal to B => {0 or 1}", "", nil},
- "!=": {"A is not equal to B => {0 or 1}", "", nil},
- "!": {"A == 0 yields 1; else 0", "", nil},
-
- "len": {"yields length of byte value A", "", nil},
- "itob": {"converts uint64 A to big-endian byte array, always of length 8", "", nil},
+ "+": {"A plus B. Fail on overflow.", "Overflow is an error condition which halts execution and fails the transaction. Full precision is available from `addw`.", nil, ""},
+ "-": {"A minus B. Fail if B > A.", "", nil, ""},
+ "/": {"A divided by B (truncated division). Fail if B == 0.", "`divmodw` is available to divide the two-element values produced by `mulw` and `addw`.", nil, ""},
+ "*": {"A times B. Fail on overflow.", "Overflow is an error condition which halts execution and fails the transaction. Full precision is available from `mulw`.", nil, ""},
+ "<": {"A less than B => {0 or 1}", "", nil, ""},
+ ">": {"A greater than B => {0 or 1}", "", nil, ""},
+ "<=": {"A less than or equal to B => {0 or 1}", "", nil, ""},
+ ">=": {"A greater than or equal to B => {0 or 1}", "", nil, ""},
+ "&&": {"A is not zero and B is not zero => {0 or 1}", "", nil, ""},
+ "||": {"A is not zero or B is not zero => {0 or 1}", "", nil, ""},
+ "==": {"A is equal to B => {0 or 1}", "", nil, ""},
+ "!=": {"A is not equal to B => {0 or 1}", "", nil, ""},
+ "!": {"A == 0 yields 1; else 0", "", nil, ""},
+
+ "len": {"yields length of byte value A", "", nil, ""},
+ "itob": {"converts uint64 A to big-endian byte array, always of length 8", "", nil, ""},
"btoi": {"converts big-endian byte array A to uint64. Fails if len(A) > 8. Padded by leading 0s if len(A) < 8.",
- "`btoi` fails if the input is longer than 8 bytes.", nil},
-
- "%": {"A modulo B. Fail if B == 0.", "", nil},
- "|": {"A bitwise-or B", "", nil},
- "&": {"A bitwise-and B", "", nil},
- "^": {"A bitwise-xor B", "", nil},
- "~": {"bitwise invert value A", "", nil},
- "shl": {"A times 2^B, modulo 2^64", "", nil},
- "shr": {"A divided by 2^B", "", nil},
- "sqrt": {"The largest integer I such that I^2 <= A", "", nil},
- "bitlen": {"The highest set bit in A. If A is a byte-array, it is interpreted as a big-endian unsigned integer. bitlen of 0 is 0, bitlen of 8 is 4", "bitlen interprets arrays as big-endian integers, unlike setbit/getbit", nil},
- "exp": {"A raised to the Bth power. Fail if A == B == 0 and on overflow", "", nil},
- "expw": {"A raised to the Bth power as a 128-bit result in two uint64s. X is the high 64 bits, Y is the low. Fail if A == B == 0 or if the results exceeds 2^128-1", "", nil},
- "mulw": {"A times B as a 128-bit result in two uint64s. X is the high 64 bits, Y is the low", "", nil},
- "addw": {"A plus B as a 128-bit result. X is the carry-bit, Y is the low-order 64 bits.", "", nil},
+ "`btoi` fails if the input is longer than 8 bytes.", nil, ""},
+
+ "%": {"A modulo B. Fail if B == 0.", "", nil, ""},
+ "|": {"A bitwise-or B", "", nil, ""},
+ "&": {"A bitwise-and B", "", nil, ""},
+ "^": {"A bitwise-xor B", "", nil, ""},
+ "~": {"bitwise invert value A", "", nil, ""},
+ "shl": {"A times 2^B, modulo 2^64", "", nil, ""},
+ "shr": {"A divided by 2^B", "", nil, ""},
+ "sqrt": {"The largest integer I such that I^2 <= A", "", nil, ""},
+ "bitlen": {"The highest set bit in A. If A is a byte-array, it is interpreted as a big-endian unsigned integer. bitlen of 0 is 0, bitlen of 8 is 4", "bitlen interprets arrays as big-endian integers, unlike setbit/getbit", nil, ""},
+ "exp": {"A raised to the Bth power. Fail if A == B == 0 and on overflow", "", nil, ""},
+ "expw": {"A raised to the Bth power as a 128-bit result in two uint64s. X is the high 64 bits, Y is the low. Fail if A == B == 0 or if the results exceeds 2^128-1", "", nil, ""},
+ "mulw": {"A times B as a 128-bit result in two uint64s. X is the high 64 bits, Y is the low", "", nil, ""},
+ "addw": {"A plus B as a 128-bit result. X is the carry-bit, Y is the low-order 64 bits.", "", nil, ""},
"divw": {"A,B / C. Fail if C == 0 or if result overflows.",
- "The notation A,B indicates that A and B are interpreted as a uint128 value, with A as the high uint64 and B the low.", nil},
+ "The notation A,B indicates that A and B are interpreted as a uint128 value, with A as the high uint64 and B the low.", nil, ""},
"divmodw": {"W,X = (A,B / C,D); Y,Z = (A,B modulo C,D)",
- "The notation J,K indicates that two uint64 values J and K are interpreted as a uint128 value, with J as the high uint64 and K the low.", nil},
-
- "intcblock": {"prepare block of uint64 constants for use by intc", "`intcblock` loads following program bytes into an array of integer constants in the evaluator. These integer constants can be referred to by `intc` and `intc_*` which will push the value onto the stack. Subsequent calls to `intcblock` reset and replace the integer constants available to the script.", []string{"a block of int constant values"}},
- "intc": {"Ith constant from intcblock", "", []string{"an index in the intcblock"}},
- "intc_0": {"constant 0 from intcblock", "", nil},
- "intc_1": {"constant 1 from intcblock", "", nil},
- "intc_2": {"constant 2 from intcblock", "", nil},
- "intc_3": {"constant 3 from intcblock", "", nil},
- "pushint": {"immediate UINT", "pushint args are not added to the intcblock during assembly processes", []string{"an int constant"}},
- "pushints": {"push sequence of immediate uints to stack in the order they appear (first uint being deepest)", "pushints args are not added to the intcblock during assembly processes", []string{"a list of int constants"}},
- "bytecblock": {"prepare block of byte-array constants for use by bytec", "`bytecblock` loads the following program bytes into an array of byte-array constants in the evaluator. These constants can be referred to by `bytec` and `bytec_*` which will push the value onto the stack. Subsequent calls to `bytecblock` reset and replace the bytes constants available to the script.", []string{"a block of byte constant values"}},
- "bytec": {"Ith constant from bytecblock", "", []string{"an index in the bytecblock"}},
- "bytec_0": {"constant 0 from bytecblock", "", nil},
- "bytec_1": {"constant 1 from bytecblock", "", nil},
- "bytec_2": {"constant 2 from bytecblock", "", nil},
- "bytec_3": {"constant 3 from bytecblock", "", nil},
- "pushbytes": {"immediate BYTES", "pushbytes args are not added to the bytecblock during assembly processes", []string{"a byte constant"}},
+ "The notation J,K indicates that two uint64 values J and K are interpreted as a uint128 value, with J as the high uint64 and K the low.", nil, ""},
+
+ "intcblock": {"prepare block of uint64 constants for use by intc", "`intcblock` loads following program bytes into an array of integer constants in the evaluator. These integer constants can be referred to by `intc` and `intc_*` which will push the value onto the stack. Subsequent calls to `intcblock` reset and replace the integer constants available to the script.", []string{"a block of int constant values"}, ""},
+ "intc": {"Ith constant from intcblock", "", []string{"an index in the intcblock"}, ""},
+ "intc_0": {"constant 0 from intcblock", "", nil, ""},
+ "intc_1": {"constant 1 from intcblock", "", nil, ""},
+ "intc_2": {"constant 2 from intcblock", "", nil, ""},
+ "intc_3": {"constant 3 from intcblock", "", nil, ""},
+ "pushint": {"immediate UINT", "pushint args are not added to the intcblock during assembly processes", []string{"an int constant"}, ""},
+ "pushints": {"push sequence of immediate uints to stack in the order they appear (first uint being deepest)", "pushints args are not added to the intcblock during assembly processes", []string{"a list of int constants"}, ""},
+ "bytecblock": {"prepare block of byte-array constants for use by bytec", "`bytecblock` loads the following program bytes into an array of byte-array constants in the evaluator. These constants can be referred to by `bytec` and `bytec_*` which will push the value onto the stack. Subsequent calls to `bytecblock` reset and replace the bytes constants available to the script.", []string{"a block of byte constant values"}, ""},
+ "bytec": {"Ith constant from bytecblock", "", []string{"an index in the bytecblock"}, ""},
+ "bytec_0": {"constant 0 from bytecblock", "", nil, ""},
+ "bytec_1": {"constant 1 from bytecblock", "", nil, ""},
+ "bytec_2": {"constant 2 from bytecblock", "", nil, ""},
+ "bytec_3": {"constant 3 from bytecblock", "", nil, ""},
+ "pushbytes": {"immediate BYTES", "pushbytes args are not added to the bytecblock during assembly processes", []string{"a byte constant"}, ""},
"pushbytess": {"push sequences of immediate byte arrays to stack (first byte array being deepest)",
"pushbytess args are not added to the bytecblock during assembly processes",
- []string{"a list of byte constants"}},
+ []string{"a list of byte constants"}, ""},
- "bzero": {"zero filled byte-array of length A", "", nil},
- "arg": {"Nth LogicSig argument", "", []string{"an arg index"}},
- "arg_0": {"LogicSig argument 0", "", nil},
- "arg_1": {"LogicSig argument 1", "", nil},
- "arg_2": {"LogicSig argument 2", "", nil},
- "arg_3": {"LogicSig argument 3", "", nil},
- "args": {"Ath LogicSig argument", "", nil},
+ "bzero": {"zero filled byte-array of length A", "", nil, ""},
+ "arg": {"Nth LogicSig argument", "", []string{"an arg index"}, ""},
+ "arg_0": {"LogicSig argument 0", "", nil, ""},
+ "arg_1": {"LogicSig argument 1", "", nil, ""},
+ "arg_2": {"LogicSig argument 2", "", nil, ""},
+ "arg_3": {"LogicSig argument 3", "", nil, ""},
+ "args": {"Ath LogicSig argument", "", nil, ""},
- "txn": {"field F of current transaction", "", []string{"transaction field index"}},
+ "txn": {"field F of current transaction", "", []string{"transaction field index"}, ""},
"gtxn": {
"field F of the Tth transaction in the current group",
"for notes on transaction fields available, see `txn`. If this transaction is _i_ in the group, `gtxn i field` is equivalent to `txn field`.",
- []string{"transaction group index", "transaction field index"},
+ []string{"transaction group index", "transaction field index"}, "",
},
"gtxns": {"field F of the Ath transaction in the current group",
"for notes on transaction fields available, see `txn`. If top of stack is _i_, `gtxns field` is equivalent to `gtxn _i_ field`. gtxns exists so that _i_ can be calculated, often based on the index of the current transaction.",
- []string{"transaction field index"},
+ []string{"transaction field index"}, "",
},
"txna": {"Ith value of the array field F of the current transaction", "",
- []string{"transaction field index", "transaction field array index"}},
+ []string{"transaction field index", "transaction field array index"}, ""},
"gtxna": {"Ith value of the array field F from the Tth transaction in the current group", "",
- []string{"transaction group index", "transaction field index", "transaction field array index"}},
+ []string{"transaction group index", "transaction field index", "transaction field array index"}, ""},
"gtxnsa": {"Ith value of the array field F from the Ath transaction in the current group", "",
- []string{"transaction field index", "transaction field array index"}},
+ []string{"transaction field index", "transaction field array index"}, ""},
"txnas": {"Ath value of the array field F of the current transaction", "",
- []string{"transaction field index"}},
+ []string{"transaction field index"}, ""},
"gtxnas": {"Ath value of the array field F from the Tth transaction in the current group", "",
- []string{"transaction group index", "transaction field index"}},
+ []string{"transaction group index", "transaction field index"}, ""},
"gtxnsas": {"Bth value of the array field F from the Ath transaction in the current group", "",
- []string{"transaction field index"}},
- "itxn": {"field F of the last inner transaction", "", []string{"transaction field index"}},
+ []string{"transaction field index"}, ""},
+ "itxn": {"field F of the last inner transaction", "", []string{"transaction field index"}, ""},
"itxna": {"Ith value of the array field F of the last inner transaction", "",
- []string{"transaction field index", "a transaction field array index"}},
+ []string{"transaction field index", "a transaction field array index"}, ""},
"itxnas": {"Ath value of the array field F of the last inner transaction", "",
- []string{"transaction field index"}},
+ []string{"transaction field index"}, ""},
"gitxn": {"field F of the Tth transaction in the last inner group submitted", "",
- []string{"transaction group index", "transaction field index"}},
+ []string{"transaction group index", "transaction field index"}, ""},
"gitxna": {"Ith value of the array field F from the Tth transaction in the last inner group submitted", "",
- []string{"transaction group index", "transaction field index", "transaction field array index"}},
+ []string{"transaction group index", "transaction field index", "transaction field array index"}, ""},
"gitxnas": {"Ath value of the array field F from the Tth transaction in the last inner group submitted", "",
- []string{"transaction group index", "transaction field index"}},
+ []string{"transaction group index", "transaction field index"}, ""},
- "global": {"global field F", "", []string{"a global field index"}},
+ "global": {"global field F", "", []string{"a global field index"}, ""},
"load": {"Ith scratch space value. All scratch spaces are 0 at program start.", "",
- []string{"position in scratch space to load from"}},
+ []string{"position in scratch space to load from"}, ""},
"store": {"store A to the Ith scratch space", "",
- []string{"position in scratch space to store to"}},
- "loads": {"Ath scratch space value. All scratch spaces are 0 at program start.", "", nil},
- "stores": {"store B to the Ath scratch space", "", nil},
+ []string{"position in scratch space to store to"}, ""},
+ "loads": {"Ath scratch space value. All scratch spaces are 0 at program start.", "", nil, ""},
+ "stores": {"store B to the Ath scratch space", "", nil, ""},
"gload": {"Ith scratch space value of the Tth transaction in the current group",
"`gload` fails unless the requested transaction is an ApplicationCall and T < GroupIndex.",
- []string{"transaction group index", "position in scratch space to load from"}},
+ []string{"transaction group index", "position in scratch space to load from"}, ""},
"gloads": {"Ith scratch space value of the Ath transaction in the current group",
"`gloads` fails unless the requested transaction is an ApplicationCall and A < GroupIndex.",
- []string{"position in scratch space to load from"},
+ []string{"position in scratch space to load from"}, "",
},
- "gloadss": {"Bth scratch space value of the Ath transaction in the current group", "", nil},
+ "gloadss": {"Bth scratch space value of the Ath transaction in the current group", "", nil, ""},
"gaid": {"ID of the asset or application created in the Tth transaction of the current group",
"`gaid` fails unless the requested transaction created an asset or application and T < GroupIndex.",
- []string{"transaction group index"}},
+ []string{"transaction group index"}, ""},
"gaids": {"ID of the asset or application created in the Ath transaction of the current group",
- "`gaids` fails unless the requested transaction created an asset or application and A < GroupIndex.", nil},
+ "`gaids` fails unless the requested transaction created an asset or application and A < GroupIndex.", nil, ""},
"json_ref": {"key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A",
- "*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
- []string{"return type index"}},
-
- "bnz": {"branch to TARGET if value A is not zero", "The `bnz` instruction opcode 0x40 is followed by two immediate data bytes which are a high byte first and low byte second which together form a 16 bit offset which the instruction may branch to. For a bnz instruction at `pc`, if the last element of the stack is not zero then branch to instruction at `pc + 3 + N`, else proceed to next instruction at `pc + 3`. Branch targets must be aligned instructions. (e.g. Branching to the second byte of a 2 byte op will be rejected.) Starting at v4, the offset is treated as a signed 16 bit integer allowing for backward branches and looping. In prior version (v1 to v3), branch offsets are limited to forward branches only, 0-0x7fff.\n\nAt v2 it became allowed to branch to the end of the program exactly after the last instruction: bnz to byte N (with 0-indexing) was illegal for a TEAL program with N bytes before v2, and is legal after it. This change eliminates the need for a last instruction of no-op as a branch target at the end. (Branching beyond the end--in other words, to a byte larger than N--is still illegal and will cause the program to fail.)", []string{"branch offset"}},
- "bz": {"branch to TARGET if value A is zero", "See `bnz` for details on how branches work. `bz` inverts the behavior of `bnz`.", []string{"branch offset"}},
- "b": {"branch unconditionally to TARGET", "See `bnz` for details on how branches work. `b` always jumps to the offset.", []string{"branch offset"}},
- "return": {"use A as success value; end", "", nil},
-
- "pop": {"discard A", "", nil},
- "dup": {"duplicate A", "", nil},
- "dup2": {"duplicate A and B", "", nil},
- "dupn": {"duplicate A, N times", "", []string{"copy count"}},
- "dig": {"Nth value from the top of the stack. dig 0 is equivalent to dup", "", []string{"depth"}},
- "bury": {"replace the Nth value from the top of the stack with A. bury 0 fails.", "", []string{"depth"}},
- "cover": {"remove top of stack, and place it deeper in the stack such that N elements are above it. Fails if stack depth <= N.", "", []string{"depth"}},
- "uncover": {"remove the value at depth N in the stack and shift above items down so the Nth deep value is on top of the stack. Fails if stack depth <= N.", "", []string{"depth"}},
- "swap": {"swaps A and B on stack", "", nil},
- "select": {"selects one of two values based on top-of-stack: B if C != 0, else A", "", nil},
-
- "concat": {"join A and B", "`concat` fails if the result would be greater than 4096 bytes.", nil},
- "substring": {"A range of bytes from A starting at S up to but not including E. If E < S, or either is larger than the array length, the program fails", "", []string{"start position", "end position"}},
- "substring3": {"A range of bytes from A starting at B up to but not including C. If C < B, or either is larger than the array length, the program fails", "", nil},
- "getbit": {"Bth bit of (byte-array or integer) A. If B is greater than or equal to the bit length of the value (8*byte length), the program fails", "see explanation of bit ordering in setbit", nil},
- "setbit": {"Copy of (byte-array or integer) A, with the Bth bit set to (0 or 1) C. If B is greater than or equal to the bit length of the value (8*byte length), the program fails", "When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on the integer 0 yields 8, or 2^3. When A is a byte array, index 0 is the leftmost bit of the leftmost byte. Setting bits 0 through 11 to 1 in a 4-byte-array of 0s yields the byte array 0xfff00000. Setting bit 3 to 1 on the 1-byte-array 0x00 yields the byte array 0x10.", nil},
- "getbyte": {"Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails", "", nil},
- "setbyte": {"Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails", "", nil},
- "extract": {"A range of bytes from A starting at S up to but not including S+L. If L is 0, then extract to the end of the string. If S or S+L is larger than the array length, the program fails", "", []string{"start position", "length"}},
- "extract3": {"A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails", "", nil},
- "extract_uint16": {"A uint16 formed from a range of big-endian bytes from A starting at B up to but not including B+2. If B+2 is larger than the array length, the program fails", "", nil},
- "extract_uint32": {"A uint32 formed from a range of big-endian bytes from A starting at B up to but not including B+4. If B+4 is larger than the array length, the program fails", "", nil},
- "extract_uint64": {"A uint64 formed from a range of big-endian bytes from A starting at B up to but not including B+8. If B+8 is larger than the array length, the program fails", "", nil},
- "replace2": {"Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)", "", []string{"start position"}},
- "replace3": {"Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)", "", nil},
-
- "base64_decode": {"decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E", "*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.", []string{"encoding index"}},
-
- "balance": {"balance for account A, in microalgos. The balance is observed after the effects of previous transactions in the group, and after the fee for the current transaction is deducted. Changes caused by inner transactions are observable immediately following `itxn_submit`", "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.", nil},
- "min_balance": {"minimum required balance for account A, in microalgos. Required balance is affected by ASA, App, and Box usage. When creating or opting into an app, the minimum balance grows before the app code runs, therefore the increase is visible there. When deleting or closing out, the minimum balance decreases after the app executes. Changes caused by inner transactions or box usage are observable immediately following the opcode effecting the change.", "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.", nil},
- "app_opted_in": {"1 if account A is opted in to application B, else 0", "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.", nil},
- "app_local_get": {"local state of the key B in the current application in account A", "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.", nil},
- "app_local_get_ex": {"X is the local state of application B, key C in account A. Y is 1 if key existed, else 0", "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.", nil},
- "app_global_get": {"global state of the key A in the current application", "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.", nil},
- "app_global_get_ex": {"X is the global state of application A, key B. Y is 1 if key existed, else 0", "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.", nil},
- "app_local_put": {"write C to key B in account A's local state of the current application", "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.", nil},
- "app_global_put": {"write B to key A in the global state of the current application", "", nil},
- "app_local_del": {"delete key B from account A's local state of the current application", "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)", nil},
- "app_global_del": {"delete key A from the global state of the current application", "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)", nil},
- "asset_holding_get": {"X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0", "params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.", []string{"asset holding field index"}},
- "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"}},
- "retsub": {"pop the top instruction from the call stack and branch to it", "If the current frame was prepared by `proto A R`, `retsub` will remove the 'A' arguments from the stack, move the `R` return values down, and pop any stack locations above the relocated return values.", nil},
-
- "b+": {"A plus B. A and B are interpreted as big-endian unsigned integers", "", nil},
- "b-": {"A minus B. A and B are interpreted as big-endian unsigned integers. Fail on underflow.", "", nil},
- "b/": {"A divided by B (truncated division). A and B are interpreted as big-endian unsigned integers. Fail if B is zero.", "", nil},
- "b*": {"A times B. A and B are interpreted as big-endian unsigned integers.", "", nil},
- "b<": {"1 if A is less than B, else 0. A and B are interpreted as big-endian unsigned integers", "", nil},
- "b>": {"1 if A is greater than B, else 0. A and B are interpreted as big-endian unsigned integers", "", nil},
- "b<=": {"1 if A is less than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers", "", nil},
- "b>=": {"1 if A is greater than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers", "", nil},
- "b==": {"1 if A is equal to B, else 0. A and B are interpreted as big-endian unsigned integers", "", nil},
- "b!=": {"0 if A is equal to B, else 1. A and B are interpreted as big-endian unsigned integers", "", nil},
- "b%": {"A modulo B. A and B are interpreted as big-endian unsigned integers. Fail if B is zero.", "", nil},
- "b|": {"A bitwise-or B. A and B are zero-left extended to the greater of their lengths", "", nil},
- "b&": {"A bitwise-and B. A and B are zero-left extended to the greater of their lengths", "", nil},
- "b^": {"A bitwise-xor B. A and B are zero-left extended to the greater of their lengths", "", nil},
- "b~": {"A with all bits inverted", "", nil},
-
- "bsqrt": {"The largest integer I such that I^2 <= A. A and I are interpreted as big-endian unsigned integers", "", nil},
-
- "log": {"write A to log state of the current application", "`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.", nil},
- "itxn_begin": {"begin preparation of a new inner transaction in a new transaction group", "`itxn_begin` initializes Sender to the application address; Fee to the minimum allowable, taking into account MinTxnFee and credit from overpaying in earlier transactions; FirstValid/LastValid to the values in the invoking transaction, and all other fields to zero or empty values.", nil},
- "itxn_next": {"begin preparation of a new inner transaction in the same transaction group", "`itxn_next` initializes the transaction exactly as `itxn_begin` does", nil},
- "itxn_field": {"set field F of the current inner transaction to A", "`itxn_field` fails if A is of the wrong type for F, including a byte array of the wrong size for use as an address when F is an address field. `itxn_field` also fails if A is an account, asset, or app that is not _available_, or an attempt is made extend an array field beyond the limit imposed by consensus parameters. (Addresses set into asset params of acfg transactions need not be _available_.)", []string{"transaction field index"}},
- "itxn_submit": {"execute the current inner transaction group. Fail if executing this group would exceed the inner transaction limit, or if any transaction in the group fails.", "`itxn_submit` resets the current transaction so that it can not be resubmitted. A new `itxn_begin` is required to prepare another inner transaction.", nil},
-
- "vrf_verify": {"Verify the proof B of message A against pubkey C. Returns vrf output and verification flag.", "`VrfAlgorand` is the VRF used in Algorand. It is ECVRF-ED25519-SHA512-Elligator2, specified in the IETF internet draft [draft-irtf-cfrg-vrf-03](https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/03/).", []string{" parameters index"}},
- "block": {"field F of block A. Fail unless A falls between txn.LastValid-1002 and txn.FirstValid (exclusive)", "", []string{" block field index"}},
-
- "switch": {"branch to the Ath label. Continue at following instruction if index A exceeds the number of labels.", "", []string{"list of labels"}},
- "match": {"given match cases from A[1] to A[N], branch to the Ith label where A[I] = B. Continue to the following instruction if no matches are found.", "`match` consumes N+1 values from the stack. Let the top stack value be B. The following N values represent an ordered list of match cases/constants (A), where the first value (A[0]) is the deepest in the stack. The immediate arguments are an ordered list of N labels (T). `match` will branch to target T[I], where A[I] = B. If there are no matches then execution continues on to the next instruction.", []string{"list of labels"}},
-
- "frame_dig": {"Nth (signed) value from the frame pointer.", "", []string{"frame slot"}},
- "frame_bury": {"replace the Nth (signed) value from the frame pointer in the stack with A", "", []string{"frame slot"}},
- "popn": {"remove N values from the top of the stack", "", []string{"stack depth"}},
-
- "box_create": {"create a box named A, of length B. Fail if the name A is empty or B exceeds 32,768. Returns 0 if A already existed, else 1", "Newly created boxes are filled with 0 bytes. `box_create` will fail if the referenced box already exists with a different size. Otherwise, existing boxes are unchanged by `box_create`.", nil},
- "box_extract": {"read C bytes from box A, starting at offset B. Fail if A does not exist, or the byte range is outside A's size.", "", nil},
- "box_replace": {"write byte-array C into box A, starting at offset B. Fail if A does not exist, or the byte range is outside A's size.", "", nil},
- "box_splice": {"set box A to contain its previous bytes up to index B, followed by D, followed by the original bytes of A that began at index B+C.", "Boxes are of constant length. If C < len(D), then len(D)-C bytes will be removed from the end. If C > len(D), zero bytes will be appended to the end to reach the box length.", nil},
- "box_del": {"delete box named A if it exists. Return 1 if A existed, 0 otherwise", "", nil},
- "box_len": {"X is the length of box A if A exists, else 0. Y is 1 if A exists, else 0.", "", nil},
- "box_get": {"X is the contents of box A if A exists, else ''. Y is 1 if A exists, else 0.", "For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `box_replace`", nil},
- "box_put": {"replaces the contents of box A with byte-array B. Fails if A exists and len(B) != len(box A). Creates A if it does not exist", "For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `box_replace`", nil},
- "box_resize": {"change the size of box named A to be of length B, adding zero bytes to end or removing bytes from the end, as needed. Fail if the name A is empty, A is not an existing box, or B exceeds 32,768.", "", nil},
+ "_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
+ []string{"return type index"}, ""},
+
+ "bnz": {"branch to TARGET if value A is not zero", "The `bnz` instruction opcode 0x40 is followed by two immediate data bytes which are a high byte first and low byte second which together form a 16 bit offset which the instruction may branch to. For a bnz instruction at `pc`, if the last element of the stack is not zero then branch to instruction at `pc + 3 + N`, else proceed to next instruction at `pc + 3`. Branch targets must be aligned instructions. (e.g. Branching to the second byte of a 2 byte op will be rejected.) Starting at v4, the offset is treated as a signed 16 bit integer allowing for backward branches and looping. In prior version (v1 to v3), branch offsets are limited to forward branches only, 0-0x7fff.\n\nAt v2 it became allowed to branch to the end of the program exactly after the last instruction: bnz to byte N (with 0-indexing) was illegal for a TEAL program with N bytes before v2, and is legal after it. This change eliminates the need for a last instruction of no-op as a branch target at the end. (Branching beyond the end--in other words, to a byte larger than N--is still illegal and will cause the program to fail.)", []string{"branch offset"}, ""},
+ "bz": {"branch to TARGET if value A is zero", "See `bnz` for details on how branches work. `bz` inverts the behavior of `bnz`.", []string{"branch offset"}, ""},
+ "b": {"branch unconditionally to TARGET", "See `bnz` for details on how branches work. `b` always jumps to the offset.", []string{"branch offset"}, ""},
+ "return": {"use A as success value; end", "", nil, ""},
+
+ "pop": {"discard A", "", nil, ""},
+ "dup": {"duplicate A", "", nil, ""},
+ "dup2": {"duplicate A and B", "", nil, ""},
+ "dupn": {"duplicate A, N times", "", []string{"copy count"}, ""},
+ "dig": {"Nth value from the top of the stack. dig 0 is equivalent to dup", "", []string{"depth"}, ""},
+ "bury": {"replace the Nth value from the top of the stack with A. bury 0 fails.", "", []string{"depth"}, ""},
+ "cover": {"remove top of stack, and place it deeper in the stack such that N elements are above it. Fails if stack depth <= N.", "", []string{"depth"}, ""},
+ "uncover": {"remove the value at depth N in the stack and shift above items down so the Nth deep value is on top of the stack. Fails if stack depth <= N.", "", []string{"depth"}, ""},
+ "swap": {"swaps A and B on stack", "", nil, ""},
+ "select": {"selects one of two values based on top-of-stack: B if C != 0, else A", "", nil, ""},
+
+ "concat": {"join A and B", "`concat` fails if the result would be greater than 4096 bytes.", nil, ""},
+ "substring": {"A range of bytes from A starting at S up to but not including E. If E < S, or either is larger than the array length, the program fails", "", []string{"start position", "end position"}, ""},
+ "substring3": {"A range of bytes from A starting at B up to but not including C. If C < B, or either is larger than the array length, the program fails", "", nil, ""},
+ "getbit": {"Bth bit of (byte-array or integer) A. If B is greater than or equal to the bit length of the value (8*byte length), the program fails", "see explanation of bit ordering in setbit", nil, ""},
+ "setbit": {"Copy of (byte-array or integer) A, with the Bth bit set to (0 or 1) C. If B is greater than or equal to the bit length of the value (8*byte length), the program fails", "When A is a uint64, index 0 is the least significant bit. Setting bit 3 to 1 on the integer 0 yields 8, or 2^3. When A is a byte array, index 0 is the leftmost bit of the leftmost byte. Setting bits 0 through 11 to 1 in a 4-byte-array of 0s yields the byte array 0xfff00000. Setting bit 3 to 1 on the 1-byte-array 0x00 yields the byte array 0x10.", nil, ""},
+ "getbyte": {"Bth byte of A, as an integer. If B is greater than or equal to the array length, the program fails", "", nil, ""},
+ "setbyte": {"Copy of A with the Bth byte set to small integer (between 0..255) C. If B is greater than or equal to the array length, the program fails", "", nil, ""},
+ "extract": {"A range of bytes from A starting at S up to but not including S+L. If L is 0, then extract to the end of the string. If S or S+L is larger than the array length, the program fails", "", []string{"start position", "length"}, ""},
+ "extract3": {"A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails", "", nil, ""},
+ "extract_uint16": {"A uint16 formed from a range of big-endian bytes from A starting at B up to but not including B+2. If B+2 is larger than the array length, the program fails", "", nil, ""},
+ "extract_uint32": {"A uint32 formed from a range of big-endian bytes from A starting at B up to but not including B+4. If B+4 is larger than the array length, the program fails", "", nil, ""},
+ "extract_uint64": {"A uint64 formed from a range of big-endian bytes from A starting at B up to but not including B+8. If B+8 is larger than the array length, the program fails", "", nil, ""},
+ "replace2": {"Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)", "", []string{"start position"}, ""},
+ "replace3": {"Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)", "", nil, ""},
+
+ "base64_decode": {"decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E", "_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.", []string{"encoding index"}, ""},
+
+ "balance": {"balance for account A, in microalgos. The balance is observed after the effects of previous transactions in the group, and after the fee for the current transaction is deducted. Changes caused by inner transactions are observable immediately following `itxn_submit`", "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.", nil, ""},
+ "min_balance": {"minimum required balance for account A, in microalgos. Required balance is affected by ASA, App, and Box usage. When creating or opting into an app, the minimum balance grows before the app code runs, therefore the increase is visible there. When deleting or closing out, the minimum balance decreases after the app executes. Changes caused by inner transactions or box usage are observable immediately following the opcode effecting the change.", "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.", nil, ""},
+ "app_opted_in": {"1 if account A is opted in to application B, else 0", "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.", nil, ""},
+ "app_local_get": {"local state of the key B in the current application in account A", "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.", nil, ""},
+ "app_local_get_ex": {"X is the local state of application B, key C in account A. Y is 1 if key existed, else 0", "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.", nil, ""},
+ "app_global_get": {"global state of the key A in the current application", "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.", nil, ""},
+ "app_global_get_ex": {"X is the global state of application A, key B. Y is 1 if key existed, else 0", "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.", nil, ""},
+ "app_local_put": {"write C to key B in account A's local state of the current application", "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.", nil, ""},
+ "app_global_put": {"write B to key A in the global state of the current application", "", nil, ""},
+ "app_local_del": {"delete key B from account A's local state of the current application", "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)", nil, ""},
+ "app_global_del": {"delete key A from the global state of the current application", "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)", nil, ""},
+ "asset_holding_get": {"X is field F from account A's holding of asset B. Y is 1 if A is opted into B, else 0", "params: Txn.Accounts offset (or, since v4, an _available_ address), asset id (or, since v4, a Txn.ForeignAssets offset). Return: did_exist flag (1 if the asset existed and 0 otherwise), value.", []string{"asset holding field index"}, ""},
+ "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"}, ""},
+ "retsub": {"pop the top instruction from the call stack and branch to it", "If the current frame was prepared by `proto A R`, `retsub` will remove the 'A' arguments from the stack, move the `R` return values down, and pop any stack locations above the relocated return values.", nil, ""},
+
+ "b+": {"A plus B. A and B are interpreted as big-endian unsigned integers", "", nil, ""},
+ "b-": {"A minus B. A and B are interpreted as big-endian unsigned integers. Fail on underflow.", "", nil, ""},
+ "b/": {"A divided by B (truncated division). A and B are interpreted as big-endian unsigned integers. Fail if B is zero.", "", nil, ""},
+ "b*": {"A times B. A and B are interpreted as big-endian unsigned integers.", "", nil, ""},
+ "b<": {"1 if A is less than B, else 0. A and B are interpreted as big-endian unsigned integers", "", nil, ""},
+ "b>": {"1 if A is greater than B, else 0. A and B are interpreted as big-endian unsigned integers", "", nil, ""},
+ "b<=": {"1 if A is less than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers", "", nil, ""},
+ "b>=": {"1 if A is greater than or equal to B, else 0. A and B are interpreted as big-endian unsigned integers", "", nil, ""},
+ "b==": {"1 if A is equal to B, else 0. A and B are interpreted as big-endian unsigned integers", "", nil, ""},
+ "b!=": {"0 if A is equal to B, else 1. A and B are interpreted as big-endian unsigned integers", "", nil, ""},
+ "b%": {"A modulo B. A and B are interpreted as big-endian unsigned integers. Fail if B is zero.", "", nil, ""},
+ "b|": {"A bitwise-or B. A and B are zero-left extended to the greater of their lengths", "", nil, ""},
+ "b&": {"A bitwise-and B. A and B are zero-left extended to the greater of their lengths", "", nil, ""},
+ "b^": {"A bitwise-xor B. A and B are zero-left extended to the greater of their lengths", "", nil, ""},
+ "b~": {"A with all bits inverted", "", nil, ""},
+
+ "bsqrt": {"The largest integer I such that I^2 <= A. A and I are interpreted as big-endian unsigned integers", "", nil, ""},
+
+ "log": {"write A to log state of the current application", "`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.", nil, ""},
+ "itxn_begin": {"begin preparation of a new inner transaction in a new transaction group", "`itxn_begin` initializes Sender to the application address; Fee to the minimum allowable, taking into account MinTxnFee and credit from overpaying in earlier transactions; FirstValid/LastValid to the values in the invoking transaction, and all other fields to zero or empty values.", nil, ""},
+ "itxn_next": {"begin preparation of a new inner transaction in the same transaction group", "`itxn_next` initializes the transaction exactly as `itxn_begin` does", nil, ""},
+ "itxn_field": {"set field F of the current inner transaction to A", "`itxn_field` fails if A is of the wrong type for F, including a byte array of the wrong size for use as an address when F is an address field. `itxn_field` also fails if A is an account, asset, or app that is not _available_, or an attempt is made extend an array field beyond the limit imposed by consensus parameters. (Addresses set into asset params of acfg transactions need not be _available_.)", []string{"transaction field index"}, ""},
+ "itxn_submit": {"execute the current inner transaction group. Fail if executing this group would exceed the inner transaction limit, or if any transaction in the group fails.", "`itxn_submit` resets the current transaction so that it can not be resubmitted. A new `itxn_begin` is required to prepare another inner transaction.", nil, ""},
+
+ "vrf_verify": {"Verify the proof B of message A against pubkey C. Returns vrf output and verification flag.", "`VrfAlgorand` is the VRF used in Algorand. It is ECVRF-ED25519-SHA512-Elligator2, specified in the IETF internet draft [draft-irtf-cfrg-vrf-03](https://datatracker.ietf.org/doc/draft-irtf-cfrg-vrf/03/).", []string{" parameters index"}, ""},
+ "block": {"field F of block A. Fail unless A falls between txn.LastValid-1002 and txn.FirstValid (exclusive)", "", []string{" block field index"}, ""},
+
+ "switch": {"branch to the Ath label. Continue at following instruction if index A exceeds the number of labels.", "", []string{"list of labels"}, ""},
+ "match": {"given match cases from A[1] to A[N], branch to the Ith label where A[I] = B. Continue to the following instruction if no matches are found.", "`match` consumes N+1 values from the stack. Let the top stack value be B. The following N values represent an ordered list of match cases/constants (A), where the first value (A[0]) is the deepest in the stack. The immediate arguments are an ordered list of N labels (T). `match` will branch to target T[I], where A[I] = B. If there are no matches then execution continues on to the next instruction.", []string{"list of labels"}, ""},
+
+ "frame_dig": {"Nth (signed) value from the frame pointer.", "", []string{"frame slot"}, ""},
+ "frame_bury": {"replace the Nth (signed) value from the frame pointer in the stack with A", "", []string{"frame slot"}, ""},
+ "popn": {"remove N values from the top of the stack", "", []string{"stack depth"}, ""},
+
+ "box_create": {"create a box named A, of length B. Fail if the name A is empty or B exceeds 32,768. Returns 0 if A already existed, else 1", "Newly created boxes are filled with 0 bytes. `box_create` will fail if the referenced box already exists with a different size. Otherwise, existing boxes are unchanged by `box_create`.", nil, ""},
+ "box_extract": {"read C bytes from box A, starting at offset B. Fail if A does not exist, or the byte range is outside A's size.", "", nil, ""},
+ "box_replace": {"write byte-array C into box A, starting at offset B. Fail if A does not exist, or the byte range is outside A's size.", "", nil, ""},
+ "box_splice": {"set box A to contain its previous bytes up to index B, followed by D, followed by the original bytes of A that began at index B+C.", "Boxes are of constant length. If C < len(D), then len(D)-C bytes will be removed from the end. If C > len(D), zero bytes will be appended to the end to reach the box length.", nil, ""},
+ "box_del": {"delete box named A if it exists. Return 1 if A existed, 0 otherwise", "", nil, ""},
+ "box_len": {"X is the length of box A if A exists, else 0. Y is 1 if A exists, else 0.", "", nil, ""},
+ "box_get": {"X is the contents of box A if A exists, else ''. Y is 1 if A exists, else 0.", "For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `box_replace`", nil, ""},
+ "box_put": {"replaces the contents of box A with byte-array B. Fails if A exists and len(B) != len(box A). Creates A if it does not exist", "For boxes that exceed 4,096 bytes, consider `box_create`, `box_extract`, and `box_replace`", nil, ""},
+ "box_resize": {"change the size of box named A to be of length B, adding zero bytes to end or removing bytes from the end, as needed. Fail if the name A is empty, A is not an existing box, or B exceeds 32,768.", "", nil, ""},
}
-// OpDoc returns a description of the op
-func OpDoc(opName string) string {
- return opDescByName[opName].Short
+// OpDescOf returns the OpDesc for a mnemonic opcode
+func OpDescOf(opName string) OpDesc {
+ return opDescByName[opName]
}
// OpImmediateDetails contains information about the an immediate argument for
@@ -342,18 +343,13 @@ func OpImmediateDetailsFromSpec(spec OpSpec) []OpImmediateDetails {
}
if imm.Group != nil {
- details[idx].Reference = imm.Group.Name
+ details[idx].Reference = imm.Group.Heading()
}
}
return details
}
-// OpDocExtra returns extra documentation text about an op
-func OpDocExtra(opName string) string {
- return opDescByName[opName].Extra
-}
-
// OpGroups is groupings of ops for documentation purposes. The order
// here is the order args opcodes are presented, so place related
// opcodes consecutively, even if their opcode values are not.
@@ -365,7 +361,10 @@ var OpGroups = map[string][]string{
"Cryptography": {"sha256", "keccak256", "sha512_256", "sha3_256", "sha512", "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", "mimc"},
"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", "voter_params_get", "online_stake", "log", "block"},
+ "Block Access": {"online_stake", "log", "block"},
+ "Account Access": {"balance", "min_balance", "acct_params_get", "voter_params_get"},
+ "Asset Access": {"asset_holding_get", "asset_params_get"},
+ "Application Access": {"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", "app_params_get"},
"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"},
}
@@ -380,40 +379,30 @@ type VerCost struct {
Cost string
}
-// TypeNameDescriptions contains extra description about a low level
-// protocol transaction Type string, and provide a friendlier type
-// constant name in assembler.
+// TypeNameDescriptions contains descriptions about low level
+// protocol transaction types.
var TypeNameDescriptions = map[string]string{
- string(protocol.UnknownTx): "Unknown type. Invalid transaction",
- string(protocol.PaymentTx): "Payment",
- string(protocol.KeyRegistrationTx): "KeyRegistration",
- string(protocol.AssetConfigTx): "AssetConfig",
- string(protocol.AssetTransferTx): "AssetTransfer",
- string(protocol.AssetFreezeTx): "AssetFreeze",
- string(protocol.ApplicationCallTx): "ApplicationCall",
-}
-
-var onCompletionDescriptions = map[OnCompletionConstType]string{
- NoOp: "Only execute the `ApprovalProgram` associated with this application ID, with no additional effects.",
- OptIn: "Before executing the `ApprovalProgram`, allocate local state for this application into the sender's account data.",
- CloseOut: "After executing the `ApprovalProgram`, clear any local state for this application out of the sender's account data.",
- ClearState: "Don't execute the `ApprovalProgram`, and instead execute the `ClearStateProgram` (which may not reject this transaction). Additionally, clear any local state for this application out of the sender's account data as in `CloseOutOC`.",
- UpdateApplication: "After executing the `ApprovalProgram`, replace the `ApprovalProgram` and `ClearStateProgram` associated with this application ID with the programs specified in this transaction.",
- DeleteApplication: "After executing the `ApprovalProgram`, delete the application parameters from the account data of the application's creator.",
+ string(protocol.UnknownTx): "Unknown type, invalid transaction",
+ string(protocol.PaymentTx): "ALGO transfers (payment)",
+ string(protocol.KeyRegistrationTx): "Consensus keys registration",
+ string(protocol.AssetConfigTx): "Asset creation and configuration",
+ string(protocol.AssetTransferTx): "Asset transfer",
+ string(protocol.AssetFreezeTx): "Asset freeze and unfreeze",
+ string(protocol.ApplicationCallTx): "Application calls",
+ string(protocol.StateProofTx): "State Proof",
+ string(protocol.HeartbeatTx): "Consensus heartbeat",
}
-// OnCompletionDescription returns extra description about OnCompletion constants
-func OnCompletionDescription(value uint64) string {
- desc, ok := onCompletionDescriptions[OnCompletionConstType(value)]
- if ok {
- return desc
- }
- return "invalid constant value"
+// OnCompletionDescriptions end up in the spec, describing what happens for each OnCompletion value.
+var OnCompletionDescriptions = map[string]string{
+ NoOp.String(): "_Only_ execute the Approval Program associated with the _application ID_, with no additional effects.",
+ OptIn.String(): "_Before_ executing the Approval Program, allocate _local state_ for this _application ID_ into the _sender_'s account data.",
+ CloseOut.String(): "_After_ executing the Approval Program, clear any _local state_ for this _application ID_ out of the _sender_'s account data.",
+ ClearState.String(): "_Do not_ execute the Approval Program, and instead execute the Clear State Program (which may not reject this transaction). Additionally, clear any _local state_ for the _application ID_ out of the _sender_’s account data (as in `CloseOutOC`).",
+ UpdateApplication.String(): "_After_ executing the Approval Program, _replace_ the Approval Program and Clear State Program associated with the _application ID_ with the programs specified in this transaction.",
+ DeleteApplication.String(): "_After_ executing the Approval Program, _delete_ the parameters of with the _application ID_ from the account data of the application’s creator.",
}
-// OnCompletionPreamble describes what the OnCompletion constants represent.
-const OnCompletionPreamble = "An application transaction must indicate the action to be taken following the execution of its approvalProgram or clearStateProgram. The constants below describe the available actions."
-
func addExtra(original string, extra string) string {
if len(original) == 0 {
return extra
diff --git a/data/transactions/logic/doc_test.go b/data/transactions/logic/doc_test.go
index f890144660..a1e3512fef 100644
--- a/data/transactions/logic/doc_test.go
+++ b/data/transactions/logic/doc_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -43,7 +43,7 @@ func TestOpDocs(t *testing.T) {
assert.True(t, seen, "opDescByName is missing description for %#v", op)
}
- require.Len(t, onCompletionDescriptions, len(OnCompletionNames))
+ require.Len(t, OnCompletionDescriptions, len(OnCompletionNames))
require.Len(t, TypeNameDescriptions, len(TxnTypeNames))
}
@@ -79,9 +79,9 @@ func TestOpDoc(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
- xd := OpDoc("txn")
+ xd := OpDescOf("txn")
require.NotEmpty(t, xd)
- xd = OpDoc("NOT AN INSTRUCTION")
+ xd = OpDescOf("NOT AN INSTRUCTION")
require.Empty(t, xd)
}
@@ -100,7 +100,7 @@ func TestOpImmediateDetails(t *testing.T) {
require.Equal(t, d.Encoding, imm.kind.String())
if imm.Group != nil {
- require.Equal(t, d.Reference, imm.Group.Name)
+ require.Equal(t, d.Reference, imm.Group.Heading())
}
}
}
@@ -110,19 +110,8 @@ func TestOpDocExtra(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
- xd := OpDocExtra("bnz")
- require.NotEmpty(t, xd)
- xd = OpDocExtra("-")
- require.Empty(t, xd)
-}
-
-func TestOnCompletionDescription(t *testing.T) {
- partitiontest.PartitionTest(t)
- t.Parallel()
-
- desc := OnCompletionDescription(0)
- require.Equal(t, "Only execute the `ApprovalProgram` associated with this application ID, with no additional effects.", desc)
-
- desc = OnCompletionDescription(100)
- require.Equal(t, "invalid constant value", desc)
+ xd := OpDescOf("bnz")
+ require.NotEmpty(t, xd.Extra)
+ xd = OpDescOf("-")
+ require.Empty(t, xd.Extra)
}
diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go
index ca1f2e07cf..3ab732b8d8 100644
--- a/data/transactions/logic/eval.go
+++ b/data/transactions/logic/eval.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -2967,6 +2967,8 @@ func (cx *EvalContext) appParamsToValue(params *basics.AppParams, fs appParamsFi
sv.Uint = uint64(params.ExtraProgramPages)
case AppVersion:
sv.Uint = params.Version
+ case AppSizeSponsor:
+ sv.Bytes = params.SizeSponsor[:]
default:
// The pseudo fields AppCreator and AppAddress are handled before this method
return sv, fmt.Errorf("invalid app_params_get field %d", fs.field)
@@ -2984,12 +2986,12 @@ func TxnFieldToTealValue(txn *transactions.Transaction, groupIndex int, field Tx
return basics.TealValue{}, fmt.Errorf("negative groupIndex %d", groupIndex)
}
var cx EvalContext
- stxnad := &transactions.SignedTxnWithAD{SignedTxn: transactions.SignedTxn{Txn: *txn}}
+ stxnad := transactions.SignedTxn{Txn: *txn}.WithAD()
fs, ok := txnFieldSpecByField(field)
if !ok {
return basics.TealValue{}, fmt.Errorf("invalid field %s", field)
}
- sv, err := cx.txnFieldToStack(stxnad, &fs, arrayFieldIdx, groupIndex, inner)
+ sv, err := cx.txnFieldToStack(&stxnad, &fs, arrayFieldIdx, groupIndex, inner)
return sv.ToTealValue(), err
}
diff --git a/data/transactions/logic/evalAppTxn_test.go b/data/transactions/logic/evalAppTxn_test.go
index 23f9701731..f1a645ffef 100644
--- a/data/transactions/logic/evalAppTxn_test.go
+++ b/data/transactions/logic/evalAppTxn_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -19,6 +19,7 @@ package logic_test
import (
"encoding/hex"
"fmt"
+ "slices"
"strconv"
"strings"
"testing"
@@ -132,7 +133,7 @@ func TestFieldLimits(t *testing.T) {
ep, _, _ := MakeSampleEnv()
- intProgram := "itxn_begin; int %d; itxn_field %s; int 1"
+ intProgram := "itxn_begin; int %v; itxn_field %s; int 1"
goodInt := func(field string, value interface{}) {
TestApp(t, fmt.Sprintf(intProgram, value, field), ep)
}
@@ -168,7 +169,10 @@ func TestFieldLimits(t *testing.T) {
// header
badInt("TypeEnum", 0)
- testInt("TypeEnum", len(TxnTypeNames)-1)
+ testInt("TypeEnum", slices.Index(TxnTypeNames[:], "appl")) // later ints are illegal for itxn
+ badInt("TypeEnum", "hb")
+ badInt("TypeEnum", "stpf")
+ badInt("TypeEnum", 0)
//keyreg
testBool("Nonparticipation")
//acfg
@@ -1308,7 +1312,43 @@ func TestApplSubmission(t *testing.T) {
// Can't set epp when app id is given
tx.ForeignApps = append(tx.ForeignApps, basics.AppIndex(7))
TestApp(t, p+`int 1; itxn_field ExtraProgramPages;
- int 7; itxn_field ApplicationID`+s, ep, "immutable")
+ int 7; itxn_field ApplicationID`+s, ep, "inappropriate non-zero tx.Extra")
+ // nor can global schema be set
+ TestApp(t, p+`int 1; itxn_field GlobalNumUint;
+ int 7; itxn_field ApplicationID`+s, ep, "inappropriate non-zero tx.Global")
+ // nor can local schema be set
+ TestApp(t, p+`int 1; itxn_field LocalNumUint;
+ int 7; itxn_field ApplicationID`+s, ep, "inappropriate non-zero tx.Local")
+
+ // When performing an update, we can set epp and (global only) schema
+ ledger.NewApp(tx.Receiver, 7, basics.AppParams{
+ ApprovalProgram: ops.Program, // which is "int 1"
+ })
+ TestApp(t, p+a+`int UpdateApplication; itxn_field OnCompletion;
+ int 1; itxn_field ExtraProgramPages;
+ int 7; itxn_field ApplicationID`+s, ep)
+ // global schema can be set
+ TestApp(t, p+a+`int UpdateApplication; itxn_field OnCompletion;
+ int 1; itxn_field GlobalNumUint;
+ int 7; itxn_field ApplicationID`+s, ep)
+ // but local schema still cannot be set
+ TestApp(t, p+a+`int UpdateApplication; itxn_field OnCompletion;
+ int 1; itxn_field LocalNumUint;
+ int 7; itxn_field ApplicationID`+s, ep, "inappropriate non-zero tx.Local")
+
+ // Even when performing an update, they cannot be set (in old consensus)
+ ep.Proto.AppSizeUpdates = false
+ TestApp(t, p+a+`int UpdateApplication; itxn_field OnCompletion;
+ int 1; itxn_field ExtraProgramPages;
+ int 7; itxn_field ApplicationID`+s, ep, "inappropriate non-zero tx.Extra")
+ // global schema can be set
+ TestApp(t, p+a+`int UpdateApplication; itxn_field OnCompletion;
+ int 1; itxn_field GlobalNumUint;
+ int 7; itxn_field ApplicationID`+s, ep, "inappropriate non-zero tx.Global")
+ // but local schema still cannot be set
+ TestApp(t, p+a+`int UpdateApplication; itxn_field OnCompletion;
+ int 1; itxn_field LocalNumUint;
+ int 7; itxn_field ApplicationID`+s, ep, "inappropriate non-zero tx.Local")
TestApp(t, p+a+"int 20; itxn_field GlobalNumUint; int 11; itxn_field GlobalNumByteSlice"+s,
ep, "too large")
@@ -1316,7 +1356,9 @@ func TestApplSubmission(t *testing.T) {
ep, "too large")
}
-func TestInnerApplCreate(t *testing.T) {
+// TestInnerApplLifecycle tests creation, update, and deletion of apps with
+// inner transactions.
+func TestInnerApplLifecycle(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
@@ -1345,6 +1387,7 @@ itxn_submit
int 1
`)
+ // Can't examine it without ForeignApps
test("int 5000; app_params_get AppGlobalNumByteSlice; assert; int 0; ==; assert",
"unavailable App 5000")
@@ -1358,7 +1401,8 @@ int 1
// Can't call it either
test(call, "unavailable App 5000")
- tx.ForeignApps = []basics.AppIndex{basics.AppIndex(5000)}
+ // Add to ForeignApps, then we can examine and call it.
+ tx.ForeignApps = []basics.AppIndex{5000}
test(`
int 5000; app_params_get AppGlobalNumByteSlice; assert; int 0; ==; assert
int 5000; app_params_get AppGlobalNumUint; assert; int 1; ==; assert
@@ -1387,10 +1431,33 @@ int 1
test(update)
if v >= 12 {
- // Version starts at 0
+ // Version is up to 1
test(`int 5000; app_params_get AppVersion; assert; int 1; ==`)
}
+ updateSchema := `
+itxn_begin
+int appl; itxn_field TypeEnum
+int 5000; itxn_field ApplicationID
+` + approve + `; itxn_field ApprovalProgram
+` + approve + `; itxn_field ClearStateProgram
+int 2; itxn_field GlobalNumUint
+int UpdateApplication; itxn_field OnCompletion
+itxn_submit
+int 1
+`
+ test(updateSchema)
+ if v >= 12 {
+ // Version is up to 2
+ test(`int 5000; app_params_get AppVersion; assert; int 2; ==`)
+ }
+
+ test(`
+int 5000; app_params_get AppGlobalNumUint; assert; int 2; ==; assert
+int 1
+`)
+
+ // Delete it
test(`
itxn_begin
int appl; itxn_field TypeEnum
@@ -1405,7 +1472,6 @@ int 1
// Can't call it either
test(call, "no app 5000")
-
})
}
@@ -3023,7 +3089,7 @@ func hexProgram(t *testing.T, source string, v uint64) string {
return "0x" + hex.EncodeToString(TestProg(t, source, v).Program)
}
-// TestCreateAndSeeApp checks that an app can be created in an inner txn, and then
+// TestCreateSeeApp checks that an app can be created in an inner txn, and then
// the address for it can be looked up.
func TestCreateSeeApp(t *testing.T) {
partitiontest.PartitionTest(t)
diff --git a/data/transactions/logic/evalBench_test.go b/data/transactions/logic/evalBench_test.go
index 6a5bdf1baf..229f1780bc 100644
--- a/data/transactions/logic/evalBench_test.go
+++ b/data/transactions/logic/evalBench_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/evalStateful_test.go b/data/transactions/logic/evalStateful_test.go
index 63733389d3..2509544a94 100644
--- a/data/transactions/logic/evalStateful_test.go
+++ b/data/transactions/logic/evalStateful_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -45,8 +45,6 @@ func makeApp(li uint64, lb uint64, gi uint64, gb uint64) basics.AppParams {
LocalStateSchema: basics.StateSchema{NumUint: li, NumByteSlice: lb},
GlobalStateSchema: basics.StateSchema{NumUint: gi, NumByteSlice: gb},
},
- ExtraProgramPages: 0,
- Version: 0,
}
}
@@ -363,11 +361,16 @@ log
Freeze: tx.Receiver,
Clawback: tx.Receiver,
}
- algoValue := basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
ledger.NewAccount(tx.Sender, 1)
- ledger.NewApp(tx.Sender, 100, basics.AppParams{})
+ ledger.NewApp(tx.Sender, 100, basics.AppParams{
+ StateSchemas: basics.StateSchemas{
+ GlobalStateSchema: basics.StateSchema{
+ NumUint: 1,
+ },
+ },
+ })
ledger.NewLocals(tx.Sender, 100)
- ledger.NewLocal(tx.Sender, 100, "ALGO", algoValue)
+ ledger.NewLocal(tx.Sender, 100, "ALGO", 0x77)
ledger.NewAsset(tx.Sender, 5, params)
if mode == ModeSig {
@@ -825,7 +828,7 @@ err
exist:
byte "ALGO"
==`
- ledger.NewLocal(now.TxnGroup[0].Txn.Receiver, 100, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
+ ledger.NewLocal(now.TxnGroup[0].Txn.Receiver, 100, string(protocol.PaymentTx), "ALGO")
testApp(t, text, now)
testApp(t, strings.Replace(text, "int 1 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui01\"", -1), now)
@@ -845,7 +848,7 @@ byte "ALGO"
// opt into 123, and try again
ledger.NewApp(now.TxnGroup[0].Txn.Receiver, 123, basics.AppParams{})
ledger.NewLocals(now.TxnGroup[0].Txn.Receiver, 123)
- ledger.NewLocal(now.TxnGroup[0].Txn.Receiver, 123, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
+ ledger.NewLocal(now.TxnGroup[0].Txn.Receiver, 123, string(protocol.PaymentTx), "ALGO")
testApp(t, strings.Replace(text, "int 100 // app id", "int 123", -1), now)
testApp(t, strings.Replace(text, "int 100 // app id", "int 0", -1), now)
@@ -868,7 +871,7 @@ exist:
byte "ALGO"
==`
- ledger.NewLocal(now.TxnGroup[0].Txn.Sender, 100, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
+ ledger.NewLocal(now.TxnGroup[0].Txn.Sender, 100, string(protocol.PaymentTx), "ALGO")
testApp(t, text, now)
testApp(t, strings.Replace(text, "int 0 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00\"", -1), now)
testApp(t, strings.Replace(text, "int 0 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui02\"", -1), now,
@@ -888,7 +891,7 @@ byte "ALGO"
==`
ledger.NewLocals(now.TxnGroup[0].Txn.Sender, 56)
- ledger.NewLocal(now.TxnGroup[0].Txn.Sender, 56, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
+ ledger.NewLocal(now.TxnGroup[0].Txn.Sender, 56, string(protocol.PaymentTx), "ALGO")
testApp(t, text, now)
// check app_local_get
@@ -898,7 +901,7 @@ app_local_get
byte "ALGO"
==`
- ledger.NewLocal(now.TxnGroup[0].Txn.Sender, 100, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
+ ledger.NewLocal(now.TxnGroup[0].Txn.Sender, 100, string(protocol.PaymentTx), "ALGO")
now.TxnGroup[0].Txn.ApplicationID = 100
testApp(t, text, now)
testApp(t, strings.Replace(text, "int 0 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00\"", -1), now)
@@ -915,7 +918,7 @@ app_local_get
int 0
==`
- ledger.NewLocal(now.TxnGroup[0].Txn.Sender, 100, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
+ ledger.NewLocal(now.TxnGroup[0].Txn.Sender, 100, string(protocol.PaymentTx), "ALGO")
testApp(t, text, now)
}
@@ -1074,7 +1077,7 @@ byte "ALGO"
testApp(t, text, now, "err opcode")
- ledger.NewGlobal(100, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
+ ledger.NewGlobal(100, string(protocol.PaymentTx), "ALGO")
testApp(t, text, now)
@@ -1090,9 +1093,14 @@ byte "ALGO"
text = "byte 0x414c474f55; app_global_get; int 0; =="
ledger.NewLocals(now.TxnGroup[0].Txn.Sender, 100)
- ledger.NewLocal(now.TxnGroup[0].Txn.Sender, 100, string(protocol.PaymentTx), basics.TealValue{Type: basics.TealBytesType, Bytes: "ALGO"})
+ ledger.NewLocal(now.TxnGroup[0].Txn.Sender, 100, string(protocol.PaymentTx), "ALGO")
testApp(t, text, now)
+ ledger.SetAppGlobalSchema(100, basics.StateSchema{
+ NumUint: 1, // we're about to add an int
+ NumByteSlice: 1, // "pay" is still there
+ })
+
text = `
byte 0x41414141
int 4141
@@ -1534,7 +1542,7 @@ func TestAppDisambiguation(t *testing.T) {
ExtraProgramPages: uint32(appID),
})
ledger.NewLocals(tx.Sender, appID)
- ledger.NewLocal(tx.Sender, appID, "x", basics.TealValue{Type: basics.TealUintType, Uint: uint64(appID) * 10})
+ ledger.NewLocal(tx.Sender, appID, "x", uint64(appID)*10)
}
makeIdentifiableApp(1)
makeIdentifiableApp(20)
@@ -1836,8 +1844,8 @@ intc_1
require.Contains(t, err.Error(), "err opcode") // no such key
}
- ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", basics.TealValue{Type: basics.TealUintType, Uint: 0x77})
- ledger.NewLocal(txn.Txn.Sender, 100, "ALGOA", basics.TealValue{Type: basics.TealUintType, Uint: 1})
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGO", 0x77)
+ ledger.NewLocal(txn.Txn.Sender, 100, "ALGOA", 1)
ledger.Reset()
pass, err := EvalApp(ops.Program, 0, 100, ep)
@@ -1932,8 +1940,7 @@ int 0x77
ledger.NoLocal(txn.Sender, 100, "ALGOA")
ledger.NoLocal(txn.Sender, 100, "ALGO")
- algoValue := basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
- ledger.NewLocal(txn.Sender, 100, "ALGO", algoValue)
+ ledger.NewLocal(txn.Sender, 100, "ALGO", 0x77)
delta, _ = testApp(t, source, ep)
require.Empty(t, delta.GlobalDelta)
@@ -1961,7 +1968,7 @@ exist2:
==
`
ledger.Reset()
- ledger.NewLocal(txn.Sender, 100, "ALGO", algoValue)
+ ledger.NewLocal(txn.Sender, 100, "ALGO", 0x77)
ledger.NoLocal(txn.Sender, 100, "ALGOA")
if ep.Proto.LogicSigVersion < directRefEnabledVersion {
@@ -1979,7 +1986,7 @@ app_local_put
int 1
`
ledger.Reset()
- ledger.NewLocal(txn.Sender, 100, "ALGO", algoValue)
+ ledger.NewLocal(txn.Sender, 100, "ALGO", 0x77)
ledger.NoLocal(txn.Sender, 100, "ALGOA")
if ep.Proto.LogicSigVersion < directRefEnabledVersion {
@@ -2009,7 +2016,7 @@ int 0x78
==
`
ledger.Reset()
- ledger.NewLocal(txn.Sender, 100, "ALGO", algoValue)
+ ledger.NewLocal(txn.Sender, 100, "ALGO", 0x77)
ledger.NoLocal(txn.Sender, 100, "ALGOA")
if ep.Proto.LogicSigVersion < directRefEnabledVersion {
@@ -2037,7 +2044,7 @@ int 0x78 // value
app_local_put
`
ledger.Reset()
- ledger.NewLocal(txn.Sender, 100, "ALGO", algoValue)
+ ledger.NewLocal(txn.Sender, 100, "ALGO", 0x77)
ledger.NoLocal(txn.Sender, 100, "ALGOA")
if ep.Proto.LogicSigVersion < directRefEnabledVersion {
@@ -2071,7 +2078,7 @@ app_local_put
int 1
`
ledger.Reset()
- ledger.NewLocal(txn.Sender, 100, "ALGO", algoValue)
+ ledger.NewLocal(txn.Sender, 100, "ALGO", 0x77)
ledger.NoLocal(txn.Sender, 100, "ALGOA")
ledger.NewAccount(txn.Receiver, 500)
@@ -2114,6 +2121,10 @@ func TestAppLocalGlobalErrorCases(t *testing.T) {
}
testApp(t, notrack(fmt.Sprintf(`byte "%v"; int 1;`+g+`int 1`, strings.Repeat("v", ep.Proto.MaxAppKeyLen+1))), ep, "key too long")
+ testApp(t, fmt.Sprintf(`byte "%v"; int 1;`+g+`int 1`, strings.Repeat("v", ep.Proto.MaxAppKeyLen)), ep, "app 888 global schema")
+
+ ledger.SetAppGlobalSchema(888, basics.StateSchema{NumUint: 1})
+
testApp(t, fmt.Sprintf(`byte "%v"; int 1;`+g+`int 1`, strings.Repeat("v", ep.Proto.MaxAppKeyLen)), ep)
ledger.NewLocals(tx.Sender, 888)
@@ -2123,6 +2134,10 @@ func TestAppLocalGlobalErrorCases(t *testing.T) {
testApp(t, fmt.Sprintf(`byte "foo"; byte "%v";`+g+`int 1`, strings.Repeat("v", ep.Proto.MaxAppBytesValueLen+1)), ep, "value too long for key")
+ testApp(t, fmt.Sprintf(`byte "foo"; byte "%v";`+g+`int 1`, strings.Repeat("v", ep.Proto.MaxAppBytesValueLen)), ep, "app 888 global schema") // because we tried to set a byte value
+
+ ledger.SetAppGlobalSchema(888, basics.StateSchema{NumByteSlice: 1, NumUint: 1})
+
testApp(t, fmt.Sprintf(`byte "foo"; byte "%v";`+g+`int 1`, strings.Repeat("v", ep.Proto.MaxAppBytesValueLen)), ep)
testApp(t, fmt.Sprintf(sender+`byte "foo"; byte "%v";`+l+`int 1`, strings.Repeat("v", ep.Proto.MaxAppBytesValueLen+1)), ep, "value too long for key")
@@ -2167,7 +2182,7 @@ int 0x77
if name == "read" {
testAppBytes(t, ops.Program, ep, "err opcode") // no such key
}
- ledger.NewGlobal(100, "ALGO", basics.TealValue{Type: basics.TealUintType, Uint: 0x77})
+ ledger.NewGlobal(100, "ALGO", 0x77)
ledger.Reset()
@@ -2248,7 +2263,11 @@ int 0x77
txn.ApplicationID = 100
txn.ForeignApps = []basics.AppIndex{txn.ApplicationID}
ledger.NewAccount(txn.Sender, 1)
- ledger.NewApp(txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(txn.Sender, 100, basics.AppParams{
+ StateSchemas: basics.StateSchemas{
+ GlobalStateSchema: basics.StateSchema{NumUint: 1, NumByteSlice: 1},
+ },
+ })
if bySlot {
// 100 is in the ForeignApps array, name it by slot
@@ -2286,8 +2305,7 @@ int 0x77
ledger.NoGlobal(100, "ALGOA")
ledger.NoGlobal(100, "ALGO")
- algoValue := basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
- ledger.NewGlobal(100, "ALGO", algoValue)
+ ledger.NewGlobal(100, "ALGO", 0x77)
delta, _ = testApp(t, source, ep)
require.Empty(t, delta.GlobalDelta)
@@ -2311,7 +2329,7 @@ int 0x77
`
ledger.Reset()
ledger.NoGlobal(100, "ALGOA")
- ledger.NewGlobal(100, "ALGO", algoValue)
+ ledger.NewGlobal(100, "ALGO", 0x77)
delta, _ = testApp(t, source, ep)
require.Empty(t, delta.GlobalDelta)
@@ -2351,7 +2369,7 @@ byte "ALGO"
`
ledger.Reset()
ledger.NoGlobal(100, "ALGOA")
- ledger.NewGlobal(100, "ALGO", algoValue)
+ ledger.NewGlobal(100, "ALGO", 0x77)
delta, _ = testApp(t, source, ep)
@@ -2415,8 +2433,7 @@ byte "myval"
ledger.NewApp(txn.Receiver, 101, basics.AppParams{})
ledger.NewApp(txn.Receiver, 100, basics.AppParams{}) // this keeps current app id = 100
- algoValue := basics.TealValue{Type: basics.TealBytesType, Bytes: "myval"}
- ledger.NewGlobal(101, "mykey", algoValue)
+ ledger.NewGlobal(101, "mykey", "myval")
delta, _ = testApp(t, source, ep)
require.Empty(t, delta.GlobalDelta)
@@ -2449,7 +2466,11 @@ int 7
testLogicRange(t, 3, 0, func(t *testing.T, ep *EvalParams, txn *transactions.Transaction, ledger *Ledger) {
txn.ApplicationID = 100
ledger.NewAccount(txn.Sender, 1)
- ledger.NewApp(txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(txn.Sender, 100, basics.AppParams{
+ StateSchemas: basics.StateSchemas{
+ GlobalStateSchema: basics.StateSchema{NumUint: 1},
+ },
+ })
delta, _ := testApp(t, source, ep)
require.Empty(t, delta.LocalDeltas)
@@ -2491,18 +2512,18 @@ int 1
ledger.NewAccount(txn.Sender, 1)
txn.ApplicationID = 100
- ledger.NewApp(txn.Sender, 100, basics.AppParams{})
+ ledger.NewApp(txn.Sender, 100, basics.AppParams{
+ StateSchemas: basics.StateSchemas{
+ GlobalStateSchema: basics.StateSchema{NumUint: 1, NumByteSlice: 1},
+ },
+ })
delta, _ := testApp(t, source, ep)
require.Len(t, delta.GlobalDelta, 2)
require.Empty(t, delta.LocalDeltas)
-
ledger.Reset()
- ledger.NoGlobal(100, "ALGOA")
- ledger.NoGlobal(100, "ALGO")
- algoValue := basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
- ledger.NewGlobal(100, "ALGO", algoValue)
+ ledger.NewGlobal(100, "ALGO", 0x77)
// check delete existing
source = `byte "ALGO"
@@ -2531,14 +2552,12 @@ app_global_get_ex
require.Equal(t, uint64(0), vd.Uint)
require.Equal(t, "", vd.Bytes)
require.Equal(t, 0, len(delta.LocalDeltas))
-
ledger.Reset()
- ledger.NoGlobal(100, "ALGOA")
- ledger.NoGlobal(100, "ALGO")
- ledger.NewGlobal(100, "ALGO", algoValue)
+ ledger.NewGlobal(100, "ALGO", 0x77)
// check delete and write non-existing
+ ledger.SetAppGlobalSchema(100, basics.StateSchema{NumUint: 2})
source = `byte "ALGOA"
app_global_del
int 0
@@ -2561,7 +2580,7 @@ app_global_put
ledger.NoGlobal(100, "ALGOA")
ledger.NoGlobal(100, "ALGO")
- ledger.NewGlobal(100, "ALGO", algoValue)
+ ledger.NewGlobal(100, "ALGO", 0x77)
// check delete and write existing
source = `byte "ALGO"
@@ -2582,7 +2601,7 @@ int 1
ledger.NoGlobal(100, "ALGOA")
ledger.NoGlobal(100, "ALGO")
- ledger.NewGlobal(100, "ALGO", algoValue)
+ ledger.NewGlobal(100, "ALGO", 0x77)
// check delete,write,delete existing
source = `byte "ALGO"
@@ -2605,7 +2624,7 @@ int 1
ledger.NoGlobal(100, "ALGOA")
ledger.NoGlobal(100, "ALGO")
- ledger.NewGlobal(100, "ALGO", algoValue)
+ ledger.NewGlobal(100, "ALGO", 0x77)
// check delete, write, delete non-existing
source = `byte "ALGOA" // key "ALGOA"
@@ -2693,8 +2712,7 @@ int 1
ledger.NoLocal(txn.Receiver, 100, "ALGOA")
ledger.NoLocal(txn.Receiver, 100, "ALGO")
- algoValue := basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
- ledger.NewLocal(txn.Sender, 100, "ALGO", algoValue)
+ ledger.NewLocal(txn.Sender, 100, "ALGO", 0x77)
// check delete existing
source = `txn Sender
@@ -2722,7 +2740,7 @@ app_local_get_ex
ledger.NoLocal(txn.Sender, 100, "ALGOA")
ledger.NoLocal(txn.Sender, 100, "ALGO")
- ledger.NewLocal(txn.Sender, 100, "ALGO", algoValue)
+ ledger.NewLocal(txn.Sender, 100, "ALGO", 0x77)
// check delete and write non-existing
source = `txn Sender
@@ -2753,7 +2771,7 @@ app_local_put
ledger.NoLocal(txn.Sender, 100, "ALGOA")
ledger.NoLocal(txn.Sender, 100, "ALGO")
- ledger.NewLocal(txn.Sender, 100, "ALGO", algoValue)
+ ledger.NewLocal(txn.Sender, 100, "ALGO", 0x77)
// check delete and write existing
source = `txn Sender
@@ -2780,7 +2798,7 @@ int 1
ledger.NoLocal(txn.Sender, 100, "ALGOA")
ledger.NoLocal(txn.Sender, 100, "ALGO")
- ledger.NewLocal(txn.Sender, 100, "ALGO", algoValue)
+ ledger.NewLocal(txn.Sender, 100, "ALGO", 0x77)
// check delete,write,delete existing
source = `txn Sender
@@ -2810,7 +2828,7 @@ int 1
ledger.NoLocal(txn.Sender, 100, "ALGOA")
ledger.NoLocal(txn.Sender, 100, "ALGO")
- ledger.NewLocal(txn.Sender, 100, "ALGO", algoValue)
+ ledger.NewLocal(txn.Sender, 100, "ALGO", 0x77)
// check delete, write, delete non-existing
source = `txn Sender
@@ -2969,10 +2987,7 @@ func TestUnnamedResourceAccess(t *testing.T) {
})
ledger.NewLocals(otherAccount, 500)
- ledger.NewLocal(otherAccount, 500, "local key", basics.TealValue{
- Type: basics.TealBytesType,
- Bytes: "local value",
- })
+ ledger.NewLocal(otherAccount, 500, "local key", "local value")
ledger.NewAsset(tx.Sender, 501, basics.AssetParams{Total: 501})
ledger.NewHolding(otherAccount, 501, 2, false)
@@ -3448,13 +3463,18 @@ func TestReturnTypes(t *testing.T) {
Clawback: tx.Receiver,
}
ledger.NewAsset(tx.Sender, 400, params)
- ledger.NewApp(tx.Sender, 300, basics.AppParams{})
+ ledger.NewApp(tx.Sender, 300, basics.AppParams{
+ StateSchemas: basics.StateSchemas{
+ GlobalStateSchema: basics.StateSchema{
+ NumUint: 1,
+ },
+ },
+ })
ledger.NewAccount(tx.Receiver, 1000000)
ledger.NewLocals(tx.Receiver, 300)
key, err := hex.DecodeString("33343536")
require.NoError(t, err)
- algoValue := basics.TealValue{Type: basics.TealUintType, Uint: 0x77}
- ledger.NewLocal(tx.Receiver, 300, string(key), algoValue)
+ ledger.NewLocal(tx.Receiver, 300, string(key), 0x77)
ledger.NewAccount(appAddr(300), 1000000)
// these allows the box_* opcodes that to work
diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go
index ac72f68567..5c81bcaf41 100644
--- a/data/transactions/logic/eval_test.go
+++ b/data/transactions/logic/eval_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -135,6 +135,9 @@ func makeTestProto(opts ...protoOpt) *config.ConsensusParams {
MinBalance: 5,
MaxBalance: 6,
},
+
+ EnableAppVersioning: true,
+ AppSizeUpdates: true,
}
for _, opt := range opts {
if opt != nil { // so some callsites can take one arg and pass it in
@@ -285,7 +288,7 @@ func TestEmptyProgram(t *testing.T) {
testLogicBytes(t, nil, nil, "invalid", "invalid program (empty)")
}
-// TestMinAvmVersionParamEval tests eval/check reading the minAvmVersion from the param
+// TestMinAvmVersionParamEvalCheckSignature tests eval/check reading the minAvmVersion from the param
func TestMinAvmVersionParamEvalCheckSignature(t *testing.T) {
partitiontest.PartitionTest(t)
@@ -1399,7 +1402,7 @@ func TestOnCompletionConstants(t *testing.T) {
}
require.Less(t, last, max, "too many OnCompletion constants, adjust max limit")
require.Equal(t, int(invalidOnCompletionConst), last)
- require.Equal(t, len(onCompletionMap), len(onCompletionDescriptions))
+ require.Equal(t, len(onCompletionMap), len(OnCompletionDescriptions))
require.Equal(t, len(OnCompletionNames), last)
for v := NoOp; v < invalidOnCompletionConst; v++ {
require.Equal(t, v.String(), OnCompletionNames[int(v)])
diff --git a/data/transactions/logic/export_test.go b/data/transactions/logic/export_test.go
index 5d3c41fd9c..907ca6a626 100644
--- a/data/transactions/logic/export_test.go
+++ b/data/transactions/logic/export_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/fields.go b/data/transactions/logic/fields.go
index 9e6a25c7e6..41efb5e1d5 100644
--- a/data/transactions/logic/fields.go
+++ b/data/transactions/logic/fields.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -18,12 +18,13 @@ package logic
import (
"fmt"
+ "strings"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/protocol"
)
-//go:generate stringer -type=TxnField,GlobalField,AssetParamsField,AppParamsField,AcctParamsField,AssetHoldingField,OnCompletionConstType,EcdsaCurve,EcGroup,MimcConfig,Base64Encoding,JSONRefType,VoterParamsField,VrfStandard,BlockField -output=fields_string.go
+//go:generate go tool -modfile=../../../tool.mod stringer -type=TxnField,GlobalField,AssetParamsField,AppParamsField,AcctParamsField,AssetHoldingField,OnCompletionConstType,EcdsaCurve,EcGroup,MimcConfig,Base64Encoding,JSONRefType,VoterParamsField,VrfStandard,BlockField -output=fields_string.go
// FieldSpec unifies the various specs for assembly, disassembly, and doc generation.
type FieldSpec interface {
@@ -48,6 +49,16 @@ type FieldGroup struct {
specs fieldSpecMap
}
+// Heading returns a documentation heading for this FieldGroup.
+func (fg FieldGroup) Heading() string {
+ heading := fg.Name
+ if fg.Doc != "" {
+ word, _, _ := strings.Cut(fg.Doc, " ")
+ heading += " " + word
+ }
+ return heading
+}
+
// SpecByName returns a FieldsSpec for a name, respecting the "sparseness" of
// the Names array to hide some names
func (fg *FieldGroup) SpecByName(name string) (FieldSpec, bool) {
@@ -453,6 +464,20 @@ var TxnTypeNames = [...]string{
string(protocol.AssetTransferTx),
string(protocol.AssetFreezeTx),
string(protocol.ApplicationCallTx),
+ string(protocol.StateProofTx),
+ string(protocol.HeartbeatTx),
+}
+
+// txnTypeLongNames provide a friendlier type constant name in assembler.
+var txnTypeLongNames = map[string]string{
+ string(protocol.PaymentTx): "Payment",
+ string(protocol.KeyRegistrationTx): "KeyRegistration",
+ string(protocol.AssetConfigTx): "AssetConfig",
+ string(protocol.AssetTransferTx): "AssetTransfer",
+ string(protocol.AssetFreezeTx): "AssetFreeze",
+ string(protocol.ApplicationCallTx): "ApplicationCall",
+ string(protocol.StateProofTx): "State Proof",
+ string(protocol.HeartbeatTx): "Consensus heartbeat",
}
// map txn type names (long and short) to index/enum value
@@ -482,7 +507,7 @@ const (
var OnCompletionNames [invalidOnCompletionConst]string
// onCompletionMap maps symbolic name to uint64 for assembleInt
-var onCompletionMap map[string]uint64
+var onCompletionMap = make(map[string]uint64)
// GlobalField is an enum for `global` opcode
type GlobalField uint64
@@ -847,7 +872,7 @@ func (s mimcConfigNameSpecMap) get(name string) (FieldSpec, bool) {
// MimcConfigs collects details about the constants used to describe MimcConfigs
var MimcConfigs = FieldGroup{
- "Mimc Configurations", "Parameters",
+ "MimcConfigurations", "Parameters",
mimcConfigNames[:],
mimcConfigSpecByName,
}
@@ -1350,6 +1375,9 @@ const (
// AppVersion begins at 0 and increasing each time either program changes
AppVersion
+ // AppSizeSponsor is responsible for extra pages and global state balance requirement.
+ AppSizeSponsor
+
invalidAppParamsField // compile-time constant for number of fields
)
@@ -1389,6 +1417,7 @@ var appParamsFieldSpecs = [...]appParamsFieldSpec{
{AppCreator, StackAddress, 5, "Creator address"},
{AppAddress, StackAddress, 5, "Address for which this application has authority"},
{AppVersion, StackUint64, 12, "Version of the app, incremented each time the approval or clear program changes"},
+ {AppSizeSponsor, StackAddress, 13, "If non-zero, this account is responsible for the app's extra pages and global state balance requirement"},
}
func appParamsFieldSpecByField(f AppParamsField) (appParamsFieldSpec, bool) {
@@ -1705,15 +1734,15 @@ func init() {
voterParamsFieldSpecByName[s.field.String()] = s
}
- txnTypeMap = make(map[string]uint64)
for i, tt := range TxnTypeNames {
txnTypeMap[tt] = uint64(i)
}
- for k, v := range TypeNameDescriptions {
+ for k, v := range txnTypeLongNames {
txnTypeMap[v] = txnTypeMap[k]
}
+ // unknown does not have a long name, hence +1
+ equal(len(TxnTypeNames), len(txnTypeLongNames)+1)
- onCompletionMap = make(map[string]uint64, len(OnCompletionNames))
for oc := NoOp; oc < invalidOnCompletionConst; oc++ {
symbol := oc.String()
OnCompletionNames[oc] = symbol
diff --git a/data/transactions/logic/fields_string.go b/data/transactions/logic/fields_string.go
index d06d737b4b..2766b41622 100644
--- a/data/transactions/logic/fields_string.go
+++ b/data/transactions/logic/fields_string.go
@@ -85,10 +85,11 @@ const _TxnField_name = "SenderFeeFirstValidFirstValidTimeLastValidNoteLeaseRecei
var _TxnField_index = [...]uint16{0, 6, 9, 19, 33, 42, 46, 51, 59, 65, 81, 87, 98, 107, 115, 130, 134, 142, 151, 162, 173, 186, 198, 208, 212, 225, 237, 252, 262, 270, 281, 296, 313, 320, 331, 347, 366, 390, 409, 424, 438, 461, 479, 497, 514, 533, 544, 562, 579, 585, 594, 606, 621, 634, 652, 664, 681, 698, 714, 718, 725, 739, 759, 766, 778, 798, 821, 843, 868, 881, 896}
func (i TxnField) String() string {
- if i < 0 || i >= TxnField(len(_TxnField_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_TxnField_index)-1 {
return "TxnField(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _TxnField_name[_TxnField_index[i]:_TxnField_index[i+1]]
+ return _TxnField_name[_TxnField_index[idx]:_TxnField_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -125,10 +126,11 @@ const _GlobalField_name = "MinTxnFeeMinBalanceMaxTxnLifeZeroAddressGroupSizeLogi
var _GlobalField_index = [...]uint16{0, 9, 19, 29, 40, 49, 64, 69, 84, 104, 118, 143, 150, 162, 181, 205, 226, 246, 257, 271, 289, 303, 320, 337, 355}
func (i GlobalField) String() string {
- if i >= GlobalField(len(_GlobalField_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_GlobalField_index)-1 {
return "GlobalField(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _GlobalField_name[_GlobalField_index[i]:_GlobalField_index[i+1]]
+ return _GlobalField_name[_GlobalField_index[idx]:_GlobalField_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -154,10 +156,11 @@ const _AssetParamsField_name = "AssetTotalAssetDecimalsAssetDefaultFrozenAssetUn
var _AssetParamsField_index = [...]uint8{0, 10, 23, 41, 54, 63, 71, 88, 100, 112, 123, 136, 148, 171}
func (i AssetParamsField) String() string {
- if i < 0 || i >= AssetParamsField(len(_AssetParamsField_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_AssetParamsField_index)-1 {
return "AssetParamsField(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _AssetParamsField_name[_AssetParamsField_index[i]:_AssetParamsField_index[i+1]]
+ return _AssetParamsField_name[_AssetParamsField_index[idx]:_AssetParamsField_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -173,18 +176,20 @@ func _() {
_ = x[AppCreator-7]
_ = x[AppAddress-8]
_ = x[AppVersion-9]
- _ = x[invalidAppParamsField-10]
+ _ = x[AppSizeSponsor-10]
+ _ = x[invalidAppParamsField-11]
}
-const _AppParamsField_name = "AppApprovalProgramAppClearStateProgramAppGlobalNumUintAppGlobalNumByteSliceAppLocalNumUintAppLocalNumByteSliceAppExtraProgramPagesAppCreatorAppAddressAppVersioninvalidAppParamsField"
+const _AppParamsField_name = "AppApprovalProgramAppClearStateProgramAppGlobalNumUintAppGlobalNumByteSliceAppLocalNumUintAppLocalNumByteSliceAppExtraProgramPagesAppCreatorAppAddressAppVersionAppSizeSponsorinvalidAppParamsField"
-var _AppParamsField_index = [...]uint8{0, 18, 38, 54, 75, 90, 110, 130, 140, 150, 160, 181}
+var _AppParamsField_index = [...]uint8{0, 18, 38, 54, 75, 90, 110, 130, 140, 150, 160, 174, 195}
func (i AppParamsField) String() string {
- if i < 0 || i >= AppParamsField(len(_AppParamsField_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_AppParamsField_index)-1 {
return "AppParamsField(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _AppParamsField_name[_AppParamsField_index[i]:_AppParamsField_index[i+1]]
+ return _AppParamsField_name[_AppParamsField_index[idx]:_AppParamsField_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -213,10 +218,11 @@ const _AcctParamsField_name = "AcctBalanceAcctMinBalanceAcctAuthAddrAcctTotalNum
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) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_AcctParamsField_index)-1 {
return "AcctParamsField(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _AcctParamsField_name[_AcctParamsField_index[i]:_AcctParamsField_index[i+1]]
+ return _AcctParamsField_name[_AcctParamsField_index[idx]:_AcctParamsField_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -232,10 +238,11 @@ const _AssetHoldingField_name = "AssetBalanceAssetFrozeninvalidAssetHoldingField
var _AssetHoldingField_index = [...]uint8{0, 12, 23, 47}
func (i AssetHoldingField) String() string {
- if i < 0 || i >= AssetHoldingField(len(_AssetHoldingField_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_AssetHoldingField_index)-1 {
return "AssetHoldingField(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _AssetHoldingField_name[_AssetHoldingField_index[i]:_AssetHoldingField_index[i+1]]
+ return _AssetHoldingField_name[_AssetHoldingField_index[idx]:_AssetHoldingField_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -254,10 +261,11 @@ const _OnCompletionConstType_name = "NoOpOptInCloseOutClearStateUpdateApplicatio
var _OnCompletionConstType_index = [...]uint8{0, 4, 9, 17, 27, 44, 61}
func (i OnCompletionConstType) String() string {
- if i >= OnCompletionConstType(len(_OnCompletionConstType_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_OnCompletionConstType_index)-1 {
return "OnCompletionConstType(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _OnCompletionConstType_name[_OnCompletionConstType_index[i]:_OnCompletionConstType_index[i+1]]
+ return _OnCompletionConstType_name[_OnCompletionConstType_index[idx]:_OnCompletionConstType_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -273,10 +281,11 @@ const _EcdsaCurve_name = "Secp256k1Secp256r1invalidEcdsaCurve"
var _EcdsaCurve_index = [...]uint8{0, 9, 18, 35}
func (i EcdsaCurve) String() string {
- if i < 0 || i >= EcdsaCurve(len(_EcdsaCurve_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_EcdsaCurve_index)-1 {
return "EcdsaCurve(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _EcdsaCurve_name[_EcdsaCurve_index[i]:_EcdsaCurve_index[i+1]]
+ return _EcdsaCurve_name[_EcdsaCurve_index[idx]:_EcdsaCurve_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -294,10 +303,11 @@ const _EcGroup_name = "BN254g1BN254g2BLS12_381g1BLS12_381g2invalidEcGroup"
var _EcGroup_index = [...]uint8{0, 7, 14, 25, 36, 50}
func (i EcGroup) String() string {
- if i < 0 || i >= EcGroup(len(_EcGroup_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_EcGroup_index)-1 {
return "EcGroup(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _EcGroup_name[_EcGroup_index[i]:_EcGroup_index[i+1]]
+ return _EcGroup_name[_EcGroup_index[idx]:_EcGroup_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -313,10 +323,11 @@ const _MimcConfig_name = "BN254Mp110BLS12_381Mp111invalidMimcConfig"
var _MimcConfig_index = [...]uint8{0, 10, 24, 41}
func (i MimcConfig) String() string {
- if i < 0 || i >= MimcConfig(len(_MimcConfig_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_MimcConfig_index)-1 {
return "MimcConfig(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _MimcConfig_name[_MimcConfig_index[i]:_MimcConfig_index[i+1]]
+ return _MimcConfig_name[_MimcConfig_index[idx]:_MimcConfig_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -332,10 +343,11 @@ const _Base64Encoding_name = "URLEncodingStdEncodinginvalidBase64Encoding"
var _Base64Encoding_index = [...]uint8{0, 11, 22, 43}
func (i Base64Encoding) String() string {
- if i < 0 || i >= Base64Encoding(len(_Base64Encoding_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_Base64Encoding_index)-1 {
return "Base64Encoding(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _Base64Encoding_name[_Base64Encoding_index[i]:_Base64Encoding_index[i+1]]
+ return _Base64Encoding_name[_Base64Encoding_index[idx]:_Base64Encoding_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -352,10 +364,11 @@ const _JSONRefType_name = "JSONStringJSONUint64JSONObjectinvalidJSONRefType"
var _JSONRefType_index = [...]uint8{0, 10, 20, 30, 48}
func (i JSONRefType) String() string {
- if i < 0 || i >= JSONRefType(len(_JSONRefType_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_JSONRefType_index)-1 {
return "JSONRefType(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _JSONRefType_name[_JSONRefType_index[i]:_JSONRefType_index[i+1]]
+ return _JSONRefType_name[_JSONRefType_index[idx]:_JSONRefType_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -371,10 +384,11 @@ const _VoterParamsField_name = "VoterBalanceVoterIncentiveEligibleinvalidVoterPa
var _VoterParamsField_index = [...]uint8{0, 12, 34, 57}
func (i VoterParamsField) String() string {
- if i < 0 || i >= VoterParamsField(len(_VoterParamsField_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_VoterParamsField_index)-1 {
return "VoterParamsField(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _VoterParamsField_name[_VoterParamsField_index[i]:_VoterParamsField_index[i+1]]
+ return _VoterParamsField_name[_VoterParamsField_index[idx]:_VoterParamsField_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -389,10 +403,11 @@ const _VrfStandard_name = "VrfAlgorandinvalidVrfStandard"
var _VrfStandard_index = [...]uint8{0, 11, 29}
func (i VrfStandard) String() string {
- if i < 0 || i >= VrfStandard(len(_VrfStandard_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_VrfStandard_index)-1 {
return "VrfStandard(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _VrfStandard_name[_VrfStandard_index[i]:_VrfStandard_index[i+1]]
+ return _VrfStandard_name[_VrfStandard_index[idx]:_VrfStandard_index[idx+1]]
}
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
@@ -420,8 +435,9 @@ const _BlockField_name = "BlkSeedBlkTimestampBlkProposerBlkFeesCollectedBlkBonus
var _BlockField_index = [...]uint8{0, 7, 19, 30, 46, 54, 63, 73, 84, 97, 114, 126, 152, 174, 196, 213}
func (i BlockField) String() string {
- if i < 0 || i >= BlockField(len(_BlockField_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_BlockField_index)-1 {
return "BlockField(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _BlockField_name[_BlockField_index[i]:_BlockField_index[i+1]]
+ return _BlockField_name[_BlockField_index[idx]:_BlockField_index[idx+1]]
}
diff --git a/data/transactions/logic/fields_test.go b/data/transactions/logic/fields_test.go
index 67cf826dee..f4df67aded 100644
--- a/data/transactions/logic/fields_test.go
+++ b/data/transactions/logic/fields_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/frames.go b/data/transactions/logic/frames.go
index fc6354483d..3e2f62aa17 100644
--- a/data/transactions/logic/frames.go
+++ b/data/transactions/logic/frames.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/frames_test.go b/data/transactions/logic/frames_test.go
index c27a9148b9..6e649c34d6 100644
--- a/data/transactions/logic/frames_test.go
+++ b/data/transactions/logic/frames_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/jsonspec_test.go b/data/transactions/logic/jsonspec_test.go
index f3e54b7b40..3e78b4547c 100644
--- a/data/transactions/logic/jsonspec_test.go
+++ b/data/transactions/logic/jsonspec_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/langspec_v1.json b/data/transactions/logic/langspec_v1.json
index cca94aaf01..93f218da39 100644
--- a/data/transactions/logic/langspec_v1.json
+++ b/data/transactions/logic/langspec_v1.json
@@ -905,7 +905,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -941,7 +941,7 @@
"Comment": "a global field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "global"
+ "Reference": "global Fields"
}
],
"IntroducedVersion": 1,
@@ -1019,7 +1019,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
diff --git a/data/transactions/logic/langspec_v10.json b/data/transactions/logic/langspec_v10.json
index 3257cfca4b..39911f3db9 100644
--- a/data/transactions/logic/langspec_v10.json
+++ b/data/transactions/logic/langspec_v10.json
@@ -202,7 +202,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -233,7 +233,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -267,7 +267,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -1137,7 +1137,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1199,7 +1199,7 @@
"Comment": "a global field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "global"
+ "Reference": "global Fields"
}
],
"IntroducedVersion": 1,
@@ -1367,7 +1367,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1443,13 +1443,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F of the current transaction\n`txna` can be called using `txn` with 2 immediates.",
+ "Doc": "Ith value of the array field F of the current transaction",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1488,7 +1488,7 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Tth transaction in the current group\n`gtxna` can be called using `gtxn` with 3 immediates.",
+ "Doc": "Ith value of the array field F from the Tth transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction group index",
@@ -1499,7 +1499,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1670,7 +1670,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 3,
@@ -1707,13 +1707,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Ath transaction in the current group\n`gtxnsa` can be called using `gtxns` with 2 immediates.",
+ "Doc": "Ith value of the array field F from the Ath transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -2350,7 +2350,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails\n`extract3` can be called using `extract` with no immediates.",
+ "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails",
"IntroducedVersion": 5,
"Groups": [
"Byte Array Manipulation"
@@ -2422,7 +2422,7 @@
],
"Size": 2,
"DocCost": "1",
- "Doc": "Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)\n`replace2` can be called using `replace` with 1 immediate.",
+ "Doc": "Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)",
"ImmediateNote": [
{
"Comment": "start position",
@@ -2448,7 +2448,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)\n`replace3` can be called using `replace` with no immediates.",
+ "Doc": "Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)",
"IntroducedVersion": 7,
"Groups": [
"Byte Array Manipulation"
@@ -2474,13 +2474,13 @@
],
"DocCost": "1 + 1 per 16 bytes of A",
"Doc": "decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E",
- "DocExtra": "*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings.\tThis opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
+ "DocExtra": "_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
"ImmediateNote": [
{
"Comment": "encoding index",
"Encoding": "uint8",
"Name": "E",
- "Reference": "base64"
+ "Reference": "base64 Encodings"
}
],
"IntroducedVersion": 7,
@@ -2511,13 +2511,13 @@
],
"DocCost": "25 + 2 per 7 bytes of A",
"Doc": "key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A",
- "DocExtra": "*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
+ "DocExtra": "_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
"ImmediateNote": [
{
"Comment": "return type index",
"Encoding": "uint8",
"Name": "R",
- "Reference": "json_ref"
+ "Reference": "json_ref Types"
}
],
"IntroducedVersion": 7,
@@ -2540,7 +2540,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2559,7 +2559,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2578,7 +2578,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2599,7 +2599,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2617,7 +2617,7 @@
"DocExtra": "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2637,7 +2637,7 @@
"DocExtra": "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2654,7 +2654,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2669,7 +2669,7 @@
"Doc": "write B to key A in the global state of the current application",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2685,7 +2685,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2700,7 +2700,7 @@
"DocExtra": "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2731,12 +2731,12 @@
"Comment": "asset holding field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_holding"
+ "Reference": "asset_holding Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2786,12 +2786,12 @@
"Comment": "asset params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_params"
+ "Reference": "asset_params Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2835,12 +2835,12 @@
"Comment": "app params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "app_params"
+ "Reference": "app_params Fields"
}
],
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2889,12 +2889,12 @@
"Comment": "account params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "acct_params"
+ "Reference": "acct_params Fields"
}
],
"IntroducedVersion": 6,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2912,7 +2912,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 3,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -3613,7 +3613,7 @@
"DocExtra": "`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.",
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -3923,7 +3923,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 5,
@@ -3963,7 +3963,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "a transaction field array index",
@@ -4192,7 +4192,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -4364,7 +4364,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4412,7 +4412,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4456,7 +4456,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4516,7 +4516,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -4546,7 +4546,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -4578,7 +4578,7 @@
"Comment": " parameters index",
"Encoding": "uint8",
"Name": "S",
- "Reference": "vrf_verify"
+ "Reference": "vrf_verify Standards"
}
],
"IntroducedVersion": 7,
@@ -4611,12 +4611,12 @@
"Comment": " block field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "block"
+ "Reference": "block Fields"
}
],
"IntroducedVersion": 7,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -4671,7 +4671,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4698,7 +4698,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4725,7 +4725,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4752,7 +4752,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4777,7 +4777,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4803,7 +4803,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
diff --git a/data/transactions/logic/langspec_v11.json b/data/transactions/logic/langspec_v11.json
index 9fb5a995ba..f2751d6255 100644
--- a/data/transactions/logic/langspec_v11.json
+++ b/data/transactions/logic/langspec_v11.json
@@ -202,7 +202,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -233,7 +233,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -267,7 +267,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -1137,7 +1137,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1209,7 +1209,7 @@
"Comment": "a global field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "global"
+ "Reference": "global Fields"
}
],
"IntroducedVersion": 1,
@@ -1377,7 +1377,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1453,13 +1453,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F of the current transaction\n`txna` can be called using `txn` with 2 immediates.",
+ "Doc": "Ith value of the array field F of the current transaction",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1498,7 +1498,7 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Tth transaction in the current group\n`gtxna` can be called using `gtxn` with 3 immediates.",
+ "Doc": "Ith value of the array field F from the Tth transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction group index",
@@ -1509,7 +1509,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1680,7 +1680,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 3,
@@ -1717,13 +1717,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Ath transaction in the current group\n`gtxnsa` can be called using `gtxns` with 2 immediates.",
+ "Doc": "Ith value of the array field F from the Ath transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -2360,7 +2360,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails\n`extract3` can be called using `extract` with no immediates.",
+ "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails",
"IntroducedVersion": 5,
"Groups": [
"Byte Array Manipulation"
@@ -2432,7 +2432,7 @@
],
"Size": 2,
"DocCost": "1",
- "Doc": "Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)\n`replace2` can be called using `replace` with 1 immediate.",
+ "Doc": "Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)",
"ImmediateNote": [
{
"Comment": "start position",
@@ -2458,7 +2458,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)\n`replace3` can be called using `replace` with no immediates.",
+ "Doc": "Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)",
"IntroducedVersion": 7,
"Groups": [
"Byte Array Manipulation"
@@ -2484,13 +2484,13 @@
],
"DocCost": "1 + 1 per 16 bytes of A",
"Doc": "decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E",
- "DocExtra": "*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings.\tThis opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
+ "DocExtra": "_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
"ImmediateNote": [
{
"Comment": "encoding index",
"Encoding": "uint8",
"Name": "E",
- "Reference": "base64"
+ "Reference": "base64 Encodings"
}
],
"IntroducedVersion": 7,
@@ -2521,13 +2521,13 @@
],
"DocCost": "25 + 2 per 7 bytes of A",
"Doc": "key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A",
- "DocExtra": "*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
+ "DocExtra": "_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
"ImmediateNote": [
{
"Comment": "return type index",
"Encoding": "uint8",
"Name": "R",
- "Reference": "json_ref"
+ "Reference": "json_ref Types"
}
],
"IntroducedVersion": 7,
@@ -2550,7 +2550,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2569,7 +2569,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2588,7 +2588,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2609,7 +2609,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2627,7 +2627,7 @@
"DocExtra": "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2647,7 +2647,7 @@
"DocExtra": "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2664,7 +2664,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2679,7 +2679,7 @@
"Doc": "write B to key A in the global state of the current application",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2695,7 +2695,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2710,7 +2710,7 @@
"DocExtra": "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2741,12 +2741,12 @@
"Comment": "asset holding field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_holding"
+ "Reference": "asset_holding Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2796,12 +2796,12 @@
"Comment": "asset params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_params"
+ "Reference": "asset_params Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2845,12 +2845,12 @@
"Comment": "app params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "app_params"
+ "Reference": "app_params Fields"
}
],
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2905,12 +2905,12 @@
"Comment": "account params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "acct_params"
+ "Reference": "acct_params Fields"
}
],
"IntroducedVersion": 6,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2931,12 +2931,12 @@
"Comment": "voter params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "voter_params"
+ "Reference": "voter_params Fields"
}
],
"IntroducedVersion": 11,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2950,7 +2950,7 @@
"Doc": "the total online stake in the agreement round",
"IntroducedVersion": 11,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -2968,7 +2968,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 3,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -3669,7 +3669,7 @@
"DocExtra": "`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.",
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -3979,7 +3979,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 5,
@@ -4019,7 +4019,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "a transaction field array index",
@@ -4248,7 +4248,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -4420,7 +4420,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4468,7 +4468,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4512,7 +4512,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4572,7 +4572,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -4602,7 +4602,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -4634,7 +4634,7 @@
"Comment": " parameters index",
"Encoding": "uint8",
"Name": "S",
- "Reference": "vrf_verify"
+ "Reference": "vrf_verify Standards"
}
],
"IntroducedVersion": 7,
@@ -4683,12 +4683,12 @@
"Comment": " block field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "block"
+ "Reference": "block Fields"
}
],
"IntroducedVersion": 7,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -4743,7 +4743,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4770,7 +4770,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4797,7 +4797,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4824,7 +4824,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4849,7 +4849,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4875,7 +4875,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4901,7 +4901,7 @@
"Comment": "configuration index",
"Encoding": "uint8",
"Name": "C",
- "Reference": "Mimc Configurations"
+ "Reference": "MimcConfigurations Parameters"
}
],
"IntroducedVersion": 11,
diff --git a/data/transactions/logic/langspec_v12.json b/data/transactions/logic/langspec_v12.json
index 8c6541e493..da38f8790d 100644
--- a/data/transactions/logic/langspec_v12.json
+++ b/data/transactions/logic/langspec_v12.json
@@ -202,7 +202,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -233,7 +233,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -267,7 +267,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -1139,7 +1139,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1211,7 +1211,7 @@
"Comment": "a global field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "global"
+ "Reference": "global Fields"
}
],
"IntroducedVersion": 1,
@@ -1381,7 +1381,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1457,13 +1457,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F of the current transaction\n`txna` can be called using `txn` with 2 immediates.",
+ "Doc": "Ith value of the array field F of the current transaction",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1502,7 +1502,7 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Tth transaction in the current group\n`gtxna` can be called using `gtxn` with 3 immediates.",
+ "Doc": "Ith value of the array field F from the Tth transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction group index",
@@ -1513,7 +1513,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1686,7 +1686,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 3,
@@ -1723,13 +1723,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Ath transaction in the current group\n`gtxnsa` can be called using `gtxns` with 2 immediates.",
+ "Doc": "Ith value of the array field F from the Ath transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -2366,7 +2366,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails\n`extract3` can be called using `extract` with no immediates.",
+ "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails",
"IntroducedVersion": 5,
"Groups": [
"Byte Array Manipulation"
@@ -2438,7 +2438,7 @@
],
"Size": 2,
"DocCost": "1",
- "Doc": "Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)\n`replace2` can be called using `replace` with 1 immediate.",
+ "Doc": "Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)",
"ImmediateNote": [
{
"Comment": "start position",
@@ -2464,7 +2464,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)\n`replace3` can be called using `replace` with no immediates.",
+ "Doc": "Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)",
"IntroducedVersion": 7,
"Groups": [
"Byte Array Manipulation"
@@ -2490,13 +2490,13 @@
],
"DocCost": "1 + 1 per 16 bytes of A",
"Doc": "decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E",
- "DocExtra": "*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings.\tThis opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
+ "DocExtra": "_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
"ImmediateNote": [
{
"Comment": "encoding index",
"Encoding": "uint8",
"Name": "E",
- "Reference": "base64"
+ "Reference": "base64 Encodings"
}
],
"IntroducedVersion": 7,
@@ -2527,13 +2527,13 @@
],
"DocCost": "25 + 2 per 7 bytes of A",
"Doc": "key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A",
- "DocExtra": "*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
+ "DocExtra": "_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
"ImmediateNote": [
{
"Comment": "return type index",
"Encoding": "uint8",
"Name": "R",
- "Reference": "json_ref"
+ "Reference": "json_ref Types"
}
],
"IntroducedVersion": 7,
@@ -2556,7 +2556,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2575,7 +2575,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2594,7 +2594,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2615,7 +2615,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2633,7 +2633,7 @@
"DocExtra": "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2653,7 +2653,7 @@
"DocExtra": "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2670,7 +2670,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2685,7 +2685,7 @@
"Doc": "write B to key A in the global state of the current application",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2701,7 +2701,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2716,7 +2716,7 @@
"DocExtra": "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2747,12 +2747,12 @@
"Comment": "asset holding field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_holding"
+ "Reference": "asset_holding Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2802,12 +2802,12 @@
"Comment": "asset params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_params"
+ "Reference": "asset_params Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2853,12 +2853,12 @@
"Comment": "app params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "app_params"
+ "Reference": "app_params Fields"
}
],
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2913,12 +2913,12 @@
"Comment": "account params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "acct_params"
+ "Reference": "acct_params Fields"
}
],
"IntroducedVersion": 6,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2939,12 +2939,12 @@
"Comment": "voter params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "voter_params"
+ "Reference": "voter_params Fields"
}
],
"IntroducedVersion": 11,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2958,7 +2958,7 @@
"Doc": "the total online stake in the agreement round",
"IntroducedVersion": 11,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -2976,7 +2976,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 3,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -3696,7 +3696,7 @@
"DocExtra": "`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.",
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -4010,7 +4010,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 5,
@@ -4050,7 +4050,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "a transaction field array index",
@@ -4281,7 +4281,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -4453,7 +4453,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4501,7 +4501,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4545,7 +4545,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4605,7 +4605,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -4635,7 +4635,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -4667,7 +4667,7 @@
"Comment": " parameters index",
"Encoding": "uint8",
"Name": "S",
- "Reference": "vrf_verify"
+ "Reference": "vrf_verify Standards"
}
],
"IntroducedVersion": 7,
@@ -4716,12 +4716,12 @@
"Comment": " block field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "block"
+ "Reference": "block Fields"
}
],
"IntroducedVersion": 7,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -4776,7 +4776,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4803,7 +4803,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4830,7 +4830,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4857,7 +4857,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4882,7 +4882,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4908,7 +4908,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "G",
- "Reference": "EC"
+ "Reference": "EC Groups"
}
],
"IntroducedVersion": 10,
@@ -4934,7 +4934,7 @@
"Comment": "configuration index",
"Encoding": "uint8",
"Name": "C",
- "Reference": "Mimc Configurations"
+ "Reference": "MimcConfigurations Parameters"
}
],
"IntroducedVersion": 11,
diff --git a/data/transactions/logic/langspec_v2.json b/data/transactions/logic/langspec_v2.json
index 6ad55bb1ca..1271f41130 100644
--- a/data/transactions/logic/langspec_v2.json
+++ b/data/transactions/logic/langspec_v2.json
@@ -972,7 +972,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1016,7 +1016,7 @@
"Comment": "a global field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "global"
+ "Reference": "global Fields"
}
],
"IntroducedVersion": 1,
@@ -1142,7 +1142,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1208,13 +1208,13 @@
"address"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F of the current transaction\n`txna` can be called using `txn` with 2 immediates.",
+ "Doc": "Ith value of the array field F of the current transaction",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1243,7 +1243,7 @@
"address"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Tth transaction in the current group\n`gtxna` can be called using `gtxn` with 3 immediates.",
+ "Doc": "Ith value of the array field F from the Tth transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction group index",
@@ -1254,7 +1254,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1479,7 +1479,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -1498,7 +1498,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1517,7 +1517,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1538,7 +1538,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1556,7 +1556,7 @@
"DocExtra": "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1576,7 +1576,7 @@
"DocExtra": "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1593,7 +1593,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1608,7 +1608,7 @@
"Doc": "write B to key A in the global state of the current application",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1624,7 +1624,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1639,7 +1639,7 @@
"DocExtra": "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1670,12 +1670,12 @@
"Comment": "asset holding field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_holding"
+ "Reference": "asset_holding Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -1723,12 +1723,12 @@
"Comment": "asset params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_params"
+ "Reference": "asset_params Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
}
]
diff --git a/data/transactions/logic/langspec_v3.json b/data/transactions/logic/langspec_v3.json
index 6193add93c..d2c7a4ed45 100644
--- a/data/transactions/logic/langspec_v3.json
+++ b/data/transactions/logic/langspec_v3.json
@@ -988,7 +988,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1034,7 +1034,7 @@
"Comment": "a global field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "global"
+ "Reference": "global Fields"
}
],
"IntroducedVersion": 1,
@@ -1176,7 +1176,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1246,13 +1246,13 @@
"uint64"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F of the current transaction\n`txna` can be called using `txn` with 2 immediates.",
+ "Doc": "Ith value of the array field F of the current transaction",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1285,7 +1285,7 @@
"uint64"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Tth transaction in the current group\n`gtxna` can be called using `gtxn` with 3 immediates.",
+ "Doc": "Ith value of the array field F from the Tth transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction group index",
@@ -1296,7 +1296,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1441,7 +1441,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 3,
@@ -1472,13 +1472,13 @@
"uint64"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Ath transaction in the current group\n`gtxnsa` can be called using `gtxns` with 2 immediates.",
+ "Doc": "Ith value of the array field F from the Ath transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1856,7 +1856,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -1875,7 +1875,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1894,7 +1894,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1915,7 +1915,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1933,7 +1933,7 @@
"DocExtra": "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1953,7 +1953,7 @@
"DocExtra": "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1970,7 +1970,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -1985,7 +1985,7 @@
"Doc": "write B to key A in the global state of the current application",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2001,7 +2001,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2016,7 +2016,7 @@
"DocExtra": "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2047,12 +2047,12 @@
"Comment": "asset holding field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_holding"
+ "Reference": "asset_holding Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2100,12 +2100,12 @@
"Comment": "asset params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_params"
+ "Reference": "asset_params Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2123,7 +2123,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 3,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
diff --git a/data/transactions/logic/langspec_v4.json b/data/transactions/logic/langspec_v4.json
index 06b7826eeb..aa632aa416 100644
--- a/data/transactions/logic/langspec_v4.json
+++ b/data/transactions/logic/langspec_v4.json
@@ -1014,7 +1014,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1060,7 +1060,7 @@
"Comment": "a global field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "global"
+ "Reference": "global Fields"
}
],
"IntroducedVersion": 1,
@@ -1204,7 +1204,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1274,13 +1274,13 @@
"uint64"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F of the current transaction\n`txna` can be called using `txn` with 2 immediates.",
+ "Doc": "Ith value of the array field F of the current transaction",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1313,7 +1313,7 @@
"uint64"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Tth transaction in the current group\n`gtxna` can be called using `gtxn` with 3 immediates.",
+ "Doc": "Ith value of the array field F from the Tth transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction group index",
@@ -1324,7 +1324,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1471,7 +1471,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 3,
@@ -1502,13 +1502,13 @@
"uint64"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Ath transaction in the current group\n`gtxnsa` can be called using `gtxns` with 2 immediates.",
+ "Doc": "Ith value of the array field F from the Ath transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1978,7 +1978,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -1997,7 +1997,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2016,7 +2016,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2037,7 +2037,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2055,7 +2055,7 @@
"DocExtra": "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2075,7 +2075,7 @@
"DocExtra": "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2092,7 +2092,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2107,7 +2107,7 @@
"Doc": "write B to key A in the global state of the current application",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2123,7 +2123,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2138,7 +2138,7 @@
"DocExtra": "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2169,12 +2169,12 @@
"Comment": "asset holding field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_holding"
+ "Reference": "asset_holding Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2222,12 +2222,12 @@
"Comment": "asset params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_params"
+ "Reference": "asset_params Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2245,7 +2245,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 3,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
diff --git a/data/transactions/logic/langspec_v5.json b/data/transactions/logic/langspec_v5.json
index 07fd2773c6..388d7bc647 100644
--- a/data/transactions/logic/langspec_v5.json
+++ b/data/transactions/logic/langspec_v5.json
@@ -201,7 +201,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -231,7 +231,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -264,7 +264,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -1120,7 +1120,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1170,7 +1170,7 @@
"Comment": "a global field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "global"
+ "Reference": "global Fields"
}
],
"IntroducedVersion": 1,
@@ -1324,7 +1324,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1396,13 +1396,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F of the current transaction\n`txna` can be called using `txn` with 2 immediates.",
+ "Doc": "Ith value of the array field F of the current transaction",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1437,7 +1437,7 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Tth transaction in the current group\n`gtxna` can be called using `gtxn` with 3 immediates.",
+ "Doc": "Ith value of the array field F from the Tth transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction group index",
@@ -1448,7 +1448,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1605,7 +1605,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 3,
@@ -1638,13 +1638,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Ath transaction in the current group\n`gtxnsa` can be called using `gtxns` with 2 immediates.",
+ "Doc": "Ith value of the array field F from the Ath transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -2221,7 +2221,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails\n`extract3` can be called using `extract` with no immediates.",
+ "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails",
"IntroducedVersion": 5,
"Groups": [
"Byte Array Manipulation"
@@ -2296,7 +2296,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2315,7 +2315,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2334,7 +2334,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2355,7 +2355,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2373,7 +2373,7 @@
"DocExtra": "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2393,7 +2393,7 @@
"DocExtra": "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2410,7 +2410,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2425,7 +2425,7 @@
"Doc": "write B to key A in the global state of the current application",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2441,7 +2441,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2456,7 +2456,7 @@
"DocExtra": "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2487,12 +2487,12 @@
"Comment": "asset holding field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_holding"
+ "Reference": "asset_holding Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2542,12 +2542,12 @@
"Comment": "asset params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_params"
+ "Reference": "asset_params Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2591,12 +2591,12 @@
"Comment": "app params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "app_params"
+ "Reference": "app_params Fields"
}
],
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2614,7 +2614,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 3,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -3098,7 +3098,7 @@
"DocExtra": "`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.",
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -3388,7 +3388,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 5,
@@ -3424,7 +3424,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "a transaction field array index",
@@ -3468,7 +3468,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -3512,7 +3512,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -3552,7 +3552,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
diff --git a/data/transactions/logic/langspec_v6.json b/data/transactions/logic/langspec_v6.json
index 962063ccf3..7787119b96 100644
--- a/data/transactions/logic/langspec_v6.json
+++ b/data/transactions/logic/langspec_v6.json
@@ -201,7 +201,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -231,7 +231,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -264,7 +264,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -1124,7 +1124,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1180,7 +1180,7 @@
"Comment": "a global field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "global"
+ "Reference": "global Fields"
}
],
"IntroducedVersion": 1,
@@ -1338,7 +1338,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1410,13 +1410,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F of the current transaction\n`txna` can be called using `txn` with 2 immediates.",
+ "Doc": "Ith value of the array field F of the current transaction",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1451,7 +1451,7 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Tth transaction in the current group\n`gtxna` can be called using `gtxn` with 3 immediates.",
+ "Doc": "Ith value of the array field F from the Tth transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction group index",
@@ -1462,7 +1462,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1623,7 +1623,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 3,
@@ -1656,13 +1656,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Ath transaction in the current group\n`gtxnsa` can be called using `gtxns` with 2 immediates.",
+ "Doc": "Ith value of the array field F from the Ath transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -2239,7 +2239,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails\n`extract3` can be called using `extract` with no immediates.",
+ "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails",
"IntroducedVersion": 5,
"Groups": [
"Byte Array Manipulation"
@@ -2314,7 +2314,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2333,7 +2333,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2352,7 +2352,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2373,7 +2373,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2391,7 +2391,7 @@
"DocExtra": "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2411,7 +2411,7 @@
"DocExtra": "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2428,7 +2428,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2443,7 +2443,7 @@
"Doc": "write B to key A in the global state of the current application",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2459,7 +2459,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2474,7 +2474,7 @@
"DocExtra": "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2505,12 +2505,12 @@
"Comment": "asset holding field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_holding"
+ "Reference": "asset_holding Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2560,12 +2560,12 @@
"Comment": "asset params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_params"
+ "Reference": "asset_params Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2609,12 +2609,12 @@
"Comment": "app params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "app_params"
+ "Reference": "app_params Fields"
}
],
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2645,12 +2645,12 @@
"Comment": "account params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "acct_params"
+ "Reference": "acct_params Fields"
}
],
"IntroducedVersion": 6,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2668,7 +2668,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 3,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -3189,7 +3189,7 @@
"DocExtra": "`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.",
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -3485,7 +3485,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 5,
@@ -3521,7 +3521,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "a transaction field array index",
@@ -3736,7 +3736,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -3780,7 +3780,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -3824,7 +3824,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -3864,7 +3864,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -3924,7 +3924,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -3954,7 +3954,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
diff --git a/data/transactions/logic/langspec_v7.json b/data/transactions/logic/langspec_v7.json
index 22a1c166ea..f26813ddeb 100644
--- a/data/transactions/logic/langspec_v7.json
+++ b/data/transactions/logic/langspec_v7.json
@@ -202,7 +202,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -233,7 +233,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -267,7 +267,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -1137,7 +1137,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1193,7 +1193,7 @@
"Comment": "a global field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "global"
+ "Reference": "global Fields"
}
],
"IntroducedVersion": 1,
@@ -1361,7 +1361,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1437,13 +1437,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F of the current transaction\n`txna` can be called using `txn` with 2 immediates.",
+ "Doc": "Ith value of the array field F of the current transaction",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1482,7 +1482,7 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Tth transaction in the current group\n`gtxna` can be called using `gtxn` with 3 immediates.",
+ "Doc": "Ith value of the array field F from the Tth transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction group index",
@@ -1493,7 +1493,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1664,7 +1664,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 3,
@@ -1701,13 +1701,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Ath transaction in the current group\n`gtxnsa` can be called using `gtxns` with 2 immediates.",
+ "Doc": "Ith value of the array field F from the Ath transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -2284,7 +2284,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails\n`extract3` can be called using `extract` with no immediates.",
+ "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails",
"IntroducedVersion": 5,
"Groups": [
"Byte Array Manipulation"
@@ -2356,7 +2356,7 @@
],
"Size": 2,
"DocCost": "1",
- "Doc": "Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)\n`replace2` can be called using `replace` with 1 immediate.",
+ "Doc": "Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)",
"ImmediateNote": [
{
"Comment": "start position",
@@ -2382,7 +2382,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)\n`replace3` can be called using `replace` with no immediates.",
+ "Doc": "Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)",
"IntroducedVersion": 7,
"Groups": [
"Byte Array Manipulation"
@@ -2408,13 +2408,13 @@
],
"DocCost": "1 + 1 per 16 bytes of A",
"Doc": "decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E",
- "DocExtra": "*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings.\tThis opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
+ "DocExtra": "_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
"ImmediateNote": [
{
"Comment": "encoding index",
"Encoding": "uint8",
"Name": "E",
- "Reference": "base64"
+ "Reference": "base64 Encodings"
}
],
"IntroducedVersion": 7,
@@ -2445,13 +2445,13 @@
],
"DocCost": "25 + 2 per 7 bytes of A",
"Doc": "key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A",
- "DocExtra": "*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
+ "DocExtra": "_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
"ImmediateNote": [
{
"Comment": "return type index",
"Encoding": "uint8",
"Name": "R",
- "Reference": "json_ref"
+ "Reference": "json_ref Types"
}
],
"IntroducedVersion": 7,
@@ -2474,7 +2474,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2493,7 +2493,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2512,7 +2512,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2533,7 +2533,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2551,7 +2551,7 @@
"DocExtra": "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2571,7 +2571,7 @@
"DocExtra": "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2588,7 +2588,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2603,7 +2603,7 @@
"Doc": "write B to key A in the global state of the current application",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2619,7 +2619,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2634,7 +2634,7 @@
"DocExtra": "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2665,12 +2665,12 @@
"Comment": "asset holding field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_holding"
+ "Reference": "asset_holding Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2720,12 +2720,12 @@
"Comment": "asset params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_params"
+ "Reference": "asset_params Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2769,12 +2769,12 @@
"Comment": "app params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "app_params"
+ "Reference": "app_params Fields"
}
],
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2805,12 +2805,12 @@
"Comment": "account params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "acct_params"
+ "Reference": "acct_params Fields"
}
],
"IntroducedVersion": 6,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2828,7 +2828,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 3,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -3385,7 +3385,7 @@
"DocExtra": "`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.",
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -3695,7 +3695,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 5,
@@ -3735,7 +3735,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "a transaction field array index",
@@ -3964,7 +3964,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -4012,7 +4012,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4060,7 +4060,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4104,7 +4104,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4164,7 +4164,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -4194,7 +4194,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -4226,7 +4226,7 @@
"Comment": " parameters index",
"Encoding": "uint8",
"Name": "S",
- "Reference": "vrf_verify"
+ "Reference": "vrf_verify Standards"
}
],
"IntroducedVersion": 7,
@@ -4259,12 +4259,12 @@
"Comment": " block field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "block"
+ "Reference": "block Fields"
}
],
"IntroducedVersion": 7,
"Groups": [
- "State Access"
+ "Block Access"
]
}
]
diff --git a/data/transactions/logic/langspec_v8.json b/data/transactions/logic/langspec_v8.json
index 196db5f565..54f494c779 100644
--- a/data/transactions/logic/langspec_v8.json
+++ b/data/transactions/logic/langspec_v8.json
@@ -202,7 +202,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -233,7 +233,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -267,7 +267,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -1137,7 +1137,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1193,7 +1193,7 @@
"Comment": "a global field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "global"
+ "Reference": "global Fields"
}
],
"IntroducedVersion": 1,
@@ -1361,7 +1361,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1437,13 +1437,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F of the current transaction\n`txna` can be called using `txn` with 2 immediates.",
+ "Doc": "Ith value of the array field F of the current transaction",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1482,7 +1482,7 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Tth transaction in the current group\n`gtxna` can be called using `gtxn` with 3 immediates.",
+ "Doc": "Ith value of the array field F from the Tth transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction group index",
@@ -1493,7 +1493,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1664,7 +1664,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 3,
@@ -1701,13 +1701,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Ath transaction in the current group\n`gtxnsa` can be called using `gtxns` with 2 immediates.",
+ "Doc": "Ith value of the array field F from the Ath transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -2344,7 +2344,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails\n`extract3` can be called using `extract` with no immediates.",
+ "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails",
"IntroducedVersion": 5,
"Groups": [
"Byte Array Manipulation"
@@ -2416,7 +2416,7 @@
],
"Size": 2,
"DocCost": "1",
- "Doc": "Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)\n`replace2` can be called using `replace` with 1 immediate.",
+ "Doc": "Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)",
"ImmediateNote": [
{
"Comment": "start position",
@@ -2442,7 +2442,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)\n`replace3` can be called using `replace` with no immediates.",
+ "Doc": "Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)",
"IntroducedVersion": 7,
"Groups": [
"Byte Array Manipulation"
@@ -2468,13 +2468,13 @@
],
"DocCost": "1 + 1 per 16 bytes of A",
"Doc": "decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E",
- "DocExtra": "*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings.\tThis opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
+ "DocExtra": "_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
"ImmediateNote": [
{
"Comment": "encoding index",
"Encoding": "uint8",
"Name": "E",
- "Reference": "base64"
+ "Reference": "base64 Encodings"
}
],
"IntroducedVersion": 7,
@@ -2505,13 +2505,13 @@
],
"DocCost": "25 + 2 per 7 bytes of A",
"Doc": "key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A",
- "DocExtra": "*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
+ "DocExtra": "_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
"ImmediateNote": [
{
"Comment": "return type index",
"Encoding": "uint8",
"Name": "R",
- "Reference": "json_ref"
+ "Reference": "json_ref Types"
}
],
"IntroducedVersion": 7,
@@ -2534,7 +2534,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2553,7 +2553,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2572,7 +2572,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2593,7 +2593,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2611,7 +2611,7 @@
"DocExtra": "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2631,7 +2631,7 @@
"DocExtra": "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2648,7 +2648,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2663,7 +2663,7 @@
"Doc": "write B to key A in the global state of the current application",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2679,7 +2679,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2694,7 +2694,7 @@
"DocExtra": "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2725,12 +2725,12 @@
"Comment": "asset holding field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_holding"
+ "Reference": "asset_holding Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2780,12 +2780,12 @@
"Comment": "asset params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_params"
+ "Reference": "asset_params Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2829,12 +2829,12 @@
"Comment": "app params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "app_params"
+ "Reference": "app_params Fields"
}
],
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2883,12 +2883,12 @@
"Comment": "account params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "acct_params"
+ "Reference": "acct_params Fields"
}
],
"IntroducedVersion": 6,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2906,7 +2906,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 3,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -3607,7 +3607,7 @@
"DocExtra": "`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.",
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -3917,7 +3917,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 5,
@@ -3957,7 +3957,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "a transaction field array index",
@@ -4186,7 +4186,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -4358,7 +4358,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4406,7 +4406,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4450,7 +4450,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4510,7 +4510,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -4540,7 +4540,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -4572,7 +4572,7 @@
"Comment": " parameters index",
"Encoding": "uint8",
"Name": "S",
- "Reference": "vrf_verify"
+ "Reference": "vrf_verify Standards"
}
],
"IntroducedVersion": 7,
@@ -4605,12 +4605,12 @@
"Comment": " block field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "block"
+ "Reference": "block Fields"
}
],
"IntroducedVersion": 7,
"Groups": [
- "State Access"
+ "Block Access"
]
}
]
diff --git a/data/transactions/logic/langspec_v9.json b/data/transactions/logic/langspec_v9.json
index 5ac362e3c4..c23f7d5d0f 100644
--- a/data/transactions/logic/langspec_v9.json
+++ b/data/transactions/logic/langspec_v9.json
@@ -202,7 +202,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -233,7 +233,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -267,7 +267,7 @@
"Comment": "curve index",
"Encoding": "uint8",
"Name": "V",
- "Reference": "ECDSA"
+ "Reference": "ECDSA Curves"
}
],
"IntroducedVersion": 5,
@@ -1137,7 +1137,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1193,7 +1193,7 @@
"Comment": "a global field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "global"
+ "Reference": "global Fields"
}
],
"IntroducedVersion": 1,
@@ -1361,7 +1361,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 1,
@@ -1437,13 +1437,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F of the current transaction\n`txna` can be called using `txn` with 2 immediates.",
+ "Doc": "Ith value of the array field F of the current transaction",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1482,7 +1482,7 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Tth transaction in the current group\n`gtxna` can be called using `gtxn` with 3 immediates.",
+ "Doc": "Ith value of the array field F from the Tth transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction group index",
@@ -1493,7 +1493,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -1664,7 +1664,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 3,
@@ -1701,13 +1701,13 @@
"[]byte"
],
"DocCost": "1",
- "Doc": "Ith value of the array field F from the Ath transaction in the current group\n`gtxnsa` can be called using `gtxns` with 2 immediates.",
+ "Doc": "Ith value of the array field F from the Ath transaction in the current group",
"ImmediateNote": [
{
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -2344,7 +2344,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails\n`extract3` can be called using `extract` with no immediates.",
+ "Doc": "A range of bytes from A starting at B up to but not including B+C. If B+C is larger than the array length, the program fails",
"IntroducedVersion": 5,
"Groups": [
"Byte Array Manipulation"
@@ -2416,7 +2416,7 @@
],
"Size": 2,
"DocCost": "1",
- "Doc": "Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)\n`replace2` can be called using `replace` with 1 immediate.",
+ "Doc": "Copy of A with the bytes starting at S replaced by the bytes of B. Fails if S+len(B) exceeds len(A)",
"ImmediateNote": [
{
"Comment": "start position",
@@ -2442,7 +2442,7 @@
],
"Size": 1,
"DocCost": "1",
- "Doc": "Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)\n`replace3` can be called using `replace` with no immediates.",
+ "Doc": "Copy of A with the bytes starting at B replaced by the bytes of C. Fails if B+len(C) exceeds len(A)",
"IntroducedVersion": 7,
"Groups": [
"Byte Array Manipulation"
@@ -2468,13 +2468,13 @@
],
"DocCost": "1 + 1 per 16 bytes of A",
"Doc": "decode A which was base64-encoded using _encoding_ E. Fail if A is not base64 encoded with encoding E",
- "DocExtra": "*Warning*: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings.\tThis opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
+ "DocExtra": "_Warning_: Usage should be restricted to very rare use cases. In almost all cases, smart contracts should directly handle non-encoded byte-strings. This opcode should only be used in cases where base64 is the only available option, e.g. interoperability with a third-party that only signs base64 strings.\n\n Decodes A using the base64 encoding E. Specify the encoding with an immediate arg either as URL and Filename Safe (`URLEncoding`) or Standard (`StdEncoding`). See [RFC 4648 sections 4 and 5](https://rfc-editor.org/rfc/rfc4648.html#section-4). It is assumed that the encoding ends with the exact number of `=` padding characters as required by the RFC. When padding occurs, any unused pad bits in the encoding must be set to zero or the decoding will fail. The special cases of `\\n` and `\\r` are allowed but completely ignored. An error will result when attempting to decode a string with a character that is not in the encoding alphabet or not one of `=`, `\\r`, or `\\n`.",
"ImmediateNote": [
{
"Comment": "encoding index",
"Encoding": "uint8",
"Name": "E",
- "Reference": "base64"
+ "Reference": "base64 Encodings"
}
],
"IntroducedVersion": 7,
@@ -2505,13 +2505,13 @@
],
"DocCost": "25 + 2 per 7 bytes of A",
"Doc": "key B's value, of type R, from a [valid](jsonspec.md) utf-8 encoded json object A",
- "DocExtra": "*Warning*: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
+ "DocExtra": "_Warning_: Usage should be restricted to very rare use cases, as JSON decoding is expensive and quite limited. In addition, JSON objects are large and not optimized for size.\n\nAlmost all smart contracts should use simpler and smaller methods (such as the [ABI](https://arc.algorand.foundation/ARCs/arc-0004). This opcode should only be used in cases where JSON is only available option, e.g. when a third-party only signs JSON.",
"ImmediateNote": [
{
"Comment": "return type index",
"Encoding": "uint8",
"Name": "R",
- "Reference": "json_ref"
+ "Reference": "json_ref Types"
}
],
"IntroducedVersion": 7,
@@ -2534,7 +2534,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2553,7 +2553,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: 1 if opted in and 0 otherwise.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2572,7 +2572,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2593,7 +2593,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2611,7 +2611,7 @@
"DocExtra": "params: state key. Return: value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2631,7 +2631,7 @@
"DocExtra": "params: Txn.ForeignApps offset (or, since v4, an _available_ application id), state key. Return: did_exist flag (top of the stack, 1 if the application and key existed and 0 otherwise), value. The value is zero (of type uint64) if the key does not exist.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2648,7 +2648,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key, value.",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2663,7 +2663,7 @@
"Doc": "write B to key A in the global state of the current application",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2679,7 +2679,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), state key.\n\nDeleting a key which is already absent has no effect on the application local state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2694,7 +2694,7 @@
"DocExtra": "params: state key.\n\nDeleting a key which is already absent has no effect on the application global state. (In particular, it does _not_ cause the program to fail.)",
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2725,12 +2725,12 @@
"Comment": "asset holding field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_holding"
+ "Reference": "asset_holding Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2780,12 +2780,12 @@
"Comment": "asset params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "asset_params"
+ "Reference": "asset_params Fields"
}
],
"IntroducedVersion": 2,
"Groups": [
- "State Access"
+ "Asset Access"
]
},
{
@@ -2829,12 +2829,12 @@
"Comment": "app params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "app_params"
+ "Reference": "app_params Fields"
}
],
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Application Access"
]
},
{
@@ -2883,12 +2883,12 @@
"Comment": "account params field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "acct_params"
+ "Reference": "acct_params Fields"
}
],
"IntroducedVersion": 6,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -2906,7 +2906,7 @@
"DocExtra": "params: Txn.Accounts offset (or, since v4, an _available_ account address), _available_ application id (or, since v4, a Txn.ForeignApps offset). Return: value.",
"IntroducedVersion": 3,
"Groups": [
- "State Access"
+ "Account Access"
]
},
{
@@ -3607,7 +3607,7 @@
"DocExtra": "`log` fails if called more than MaxLogCalls times in a program, or if the sum of logged bytes exceeds 1024 bytes.",
"IntroducedVersion": 5,
"Groups": [
- "State Access"
+ "Block Access"
]
},
{
@@ -3917,7 +3917,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txn"
+ "Reference": "txn Fields"
}
],
"IntroducedVersion": 5,
@@ -3957,7 +3957,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "a transaction field array index",
@@ -4186,7 +4186,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
},
{
"Comment": "transaction field array index",
@@ -4358,7 +4358,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4406,7 +4406,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4450,7 +4450,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 5,
@@ -4510,7 +4510,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -4540,7 +4540,7 @@
"Comment": "transaction field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "txna"
+ "Reference": "txna Fields"
}
],
"IntroducedVersion": 6,
@@ -4572,7 +4572,7 @@
"Comment": " parameters index",
"Encoding": "uint8",
"Name": "S",
- "Reference": "vrf_verify"
+ "Reference": "vrf_verify Standards"
}
],
"IntroducedVersion": 7,
@@ -4605,12 +4605,12 @@
"Comment": " block field index",
"Encoding": "uint8",
"Name": "F",
- "Reference": "block"
+ "Reference": "block Fields"
}
],
"IntroducedVersion": 7,
"Groups": [
- "State Access"
+ "Block Access"
]
}
]
diff --git a/data/transactions/logic/ledger_test.go b/data/transactions/logic/ledger_test.go
index fb95d70d73..bbd2a88654 100644
--- a/data/transactions/logic/ledger_test.go
+++ b/data/transactions/logic/ledger_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -138,6 +138,12 @@ func (l *Ledger) NewApp(creator basics.Address, appID basics.AppIndex, params ba
}
}
+func (l *Ledger) SetAppGlobalSchema(appID basics.AppIndex, schema basics.StateSchema) {
+ app := l.applications[appID]
+ app.GlobalStateSchema = schema
+ l.applications[appID] = app
+}
+
// NewAsset adds an asset with the given id and params to the ledger.
func (l *Ledger) NewAsset(creator basics.Address, assetID basics.AssetIndex, params basics.AssetParams) {
l.assets[assetID] = asaParams{
@@ -187,9 +193,25 @@ func (l *Ledger) NewLocals(addr basics.Address, appID basics.AppIndex) {
l.balances[addr].locals[appID] = basics.TealKeyValue{}
}
+func toTealValue(value any) basics.TealValue {
+ switch v := value.(type) {
+ case int:
+ return basics.TealValue{Type: basics.TealUintType, Uint: uint64(v)}
+ case uint64:
+ return basics.TealValue{Type: basics.TealUintType, Uint: v}
+ case string:
+ return basics.TealValue{Type: basics.TealBytesType, Bytes: v}
+ case []byte:
+ return basics.TealValue{Type: basics.TealBytesType, Bytes: string(v)}
+ case basics.TealValue:
+ return v
+ }
+ panic(value)
+}
+
// NewLocal sets a local value of an app on an address
-func (l *Ledger) NewLocal(addr basics.Address, appID basics.AppIndex, key string, value basics.TealValue) {
- l.balances[addr].locals[appID][key] = value
+func (l *Ledger) NewLocal(addr basics.Address, appID basics.AppIndex, key string, value any) {
+ l.balances[addr].locals[appID][key] = toTealValue(value)
}
// NoLocal removes a key from an address locals for an app.
@@ -197,9 +219,17 @@ func (l *Ledger) NoLocal(addr basics.Address, appID basics.AppIndex, key string)
delete(l.balances[addr].locals[appID], key)
}
-// NewGlobal sets a global value for an app
-func (l *Ledger) NewGlobal(appID basics.AppIndex, key string, value basics.TealValue) {
- l.applications[appID].GlobalState[key] = value
+// NewGlobal sets a global value for an app incrmementing the schema to accommodate it
+func (l *Ledger) NewGlobal(appID basics.AppIndex, key string, value any) {
+ tv := toTealValue(value)
+ app := l.applications[appID]
+ app.GlobalState[key] = tv
+ if tv.Type == basics.TealBytesType {
+ app.GlobalStateSchema.NumByteSlice++
+ } else {
+ app.GlobalStateSchema.NumUint++
+ }
+ l.applications[appID] = app
}
// NoGlobal removes a global key for an app
@@ -215,7 +245,7 @@ func (l *Ledger) Rekey(addr basics.Address, auth basics.Address) {
}
}
-// LatestTimestamp gives a uint64, chosen randomly. It should
+// PrevTimestamp gives a uint64, chosen randomly. It should
// probably increase monotonically, but no tests care yet.
func (l *Ledger) PrevTimestamp() int64 {
return int64(rand.Uint32() + 1)
@@ -398,13 +428,40 @@ func (l *Ledger) SetGlobal(appIdx basics.AppIndex, key string, value basics.Teal
return fmt.Errorf("no app %d", appIdx)
}
- // if writing the same value, return
- // this simulates real ledger behavior for tests
- val, ok := params.GlobalState[key]
- if ok && val == value {
+ // Populate globals from the app object, then add in the mods
+ globals := params.GlobalState.Clone() // this does not contain the running changes in mods
+ for k, vd := range l.mods[appIdx] {
+ tv, exists := vd.ToTealValue()
+ if exists {
+ globals[k] = tv
+ } else {
+ delete(globals, k)
+ }
+ }
+
+ // if writing the same value, return to simulate real ledger behavior for
+ // tests
+ val, present := globals[key]
+ if present && val == value {
return nil
}
+ delete(globals, key) // remove before getting schema, since type may change
+ required, err := globals.ToStateSchema()
+ if err != nil {
+ return err
+ }
+ // now add it back in, possibly with new type
+ if value.Type == basics.TealBytesType {
+ required.NumByteSlice++
+ } else {
+ required.NumUint++
+ }
+ if !params.GlobalStateSchema.Allows(required) {
+ return fmt.Errorf("app %d global schema %s does not allow %s",
+ appIdx, params.GlobalStateSchema, required)
+ }
+
// write to deltas
_, ok = l.mods[appIdx]
if !ok {
@@ -919,7 +976,19 @@ func (l *Ledger) appl(from basics.Address, appl transactions.ApplicationCallTxnF
}
app.ApprovalProgram = appl.ApprovalProgram
app.ClearStateProgram = appl.ClearStateProgram
- app.Version++
+ if ep.Proto.EnableAppVersioning {
+ app.Version++
+ }
+ if appl.UpdatingSizes() {
+ if ep.Proto.AppSizeUpdates {
+ app.ExtraProgramPages = appl.ExtraProgramPages
+ app.GlobalStateSchema = appl.GlobalStateSchema
+ app.SizeSponsor = from
+ } else {
+ return fmt.Errorf("Tried to update size epp=%v gs=%v",
+ appl.ExtraProgramPages, appl.GlobalStateSchema)
+ }
+ }
l.applications[aid] = app
}
return nil
diff --git a/data/transactions/logic/merge.py b/data/transactions/logic/merge.py
deleted file mode 100644
index daf05862d6..0000000000
--- a/data/transactions/logic/merge.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env python
-
-import re
-import sys
-
-import_re = re.compile(r'^@@\s+(\S+)\s+@@$')
-
-out = sys.stdout
-
-fin = open('README_in.md')
-for line in fin:
- m = import_re.match(line)
- if m:
- with open(m.group(1), 'rt') as subf:
- out.write(subf.read())
- continue
- out.write(line)
diff --git a/data/transactions/logic/mocktracer/scenarios.go b/data/transactions/logic/mocktracer/scenarios.go
index c0f4d11fb2..dc529595c6 100644
--- a/data/transactions/logic/mocktracer/scenarios.go
+++ b/data/transactions/logic/mocktracer/scenarios.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/mocktracer/tracer.go b/data/transactions/logic/mocktracer/tracer.go
index 1c89687d20..050fa7bbe4 100644
--- a/data/transactions/logic/mocktracer/tracer.go
+++ b/data/transactions/logic/mocktracer/tracer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/opcodeExplain.go b/data/transactions/logic/opcodeExplain.go
index a9360fe520..f25c5d1c16 100644
--- a/data/transactions/logic/opcodeExplain.go
+++ b/data/transactions/logic/opcodeExplain.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/opcodes.go b/data/transactions/logic/opcodes.go
index 6dc75d555e..1d1f3d29fa 100644
--- a/data/transactions/logic/opcodes.go
+++ b/data/transactions/logic/opcodes.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -339,7 +339,7 @@ func costByLength(initial, perChunk, chunkSize, depth int) OpDetails {
return d
}
-// immType describes the immediate arguments to an opcode
+// immKind describes the immediate arguments to an opcode
type immKind byte
const (
@@ -486,8 +486,6 @@ func (spec *OpSpec) deadens() bool {
// OpSpecs is the table of operations that can be assembled and evaluated.
//
-// Any changes should be reflected in README_in.md which serves as the language spec.
-//
// Note: assembly can specialize an Any return type if known at
// assembly-time, with ops.returns()
var OpSpecs = []OpSpec{
diff --git a/data/transactions/logic/opcodes_test.go b/data/transactions/logic/opcodes_test.go
index 86965d0887..bdb8fb4441 100644
--- a/data/transactions/logic/opcodes_test.go
+++ b/data/transactions/logic/opcodes_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/pairing.go b/data/transactions/logic/pairing.go
index cb4ac4a0cc..25acf7a280 100644
--- a/data/transactions/logic/pairing.go
+++ b/data/transactions/logic/pairing.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/pairing_test.go b/data/transactions/logic/pairing_test.go
index c59a243ff4..f97e4e57c4 100644
--- a/data/transactions/logic/pairing_test.go
+++ b/data/transactions/logic/pairing_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/program.go b/data/transactions/logic/program.go
index 5747ad9a5c..5b4521c0ff 100644
--- a/data/transactions/logic/program.go
+++ b/data/transactions/logic/program.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/resources.go b/data/transactions/logic/resources.go
index 39204daaf3..7046ec3637 100644
--- a/data/transactions/logic/resources.go
+++ b/data/transactions/logic/resources.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -252,11 +252,9 @@ func (cx *EvalContext) requireLocals(acct basics.Address, id basics.AppIndex) er
}
func (cx *EvalContext) allowsAssetTransfer(hdr *transactions.Header, tx *transactions.AssetTransferTxnFields) error {
- // After EnableInnerClawbackWithoutSenderHolding appears in a consensus
- // update, we should remove it from consensus params and assume it's true in
- // the next release. It only needs to be in there so that it gates the
- // behavior change in the release it first appears.
- if !cx.Proto.EnableInnerClawbackWithoutSenderHolding || tx.AssetSender.IsZero() {
+ // When AssetSender is set (we're doing a clawback) we don't need the
+ // Sender's holding. The Sender/ClawbackAddress may not even have the asset.
+ if tx.AssetSender.IsZero() {
err := cx.requireHolding(hdr.Sender, tx.XferAsset)
if err != nil {
return fmt.Errorf("axfer Sender: %w", err)
@@ -323,17 +321,14 @@ func (r *resources) fillApplicationCallAccess(ep *EvalParams, hdr *transactions.
r.shareHolding(address, asset)
case !rr.Locals.Empty():
// ApplicationCallTxnFields.wellFormed ensures no error here.
- address, app, _ := rr.Locals.Resolve(tx.Access, hdr.Sender)
+ address, app, _ := rr.Locals.Resolve(tx.Access, hdr.Sender, tx.ApplicationID)
r.shareLocal(address, app)
case !rr.Box.Empty():
// ApplicationCallTxnFields.wellFormed ensures no error here.
app, name, _ := rr.Box.Resolve(tx.Access)
r.shareBox(basics.BoxRef{App: app, Name: name}, tx.ApplicationID)
default:
- // all empty equals an "empty boxref" which allows one unnamed access
- if ep.Proto.EnableUnnamedBoxAccessInNewApps {
- r.unnamedAccess++
- }
+ r.unnamedAccess++
}
}
}
@@ -374,7 +369,7 @@ func (r *resources) fillApplicationCallForeign(ep *EvalParams, hdr *transactions
}
for _, br := range tx.Boxes {
- if ep.Proto.EnableUnnamedBoxAccessInNewApps && br.Empty() {
+ if br.Empty() {
r.unnamedAccess++
}
var app basics.AppIndex
diff --git a/data/transactions/logic/resources_test.go b/data/transactions/logic/resources_test.go
index 502f178f12..11691a0bc5 100644
--- a/data/transactions/logic/resources_test.go
+++ b/data/transactions/logic/resources_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/sourcemap.go b/data/transactions/logic/sourcemap.go
index 6d7e186fa7..458dae7b4f 100644
--- a/data/transactions/logic/sourcemap.go
+++ b/data/transactions/logic/sourcemap.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/sourcemap_test.go b/data/transactions/logic/sourcemap_test.go
index c6465a15a8..04159bdc90 100644
--- a/data/transactions/logic/sourcemap_test.go
+++ b/data/transactions/logic/sourcemap_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/teal.tmLanguage.json b/data/transactions/logic/teal.tmLanguage.json
index 5473503ad0..06e7a4d6bc 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|online_stake|voter_params_get)\\b"
+ "match": "^(acct_params_get|balance|min_balance|voter_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|block|log|online_stake|box_create|box_del|box_extract|box_get|box_len|box_put|box_replace|box_resize|box_splice)\\b"
},
{
"name": "keyword.operator.teal",
@@ -112,7 +112,7 @@
},
{
"name": "variable.parameter.teal",
- "match": "\\b(unknown|pay|keyreg|acfg|axfer|afrz|appl|NoOp|OptIn|CloseOut|ClearState|UpdateApplication|DeleteApplication|Secp256k1|Secp256r1|Sender|Fee|FirstValid|FirstValidTime|LastValid|Note|Lease|Receiver|Amount|CloseRemainderTo|VotePK|SelectionPK|VoteFirst|VoteLast|VoteKeyDilution|Type|TypeEnum|XferAsset|AssetAmount|AssetSender|AssetReceiver|AssetCloseTo|GroupIndex|TxID|ApplicationID|OnCompletion|NumAppArgs|NumAccounts|ApprovalProgram|ClearStateProgram|RekeyTo|ConfigAsset|ConfigAssetTotal|ConfigAssetDecimals|ConfigAssetDefaultFrozen|ConfigAssetUnitName|ConfigAssetName|ConfigAssetURL|ConfigAssetMetadataHash|ConfigAssetManager|ConfigAssetReserve|ConfigAssetFreeze|ConfigAssetClawback|FreezeAsset|FreezeAssetAccount|FreezeAssetFrozen|NumAssets|NumApplications|GlobalNumUint|GlobalNumByteSlice|LocalNumUint|LocalNumByteSlice|ExtraProgramPages|Nonparticipation|NumLogs|CreatedAssetID|CreatedApplicationID|LastLog|StateProofPK|NumApprovalProgramPages|NumClearStateProgramPages|RejectVersion|MinTxnFee|MinBalance|MaxTxnLife|ZeroAddress|GroupSize|LogicSigVersion|Round|LatestTimestamp|CurrentApplicationID|CreatorAddress|CurrentApplicationAddress|GroupID|OpcodeBudget|CallerApplicationID|CallerApplicationAddress|AssetCreateMinBalance|AssetOptInMinBalance|GenesisHash|PayoutsEnabled|PayoutsGoOnlineFee|PayoutsPercent|PayoutsMinBalance|PayoutsMaxBalance|ApplicationArgs|Accounts|Assets|Applications|Logs|ApprovalProgramPages|ClearStateProgramPages|URLEncoding|StdEncoding|JSONString|JSONUint64|JSONObject|AssetBalance|AssetFrozen|AssetTotal|AssetDecimals|AssetDefaultFrozen|AssetUnitName|AssetName|AssetURL|AssetMetadataHash|AssetManager|AssetReserve|AssetFreeze|AssetClawback|AssetCreator|AppApprovalProgram|AppClearStateProgram|AppGlobalNumUint|AppGlobalNumByteSlice|AppLocalNumUint|AppLocalNumByteSlice|AppExtraProgramPages|AppCreator|AppAddress|AppVersion|AcctBalance|AcctMinBalance|AcctAuthAddr|AcctTotalNumUint|AcctTotalNumByteSlice|AcctTotalExtraAppPages|AcctTotalAppsCreated|AcctTotalAppsOptedIn|AcctTotalAssetsCreated|AcctTotalAssets|AcctTotalBoxes|AcctTotalBoxBytes|AcctIncentiveEligible|AcctLastProposed|AcctLastHeartbeat|VoterBalance|VoterIncentiveEligible|VrfAlgorand|BlkSeed|BlkTimestamp|BlkProposer|BlkFeesCollected|BlkBonus|BlkBranch|BlkFeeSink|BlkProtocol|BlkTxnCounter|BlkProposerPayout|BN254g1|BN254g2|BLS12_381g1|BLS12_381g2|BN254Mp110|BLS12_381Mp111)\\b"
+ "match": "\\b(unknown|pay|keyreg|acfg|axfer|afrz|appl|stpf|hb|NoOp|OptIn|CloseOut|ClearState|UpdateApplication|DeleteApplication|Secp256k1|Secp256r1|Sender|Fee|FirstValid|FirstValidTime|LastValid|Note|Lease|Receiver|Amount|CloseRemainderTo|VotePK|SelectionPK|VoteFirst|VoteLast|VoteKeyDilution|Type|TypeEnum|XferAsset|AssetAmount|AssetSender|AssetReceiver|AssetCloseTo|GroupIndex|TxID|ApplicationID|OnCompletion|NumAppArgs|NumAccounts|ApprovalProgram|ClearStateProgram|RekeyTo|ConfigAsset|ConfigAssetTotal|ConfigAssetDecimals|ConfigAssetDefaultFrozen|ConfigAssetUnitName|ConfigAssetName|ConfigAssetURL|ConfigAssetMetadataHash|ConfigAssetManager|ConfigAssetReserve|ConfigAssetFreeze|ConfigAssetClawback|FreezeAsset|FreezeAssetAccount|FreezeAssetFrozen|NumAssets|NumApplications|GlobalNumUint|GlobalNumByteSlice|LocalNumUint|LocalNumByteSlice|ExtraProgramPages|Nonparticipation|NumLogs|CreatedAssetID|CreatedApplicationID|LastLog|StateProofPK|NumApprovalProgramPages|NumClearStateProgramPages|RejectVersion|MinTxnFee|MinBalance|MaxTxnLife|ZeroAddress|GroupSize|LogicSigVersion|Round|LatestTimestamp|CurrentApplicationID|CreatorAddress|CurrentApplicationAddress|GroupID|OpcodeBudget|CallerApplicationID|CallerApplicationAddress|AssetCreateMinBalance|AssetOptInMinBalance|GenesisHash|PayoutsEnabled|PayoutsGoOnlineFee|PayoutsPercent|PayoutsMinBalance|PayoutsMaxBalance|ApplicationArgs|Accounts|Assets|Applications|Logs|ApprovalProgramPages|ClearStateProgramPages|URLEncoding|StdEncoding|JSONString|JSONUint64|JSONObject|AssetBalance|AssetFrozen|AssetTotal|AssetDecimals|AssetDefaultFrozen|AssetUnitName|AssetName|AssetURL|AssetMetadataHash|AssetManager|AssetReserve|AssetFreeze|AssetClawback|AssetCreator|AppApprovalProgram|AppClearStateProgram|AppGlobalNumUint|AppGlobalNumByteSlice|AppLocalNumUint|AppLocalNumByteSlice|AppExtraProgramPages|AppCreator|AppAddress|AppVersion|AcctBalance|AcctMinBalance|AcctAuthAddr|AcctTotalNumUint|AcctTotalNumByteSlice|AcctTotalExtraAppPages|AcctTotalAppsCreated|AcctTotalAppsOptedIn|AcctTotalAssetsCreated|AcctTotalAssets|AcctTotalBoxes|AcctTotalBoxBytes|AcctIncentiveEligible|AcctLastProposed|AcctLastHeartbeat|VoterBalance|VoterIncentiveEligible|VrfAlgorand|BlkSeed|BlkTimestamp|BlkProposer|BlkFeesCollected|BlkBonus|BlkBranch|BlkFeeSink|BlkProtocol|BlkTxnCounter|BlkProposerPayout|BN254g1|BN254g2|BLS12_381g1|BLS12_381g2|BN254Mp110|BLS12_381Mp111)\\b"
}
]
},
diff --git a/data/transactions/logic/tracer.go b/data/transactions/logic/tracer.go
index d8cd980603..d59b736e0d 100644
--- a/data/transactions/logic/tracer.go
+++ b/data/transactions/logic/tracer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/logic/tracer_test.go b/data/transactions/logic/tracer_test.go
index ad4f953b62..386c9ee3a7 100644
--- a/data/transactions/logic/tracer_test.go
+++ b/data/transactions/logic/tracer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -214,7 +214,7 @@ func (t *panicTracer) AfterOpcode(cx *EvalContext, evalError error) {
panic("panicTracer panics")
}
-// TestEvalWithTracerTracerPanic ensures that tracer panics get recovered and turned into errors
+// TestEvalWithTracerPanic ensures that tracer panics get recovered and turned into errors
func TestEvalWithTracerPanic(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
diff --git a/data/transactions/logicsig.go b/data/transactions/logicsig.go
index ad861f0a9b..15abda1611 100644
--- a/data/transactions/logicsig.go
+++ b/data/transactions/logicsig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/msgp_gen.go b/data/transactions/msgp_gen.go
index a0d916fa10..5f6fabcea6 100644
--- a/data/transactions/msgp_gen.go
+++ b/data/transactions/msgp_gen.go
@@ -1,7 +1,7 @@
-package transactions
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package transactions
+
import (
"sort"
@@ -1230,7 +1230,7 @@ func (z *ApplicationCallTxnFields) MsgIsZero() bool {
return ((*z).ApplicationID.MsgIsZero()) && ((*z).OnCompletion == 0) && (len((*z).ApplicationArgs) == 0) && (len((*z).Accounts) == 0) && (len((*z).ForeignAssets) == 0) && (len((*z).ForeignApps) == 0) && (len((*z).Access) == 0) && (len((*z).Boxes) == 0) && ((*z).LocalStateSchema.MsgIsZero()) && ((*z).GlobalStateSchema.MsgIsZero()) && (len((*z).ApprovalProgram) == 0) && (len((*z).ClearStateProgram) == 0) && ((*z).ExtraProgramPages == 0) && ((*z).RejectVersion == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// ApplicationCallTxnFieldsMaxSize returns a maximum valid message size for this message type
func ApplicationCallTxnFieldsMaxSize() (s int) {
s = 1 + 5 + basics.AppIndexMaxSize() + 5 + msgp.Uint64Size + 5
// Calculating size of slice: z.ApplicationArgs
@@ -1528,7 +1528,7 @@ func (z *ApplyData) MsgIsZero() bool {
return ((*z).ClosingAmount.MsgIsZero()) && ((*z).AssetClosingAmount == 0) && ((*z).SenderRewards.MsgIsZero()) && ((*z).ReceiverRewards.MsgIsZero()) && ((*z).CloseRewards.MsgIsZero()) && ((*z).EvalDelta.MsgIsZero()) && ((*z).ConfigAsset.MsgIsZero()) && ((*z).ApplicationID.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// ApplyDataMaxSize returns a maximum valid message size for this message type
func ApplyDataMaxSize() (s int) {
s = 1 + 3 + basics.MicroAlgosMaxSize() + 4 + msgp.Uint64Size + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + EvalDeltaMaxSize() + 5 + basics.AssetIndexMaxSize() + 5 + basics.AppIndexMaxSize()
return
@@ -1671,7 +1671,7 @@ func (z *AssetConfigTxnFields) MsgIsZero() bool {
return ((*z).ConfigAsset.MsgIsZero()) && ((*z).AssetParams.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// AssetConfigTxnFieldsMaxSize returns a maximum valid message size for this message type
func AssetConfigTxnFieldsMaxSize() (s int) {
s = 1 + 5 + basics.AssetIndexMaxSize() + 5 + basics.AssetParamsMaxSize()
return
@@ -1837,7 +1837,7 @@ func (z *AssetFreezeTxnFields) MsgIsZero() bool {
return ((*z).FreezeAccount.MsgIsZero()) && ((*z).FreezeAsset.MsgIsZero()) && ((*z).AssetFrozen == false)
}
-// MaxSize returns a maximum valid message size for this message type
+// AssetFreezeTxnFieldsMaxSize returns a maximum valid message size for this message type
func AssetFreezeTxnFieldsMaxSize() (s int) {
s = 1 + 5 + basics.AddressMaxSize() + 5 + basics.AssetIndexMaxSize() + 5 + msgp.BoolSize
return
@@ -2049,7 +2049,7 @@ func (z *AssetTransferTxnFields) MsgIsZero() bool {
return ((*z).XferAsset.MsgIsZero()) && ((*z).AssetAmount == 0) && ((*z).AssetSender.MsgIsZero()) && ((*z).AssetReceiver.MsgIsZero()) && ((*z).AssetCloseTo.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// AssetTransferTxnFieldsMaxSize returns a maximum valid message size for this message type
func AssetTransferTxnFieldsMaxSize() (s int) {
s = 1 + 5 + basics.AssetIndexMaxSize() + 5 + msgp.Uint64Size + 5 + basics.AddressMaxSize() + 5 + basics.AddressMaxSize() + 7 + basics.AddressMaxSize()
return
@@ -2212,7 +2212,7 @@ func (z *BoxRef) MsgIsZero() bool {
return ((*z).Index == 0) && (len((*z).Name) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// BoxRefMaxSize returns a maximum valid message size for this message type
func BoxRefMaxSize() (s int) {
s = 1 + 2 + msgp.Uint64Size + 2 + msgp.BytesPrefixSize + bounds.MaxBytesKeyValueLen
return
@@ -2661,7 +2661,7 @@ func (z *EvalDelta) MsgIsZero() bool {
return ((*z).GlobalDelta.MsgIsZero()) && (len((*z).LocalDeltas) == 0) && (len((*z).SharedAccts) == 0) && (len((*z).Logs) == 0) && (len((*z).InnerTxns) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// EvalDeltaMaxSize returns a maximum valid message size for this message type
func EvalDeltaMaxSize() (s int) {
s = 1 + 3 + basics.StateDeltaMaxSize() + 3
s += msgp.MapHeaderSize
@@ -3041,7 +3041,7 @@ func (z *Header) MsgIsZero() bool {
return ((*z).Sender.MsgIsZero()) && ((*z).Fee.MsgIsZero()) && ((*z).FirstValid.MsgIsZero()) && ((*z).LastValid.MsgIsZero()) && (len((*z).Note) == 0) && ((*z).GenesisID == "") && ((*z).GenesisHash.MsgIsZero()) && ((*z).Group.MsgIsZero()) && ((*z).Lease == ([32]byte{})) && ((*z).RekeyTo.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// HeaderMaxSize returns a maximum valid message size for this message type
func HeaderMaxSize() (s int) {
s = 1 + 4 + basics.AddressMaxSize() + 4 + basics.MicroAlgosMaxSize() + 3 + basics.RoundMaxSize() + 3 + basics.RoundMaxSize() + 5 + msgp.BytesPrefixSize + bounds.MaxTxnNoteBytes + 4 + msgp.StringPrefixSize + bounds.MaxGenesisIDLen + 3 + crypto.DigestMaxSize() + 4 + crypto.DigestMaxSize() + 3
// Calculating size of array: z.Lease
@@ -3256,7 +3256,7 @@ func (z *HeartbeatTxnFields) MsgIsZero() bool {
return ((*z).HbAddress.MsgIsZero()) && ((*z).HbProof.MsgIsZero()) && ((*z).HbSeed.MsgIsZero()) && ((*z).HbVoteID.MsgIsZero()) && ((*z).HbKeyDilution == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// HeartbeatTxnFieldsMaxSize returns a maximum valid message size for this message type
func HeartbeatTxnFieldsMaxSize() (s int) {
s = 1 + 2 + basics.AddressMaxSize() + 4 + crypto.HeartbeatProofMaxSize() + 3 + committee.SeedMaxSize() + 4 + crypto.OneTimeSignatureVerifierMaxSize() + 3 + msgp.Uint64Size
return
@@ -3399,7 +3399,7 @@ func (z *HoldingRef) MsgIsZero() bool {
return ((*z).Address == 0) && ((*z).Asset == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// HoldingRefMaxSize returns a maximum valid message size for this message type
func HoldingRefMaxSize() (s int) {
s = 1 + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size
return
@@ -3657,7 +3657,7 @@ func (z *KeyregTxnFields) MsgIsZero() bool {
return ((*z).VotePK.MsgIsZero()) && ((*z).SelectionPK.MsgIsZero()) && ((*z).StateProofPK.MsgIsZero()) && ((*z).VoteFirst.MsgIsZero()) && ((*z).VoteLast.MsgIsZero()) && ((*z).VoteKeyDilution == 0) && ((*z).Nonparticipation == false)
}
-// MaxSize returns a maximum valid message size for this message type
+// KeyregTxnFieldsMaxSize returns a maximum valid message size for this message type
func KeyregTxnFieldsMaxSize() (s int) {
s = 1 + 8 + crypto.OneTimeSignatureVerifierMaxSize() + 7 + crypto.VRFVerifierMaxSize() + 8 + merklesignature.CommitmentMaxSize() + 8 + basics.RoundMaxSize() + 8 + basics.RoundMaxSize() + 7 + msgp.Uint64Size + 8 + msgp.BoolSize
return
@@ -3800,7 +3800,7 @@ func (z *LocalsRef) MsgIsZero() bool {
return ((*z).Address == 0) && ((*z).App == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// LocalsRefMaxSize returns a maximum valid message size for this message type
func LocalsRefMaxSize() (s int) {
s = 1 + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size
return
@@ -4104,7 +4104,7 @@ func (z *LogicSig) MsgIsZero() bool {
return (len((*z).Logic) == 0) && ((*z).Sig.MsgIsZero()) && ((*z).Msig.MsgIsZero()) && ((*z).LMsig.MsgIsZero()) && (len((*z).Args) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// LogicSigMaxSize returns a maximum valid message size for this message type
func LogicSigMaxSize() (s int) {
s = 1 + 2 + msgp.BytesPrefixSize + bounds.MaxLogicSigMaxSize + 4 + crypto.SignatureMaxSize() + 5 + crypto.MultisigSigMaxSize() + 6 + crypto.MultisigSigMaxSize() + 4
// Calculating size of slice: z.Args
@@ -4166,7 +4166,7 @@ func (z OnCompletion) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// OnCompletionMaxSize returns a maximum valid message size for this message type
func OnCompletionMaxSize() (s int) {
s = msgp.Uint64Size
return
@@ -4332,7 +4332,7 @@ func (z *PaymentTxnFields) MsgIsZero() bool {
return ((*z).Receiver.MsgIsZero()) && ((*z).Amount.MsgIsZero()) && ((*z).CloseRemainderTo.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// PaymentTxnFieldsMaxSize returns a maximum valid message size for this message type
func PaymentTxnFieldsMaxSize() (s int) {
s = 1 + 4 + basics.AddressMaxSize() + 4 + basics.MicroAlgosMaxSize() + 6 + basics.AddressMaxSize()
return
@@ -4419,7 +4419,7 @@ func (z Payset) MsgIsZero() bool {
return len(z) == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// PaysetMaxSize returns a maximum valid message size for this message type
func PaysetMaxSize() (s int) {
// Calculating size of slice: z
s += msgp.ArrayHeaderSize + ((100000) * (SignedTxnInBlockMaxSize()))
@@ -5145,7 +5145,7 @@ func (z *ResourceRef) MsgIsZero() bool {
return ((*z).Address.MsgIsZero()) && ((*z).Asset.MsgIsZero()) && ((*z).App.MsgIsZero()) && (((*z).Holding.Address == 0) && ((*z).Holding.Asset == 0)) && (((*z).Locals.Address == 0) && ((*z).Locals.App == 0)) && (((*z).Box.Index == 0) && (len((*z).Box.Name) == 0))
}
-// MaxSize returns a maximum valid message size for this message type
+// ResourceRefMaxSize returns a maximum valid message size for this message type
func ResourceRefMaxSize() (s int) {
s = 1 + 2 + basics.AddressMaxSize() + 2 + basics.AssetIndexMaxSize() + 2 + basics.AppIndexMaxSize() + 2 + 1 + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + 1 + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + 1 + 2 + msgp.Uint64Size + 2 + msgp.BytesPrefixSize + bounds.MaxBytesKeyValueLen
return
@@ -5357,7 +5357,7 @@ func (z *SignedTxn) MsgIsZero() bool {
return ((*z).Sig.MsgIsZero()) && ((*z).Msig.MsgIsZero()) && ((*z).Lsig.MsgIsZero()) && ((*z).Txn.MsgIsZero()) && ((*z).AuthAddr.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// SignedTxnMaxSize returns a maximum valid message size for this message type
func SignedTxnMaxSize() (s int) {
s = 1 + 4 + crypto.SignatureMaxSize() + 5 + crypto.MultisigSigMaxSize() + 5 + LogicSigMaxSize() + 4 + TransactionMaxSize() + 5 + basics.AddressMaxSize()
return
@@ -5799,7 +5799,7 @@ func (z *SignedTxnInBlock) MsgIsZero() bool {
return ((*z).SignedTxnWithAD.SignedTxn.Sig.MsgIsZero()) && ((*z).SignedTxnWithAD.SignedTxn.Msig.MsgIsZero()) && ((*z).SignedTxnWithAD.SignedTxn.Lsig.MsgIsZero()) && ((*z).SignedTxnWithAD.SignedTxn.Txn.MsgIsZero()) && ((*z).SignedTxnWithAD.SignedTxn.AuthAddr.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.ClosingAmount.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.AssetClosingAmount == 0) && ((*z).SignedTxnWithAD.ApplyData.SenderRewards.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.ReceiverRewards.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.CloseRewards.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.EvalDelta.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.ConfigAsset.MsgIsZero()) && ((*z).SignedTxnWithAD.ApplyData.ApplicationID.MsgIsZero()) && ((*z).HasGenesisID == false) && ((*z).HasGenesisHash == false)
}
-// MaxSize returns a maximum valid message size for this message type
+// SignedTxnInBlockMaxSize returns a maximum valid message size for this message type
func SignedTxnInBlockMaxSize() (s int) {
s = 1 + 4 + crypto.SignatureMaxSize() + 5 + crypto.MultisigSigMaxSize() + 5 + LogicSigMaxSize() + 4 + TransactionMaxSize() + 5 + basics.AddressMaxSize() + 3 + basics.MicroAlgosMaxSize() + 4 + msgp.Uint64Size + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + EvalDeltaMaxSize() + 5 + basics.AssetIndexMaxSize() + 5 + basics.AppIndexMaxSize() + 4 + msgp.BoolSize + 4 + msgp.BoolSize
return
@@ -6195,7 +6195,7 @@ func (z *SignedTxnWithAD) MsgIsZero() bool {
return ((*z).SignedTxn.Sig.MsgIsZero()) && ((*z).SignedTxn.Msig.MsgIsZero()) && ((*z).SignedTxn.Lsig.MsgIsZero()) && ((*z).SignedTxn.Txn.MsgIsZero()) && ((*z).SignedTxn.AuthAddr.MsgIsZero()) && ((*z).ApplyData.ClosingAmount.MsgIsZero()) && ((*z).ApplyData.AssetClosingAmount == 0) && ((*z).ApplyData.SenderRewards.MsgIsZero()) && ((*z).ApplyData.ReceiverRewards.MsgIsZero()) && ((*z).ApplyData.CloseRewards.MsgIsZero()) && ((*z).ApplyData.EvalDelta.MsgIsZero()) && ((*z).ApplyData.ConfigAsset.MsgIsZero()) && ((*z).ApplyData.ApplicationID.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// SignedTxnWithADMaxSize returns a maximum valid message size for this message type
func SignedTxnWithADMaxSize() (s int) {
s = 1 + 4 + crypto.SignatureMaxSize() + 5 + crypto.MultisigSigMaxSize() + 5 + LogicSigMaxSize() + 4 + TransactionMaxSize() + 5 + basics.AddressMaxSize() + 3 + basics.MicroAlgosMaxSize() + 4 + msgp.Uint64Size + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + basics.MicroAlgosMaxSize() + 3 + EvalDeltaMaxSize() + 5 + basics.AssetIndexMaxSize() + 5 + basics.AppIndexMaxSize()
return
@@ -6361,7 +6361,7 @@ func (z *StateProofTxnFields) MsgIsZero() bool {
return ((*z).StateProofType.MsgIsZero()) && ((*z).StateProof.MsgIsZero()) && ((*z).Message.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// StateProofTxnFieldsMaxSize returns a maximum valid message size for this message type
func StateProofTxnFieldsMaxSize() (s int) {
s = 1 + 7 + protocol.StateProofTypeMaxSize() + 3 + stateproof.StateProofMaxSize() + 6 + stateproofmsg.MessageMaxSize()
return
@@ -8212,7 +8212,7 @@ func (z *Transaction) MsgIsZero() bool {
return ((*z).Type.MsgIsZero()) && ((*z).Header.Sender.MsgIsZero()) && ((*z).Header.Fee.MsgIsZero()) && ((*z).Header.FirstValid.MsgIsZero()) && ((*z).Header.LastValid.MsgIsZero()) && (len((*z).Header.Note) == 0) && ((*z).Header.GenesisID == "") && ((*z).Header.GenesisHash.MsgIsZero()) && ((*z).Header.Group.MsgIsZero()) && ((*z).Header.Lease == ([32]byte{})) && ((*z).Header.RekeyTo.MsgIsZero()) && ((*z).KeyregTxnFields.VotePK.MsgIsZero()) && ((*z).KeyregTxnFields.SelectionPK.MsgIsZero()) && ((*z).KeyregTxnFields.StateProofPK.MsgIsZero()) && ((*z).KeyregTxnFields.VoteFirst.MsgIsZero()) && ((*z).KeyregTxnFields.VoteLast.MsgIsZero()) && ((*z).KeyregTxnFields.VoteKeyDilution == 0) && ((*z).KeyregTxnFields.Nonparticipation == false) && ((*z).PaymentTxnFields.Receiver.MsgIsZero()) && ((*z).PaymentTxnFields.Amount.MsgIsZero()) && ((*z).PaymentTxnFields.CloseRemainderTo.MsgIsZero()) && ((*z).AssetConfigTxnFields.ConfigAsset.MsgIsZero()) && ((*z).AssetConfigTxnFields.AssetParams.MsgIsZero()) && ((*z).AssetTransferTxnFields.XferAsset.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetAmount == 0) && ((*z).AssetTransferTxnFields.AssetSender.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetReceiver.MsgIsZero()) && ((*z).AssetTransferTxnFields.AssetCloseTo.MsgIsZero()) && ((*z).AssetFreezeTxnFields.FreezeAccount.MsgIsZero()) && ((*z).AssetFreezeTxnFields.FreezeAsset.MsgIsZero()) && ((*z).AssetFreezeTxnFields.AssetFrozen == false) && ((*z).ApplicationCallTxnFields.ApplicationID.MsgIsZero()) && ((*z).ApplicationCallTxnFields.OnCompletion == 0) && (len((*z).ApplicationCallTxnFields.ApplicationArgs) == 0) && (len((*z).ApplicationCallTxnFields.Accounts) == 0) && (len((*z).ApplicationCallTxnFields.ForeignAssets) == 0) && (len((*z).ApplicationCallTxnFields.ForeignApps) == 0) && (len((*z).ApplicationCallTxnFields.Access) == 0) && (len((*z).ApplicationCallTxnFields.Boxes) == 0) && ((*z).ApplicationCallTxnFields.LocalStateSchema.MsgIsZero()) && ((*z).ApplicationCallTxnFields.GlobalStateSchema.MsgIsZero()) && (len((*z).ApplicationCallTxnFields.ApprovalProgram) == 0) && (len((*z).ApplicationCallTxnFields.ClearStateProgram) == 0) && ((*z).ApplicationCallTxnFields.ExtraProgramPages == 0) && ((*z).ApplicationCallTxnFields.RejectVersion == 0) && ((*z).StateProofTxnFields.StateProofType.MsgIsZero()) && ((*z).StateProofTxnFields.StateProof.MsgIsZero()) && ((*z).StateProofTxnFields.Message.MsgIsZero()) && ((*z).HeartbeatTxnFields == nil)
}
-// MaxSize returns a maximum valid message size for this message type
+// TransactionMaxSize returns a maximum valid message size for this message type
func TransactionMaxSize() (s int) {
s = 3 + 5 + protocol.TxTypeMaxSize() + 4 + basics.AddressMaxSize() + 4 + basics.MicroAlgosMaxSize() + 3 + basics.RoundMaxSize() + 3 + basics.RoundMaxSize() + 5 + msgp.BytesPrefixSize + bounds.MaxTxnNoteBytes + 4 + msgp.StringPrefixSize + bounds.MaxGenesisIDLen + 3 + crypto.DigestMaxSize() + 4 + crypto.DigestMaxSize() + 3
// Calculating size of array: z.Header.Lease
@@ -8405,7 +8405,7 @@ func (z *TxGroup) MsgIsZero() bool {
return (len((*z).TxGroupHashes) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// TxGroupMaxSize returns a maximum valid message size for this message type
func TxGroupMaxSize() (s int) {
s = 1 + 7
// Calculating size of slice: z.TxGroupHashes
@@ -8444,7 +8444,7 @@ func (z *Txid) MsgIsZero() bool {
return ((*(crypto.Digest))(z)).MsgIsZero()
}
-// MaxSize returns a maximum valid message size for this message type
+// crypto.DigestMaxSize returns a maximum valid message size for this message type
func TxidMaxSize() int {
return crypto.DigestMaxSize()
}
diff --git a/data/transactions/msgp_gen_test.go b/data/transactions/msgp_gen_test.go
index 8cc316425c..d16eff9a0c 100644
--- a/data/transactions/msgp_gen_test.go
+++ b/data/transactions/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package transactions
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package transactions
+
import (
"testing"
diff --git a/data/transactions/payment.go b/data/transactions/payment.go
index 59b54d8075..99191270d6 100644
--- a/data/transactions/payment.go
+++ b/data/transactions/payment.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/payment_test.go b/data/transactions/payment_test.go
index 50b8491079..e94a7778a4 100644
--- a/data/transactions/payment_test.go
+++ b/data/transactions/payment_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/payset.go b/data/transactions/payset.go
index 8519f361f9..29f67e395e 100644
--- a/data/transactions/payset.go
+++ b/data/transactions/payset.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/payset_test.go b/data/transactions/payset_test.go
index 7a86439a7f..33f99dafbf 100644
--- a/data/transactions/payset_test.go
+++ b/data/transactions/payset_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -27,9 +27,7 @@ func generatePayset(txnCount, acctCount int) Payset {
stxnb := make([]SignedTxnInBlock, txnCount)
for i, stxn := range generateSignedTxns(txnCount, acctCount) {
stxnb[i] = SignedTxnInBlock{
- SignedTxnWithAD: SignedTxnWithAD{
- SignedTxn: stxn,
- },
+ SignedTxnWithAD: stxn.WithAD(),
}
}
return Payset(stxnb)
diff --git a/data/transactions/perf_test.go b/data/transactions/perf_test.go
index d2652f56e9..8e8b42cdd2 100644
--- a/data/transactions/perf_test.go
+++ b/data/transactions/perf_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/signedtxn.go b/data/transactions/signedtxn.go
index f43cc18acd..bee69d7569 100644
--- a/data/transactions/signedtxn.go
+++ b/data/transactions/signedtxn.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -62,6 +62,18 @@ func (s SignedTxn) ID() Txid {
return s.Txn.ID()
}
+// WithAD returns a SignedTxnWithAD with an (optional) ApplyData.
+func (s SignedTxn) WithAD(ad ...ApplyData) SignedTxnWithAD {
+ switch len(ad) {
+ case 0:
+ return SignedTxnWithAD{SignedTxn: s}
+ case 1:
+ return SignedTxnWithAD{SignedTxn: s, ApplyData: ad[0]}
+ default:
+ panic("WithAD called incorrectly")
+ }
+}
+
// ID on SignedTxnInBlock should never be called, because the ID depends
// on the block from which this transaction will be decoded. By having
// a different return value from SignedTxn.ID(), we will catch errors at
diff --git a/data/transactions/signedtxn_test.go b/data/transactions/signedtxn_test.go
index 6001bed087..f3e9f6ae50 100644
--- a/data/transactions/signedtxn_test.go
+++ b/data/transactions/signedtxn_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/sort.go b/data/transactions/sort.go
index 8686149ec2..401a9ebb64 100644
--- a/data/transactions/sort.go
+++ b/data/transactions/sort.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/stateproof.go b/data/transactions/stateproof.go
index cdc8bc916b..5e3aba6851 100644
--- a/data/transactions/stateproof.go
+++ b/data/transactions/stateproof.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/stateproof_test.go b/data/transactions/stateproof_test.go
index 9090c90352..6ef95e8d6d 100644
--- a/data/transactions/stateproof_test.go
+++ b/data/transactions/stateproof_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/teal.go b/data/transactions/teal.go
index 6f886d8680..3f5094db7d 100644
--- a/data/transactions/teal.go
+++ b/data/transactions/teal.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/teal_test.go b/data/transactions/teal_test.go
index 56edec8d13..954fe501ba 100644
--- a/data/transactions/teal_test.go
+++ b/data/transactions/teal_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/testhelpers.go b/data/transactions/testhelpers.go
index 17488d14a8..660de2800f 100644
--- a/data/transactions/testhelpers.go
+++ b/data/transactions/testhelpers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/transaction.go b/data/transactions/transaction.go
index 9ced317c04..1c0ed37bdf 100644
--- a/data/transactions/transaction.go
+++ b/data/transactions/transaction.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/transaction_test.go b/data/transactions/transaction_test.go
index 30e1bdc5f5..c3201e3c92 100644
--- a/data/transactions/transaction_test.go
+++ b/data/transactions/transaction_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -124,8 +124,7 @@ func TestApplyDataEquality(t *testing.T) {
t.Parallel()
var empty ApplyData
- for _, nz := range basics_testing.NearZeros(t, ApplyData{}) {
- ad := nz.(ApplyData)
+ for _, ad := range basics_testing.NearZeros(t, ApplyData{}) {
assert.False(t, ad.Equal(empty), "Equal() seems to be disregarding something %+v", ad)
}
@@ -136,8 +135,7 @@ func TestEvalDataEquality(t *testing.T) {
t.Parallel()
var empty EvalDelta
- for _, nz := range basics_testing.NearZeros(t, EvalDelta{}) {
- ed := nz.(EvalDelta)
+ for _, ed := range basics_testing.NearZeros(t, EvalDelta{}) {
assert.False(t, ed.Equal(empty), "Equal() seems to be disregarding something %+v", ed)
}
@@ -148,8 +146,7 @@ func TestLogicSigEquality(t *testing.T) {
t.Parallel()
var empty LogicSig
- for _, nz := range basics_testing.NearZeros(t, LogicSig{}) {
- ls := nz.(LogicSig)
+ for _, ls := range basics_testing.NearZeros(t, LogicSig{}) {
assert.False(t, ls.Equal(&empty), "Equal() seems to be disregarding something %+v", ls)
}
diff --git a/data/transactions/verify/artifact_test.go b/data/transactions/verify/artifact_test.go
index 7f5f0d9645..748d7dccab 100644
--- a/data/transactions/verify/artifact_test.go
+++ b/data/transactions/verify/artifact_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/verify/txn.go b/data/transactions/verify/txn.go
index ca9ca10c90..62d5cbeeab 100644
--- a/data/transactions/verify/txn.go
+++ b/data/transactions/verify/txn.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -84,6 +84,7 @@ var errTxGroupInvalidFee = errors.New("txgroup fee requirement overflow")
var errTxnSigHasNoSig = errors.New("signedtxn has no sig")
var errTxnSigNotWellFormed = errors.New("signedtxn should only have one of Sig or Msig or LogicSig")
var errRekeyingNotSupported = errors.New("nonempty AuthAddr but rekeying is not supported")
+var errAuthAddrEqualsSender = errors.New("AuthAddr must be different from Sender")
var errUnknownSignature = errors.New("has one mystery sig. WAT?")
// TxGroupErrorReason is reason code for ErrTxGroupError
@@ -168,6 +169,10 @@ func txnBatchPrep(gi int, groupCtx *GroupContext, verifier crypto.BatchVerifier)
return &TxGroupError{err: errRekeyingNotSupported, GroupIndex: gi, Reason: TxGroupErrorReasonGeneric}
}
+ if groupCtx.consensusParams.EnforceAuthAddrSenderDiff && !s.AuthAddr.IsZero() && s.AuthAddr == s.Txn.Sender {
+ return &TxGroupError{err: errAuthAddrEqualsSender, GroupIndex: gi, Reason: TxGroupErrorReasonGeneric}
+ }
+
if err := s.Txn.WellFormed(groupCtx.specAddrs, groupCtx.consensusParams); err != nil {
return &TxGroupError{err: err, GroupIndex: gi, Reason: TxGroupErrorReasonNotWellFormed}
}
diff --git a/data/transactions/verify/txnBatch.go b/data/transactions/verify/txnBatch.go
index 6f1fff7ce5..3fe96cde4d 100644
--- a/data/transactions/verify/txnBatch.go
+++ b/data/transactions/verify/txnBatch.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/verify/txnBatch_test.go b/data/transactions/verify/txnBatch_test.go
index 036b1fc0b8..d4ab5dc788 100644
--- a/data/transactions/verify/txnBatch_test.go
+++ b/data/transactions/verify/txnBatch_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/verify/txn_test.go b/data/transactions/verify/txn_test.go
index ffcc0f4c77..d34575ccd6 100644
--- a/data/transactions/verify/txn_test.go
+++ b/data/transactions/verify/txn_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -1531,3 +1531,70 @@ func TestLogicSigMsigBothFlags(t *testing.T) {
err = verifyLogicSig()
require.ErrorContains(t, err, "LogicSig should only have one of Sig, Msig, or LMsig but has more than one")
}
+
+func TestAuthAddrSenderDiff(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ t.Run("v41-disabled", func(t *testing.T) { testAuthAddrSenderDiff(t, protocol.ConsensusV41, false) })
+ t.Run("future-enabled", func(t *testing.T) { testAuthAddrSenderDiff(t, protocol.ConsensusFuture, true) })
+}
+
+func testAuthAddrSenderDiff(t *testing.T, consensusVer protocol.ConsensusVersion, enforceEnabled bool) {
+ secrets, addrs, _ := generateAccounts(3)
+ sender := addrs[0]
+ otherAddr := addrs[1]
+
+ blockHeader := createDummyBlockHeader(consensusVer)
+ proto := config.Consensus[consensusVer]
+
+ makeTxn := func() transactions.Transaction {
+ return transactions.Transaction{
+ Type: protocol.PaymentTx,
+ Header: transactions.Header{
+ Sender: sender,
+ Fee: basics.MicroAlgos{Raw: proto.MinTxnFee},
+ FirstValid: 1,
+ LastValid: 100,
+ GenesisHash: blockHeader.GenesisHash,
+ },
+ PaymentTxnFields: transactions.PaymentTxnFields{
+ Receiver: addrs[2],
+ Amount: basics.MicroAlgos{Raw: 1000},
+ },
+ }
+ }
+
+ // Test 1: AuthAddr == Sender
+ tx1 := makeTxn()
+ stxn := tx1.Sign(secrets[0])
+ stxn.AuthAddr = sender
+ groupCtx, err := PrepareGroupContext([]transactions.SignedTxn{stxn}, &blockHeader, nil, nil)
+ require.NoError(t, err)
+ err = verifyTxn(0, groupCtx)
+ if enforceEnabled {
+ require.ErrorContains(t, err, "AuthAddr must be different from Sender",
+ "AuthAddr == Sender should be rejected when enforcement is enabled")
+ } else {
+ require.NoError(t, err,
+ "AuthAddr == Sender should be allowed when enforcement is disabled")
+ }
+
+ // Test 2: Empty AuthAddr should always be allowed
+ tx2 := makeTxn()
+ stxn = tx2.Sign(secrets[0])
+ stxn.AuthAddr = basics.Address{}
+ groupCtx, err = PrepareGroupContext([]transactions.SignedTxn{stxn}, &blockHeader, nil, nil)
+ require.NoError(t, err)
+ err = verifyTxn(0, groupCtx)
+ require.NoError(t, err, "empty AuthAddr should always be allowed")
+
+ // Test 3: AuthAddr != Sender should pass the check (legitimate rekeying case)
+ // Sign with otherAddr's key to pass signature verification
+ tx3 := makeTxn()
+ stxn = tx3.Sign(secrets[1]) // Sign with secrets[1] which corresponds to otherAddr
+ stxn.AuthAddr = otherAddr
+ groupCtx, err = PrepareGroupContext([]transactions.SignedTxn{stxn}, &blockHeader, nil, nil)
+ require.NoError(t, err)
+ err = verifyTxn(0, groupCtx)
+ require.NoError(t, err, "AuthAddr != Sender should pass verification (legitimate rekeying)")
+}
diff --git a/data/transactions/verify/verifiedTxnCache.go b/data/transactions/verify/verifiedTxnCache.go
index fd915690d1..525ebf0fc1 100644
--- a/data/transactions/verify/verifiedTxnCache.go
+++ b/data/transactions/verify/verifiedTxnCache.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/transactions/verify/verifiedTxnCache_test.go b/data/transactions/verify/verifiedTxnCache_test.go
index 6fde7135c1..d87a358432 100644
--- a/data/transactions/verify/verifiedTxnCache_test.go
+++ b/data/transactions/verify/verifiedTxnCache_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/txDupCache.go b/data/txDupCache.go
index 130fe3c5b5..92b7087721 100644
--- a/data/txDupCache.go
+++ b/data/txDupCache.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/txDupCache_test.go b/data/txDupCache_test.go
index aee303fc54..79899b313d 100644
--- a/data/txDupCache_test.go
+++ b/data/txDupCache_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/txHandler.go b/data/txHandler.go
index beb23f68b2..db3f8e03a5 100644
--- a/data/txHandler.go
+++ b/data/txHandler.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -32,7 +32,6 @@ import (
"github.com/algorand/go-algorand/data/pools"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/data/transactions/verify"
- "github.com/algorand/go-algorand/ledger/ledgercore"
"github.com/algorand/go-algorand/logging"
"github.com/algorand/go-algorand/network"
"github.com/algorand/go-algorand/protocol"
@@ -74,33 +73,18 @@ var ErrInvalidLedger = errors.New("MakeTxHandler: ledger is nil on initializatio
var transactionMessageTxPoolRememberCounter = metrics.NewTagCounter(
"algod_transaction_messages_txpool_remember_err_{TAG}", "Number of transaction messages not remembered by txpool b/c of {TAG}",
- txPoolRememberTagCap, txPoolRememberPendingEval, txPoolRememberTagNoSpace, txPoolRememberTagFee, txPoolRememberTagTxnDead, txPoolRememberTagTxnEarly, txPoolRememberTagTooLarge, txPoolRememberTagGroupID,
- txPoolRememberTagTxID, txPoolRememberTagLease, txPoolRememberTagTxIDEval, txPoolRememberTagLeaseEval, txPoolRememberTagEvalGeneric,
+ pools.TxPoolErrTags...,
)
var transactionMessageTxPoolCheckCounter = metrics.NewTagCounter(
"algod_transaction_messages_txpool_check_err_{TAG}", "Number of transaction messages that didn't pass check by txpool b/c of {TAG}",
- txPoolRememberTagTxnNotWellFormed, txPoolRememberTagTxnDead, txPoolRememberTagTxnEarly, txPoolRememberTagTooLarge, txPoolRememberTagGroupID,
- txPoolRememberTagTxID, txPoolRememberTagLease, txPoolRememberTagTxIDEval, txPoolRememberTagLeaseEval, txPoolRememberTagEvalGeneric,
+ pools.TxPoolErrTags...,
)
-const (
- txPoolRememberTagCap = "cap"
- txPoolRememberPendingEval = "pending_eval"
- txPoolRememberTagNoSpace = "no_space"
- txPoolRememberTagFee = "fee"
- txPoolRememberTagTxnDead = "txn_dead"
- txPoolRememberTagTxnEarly = "txn_early"
- txPoolRememberTagTooLarge = "too_large"
- txPoolRememberTagGroupID = "groupid"
- txPoolRememberTagTxID = "txid"
- txPoolRememberTagLease = "lease"
- txPoolRememberTagTxIDEval = "txid_eval"
- txPoolRememberTagLeaseEval = "lease_eval"
- txPoolRememberTagEvalGeneric = "eval"
-
- txPoolRememberTagTxnNotWellFormed = "not_well"
-)
+type transactionPool interface {
+ Test(stxns []transactions.SignedTxn) error
+ Remember(stxns []transactions.SignedTxn) error
+}
// The txBacklogMsg structure used to track a single incoming transaction from the gossip network,
type txBacklogMsg struct {
@@ -115,11 +99,11 @@ type txBacklogMsg struct {
// TxHandler handles transaction messages
type TxHandler struct {
- txPool *pools.TransactionPool
+ txPool transactionPool
ledger *Ledger
txVerificationPool execpool.BacklogPool
backlogQueue chan *txBacklogMsg
- backlogCongestionThreshold float64
+ backlogCongestionThreshold int
postVerificationQueue chan *verify.VerificationResult
backlogWg sync.WaitGroup
net network.GossipNode
@@ -142,7 +126,7 @@ type TxHandler struct {
// TxHandlerOpts is TxHandler configuration options
type TxHandlerOpts struct {
- TxPool *pools.TransactionPool
+ TxPool transactionPool
ExecutionPool execpool.BacklogPool
Ledger *Ledger
Net network.GossipNode
@@ -193,10 +177,13 @@ func MakeTxHandler(opts TxHandlerOpts) (*TxHandler, error) {
if opts.Config.TxBacklogRateLimitingCongestionPct > 100 || opts.Config.TxBacklogRateLimitingCongestionPct < 0 {
return nil, fmt.Errorf("invalid value for TxBacklogRateLimitingCongestionPct: %d", opts.Config.TxBacklogRateLimitingCongestionPct)
}
+ if opts.Config.TxBacklogAppRateLimitingCongestionPct > 100 || opts.Config.TxBacklogAppRateLimitingCongestionPct < 0 {
+ return nil, fmt.Errorf("invalid value for TxBacklogAppRateLimitingCongestionPct: %d", opts.Config.TxBacklogAppRateLimitingCongestionPct)
+ }
if opts.Config.EnableTxBacklogAppRateLimiting && opts.Config.TxBacklogAppTxRateLimiterMaxSize == 0 {
return nil, fmt.Errorf("invalid value for TxBacklogAppTxRateLimiterMaxSize: %d. App rate limiter enabled with zero size", opts.Config.TxBacklogAppTxRateLimiterMaxSize)
}
- handler.backlogCongestionThreshold = float64(opts.Config.TxBacklogRateLimitingCongestionPct) / 100
+ handler.backlogCongestionThreshold = int(float64(txBacklogSize*opts.Config.TxBacklogRateLimitingCongestionPct) / 100)
if opts.Config.EnableTxBacklogRateLimiting {
handler.erl = util.NewElasticRateLimiter(
txBacklogSize,
@@ -215,8 +202,8 @@ func MakeTxHandler(opts TxHandlerOpts) (*TxHandler, error) {
uint64(opts.Config.TxBacklogAppTxPerSecondRate),
time.Duration(opts.Config.TxBacklogServiceRateWindowSeconds)*time.Second,
)
- // set appLimiter triggering threshold at 50% of the base backlog size
- handler.appLimiterBacklogThreshold = int(float64(opts.Config.TxBacklogSize) * float64(opts.Config.TxBacklogRateLimitingCongestionPct) / 100)
+ // set appLimiter triggering threshold at TxBacklogAppRateLimitingCongestionPct (current default is 10) percent of the base backlog size
+ handler.appLimiterBacklogThreshold = int(float64(opts.Config.TxBacklogSize) * float64(opts.Config.TxBacklogAppRateLimitingCongestionPct) / 100)
handler.appLimiterCountERLDrops = opts.Config.TxBacklogAppRateLimitingCountERLDrops
}
}
@@ -417,107 +404,6 @@ func (handler *TxHandler) postProcessReportErrors(err error) {
}
}
-func (handler *TxHandler) checkReportErrors(err error) {
- switch err := err.(type) {
- case *ledgercore.TxnNotWellFormedError:
- transactionMessageTxPoolCheckCounter.Add(txPoolRememberTagTxnNotWellFormed, 1)
- return
- case *bookkeeping.TxnDeadError:
- if err.Early {
- transactionMessageTxPoolCheckCounter.Add(txPoolRememberTagTxnEarly, 1)
- } else {
- transactionMessageTxPoolCheckCounter.Add(txPoolRememberTagTxnDead, 1)
- }
- return
- case *ledgercore.TransactionInLedgerError:
- if err.InBlockEvaluator {
- transactionMessageTxPoolCheckCounter.Add(txPoolRememberTagTxIDEval, 1)
- } else {
- transactionMessageTxPoolCheckCounter.Add(txPoolRememberTagTxID, 1)
- }
- return
- case *ledgercore.LeaseInLedgerError:
- if err.InBlockEvaluator {
- transactionMessageTxPoolCheckCounter.Add(txPoolRememberTagLeaseEval, 1)
- } else {
- transactionMessageTxPoolCheckCounter.Add(txPoolRememberTagLease, 1)
- }
- return
- case *ledgercore.TxGroupMalformedError:
- switch err.Reason {
- case ledgercore.TxGroupMalformedErrorReasonExceedMaxSize:
- transactionMessageTxPoolCheckCounter.Add(txPoolRememberTagTooLarge, 1)
- default:
- transactionMessageTxPoolCheckCounter.Add(txPoolRememberTagGroupID, 1)
- }
- return
- }
-
- transactionMessageTxPoolCheckCounter.Add(txPoolRememberTagEvalGeneric, 1)
-}
-
-func (handler *TxHandler) rememberReportErrors(err error) {
- if errors.Is(err, pools.ErrPendingQueueReachedMaxCap) {
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberTagCap, 1)
- return
- }
-
- if errors.Is(err, pools.ErrNoPendingBlockEvaluator) {
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberPendingEval, 1)
- return
- }
-
- if errors.Is(err, ledgercore.ErrNoSpace) {
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberTagNoSpace, 1)
- return
- }
-
- // it is possible to call errors.As but it requires additional allocations
- // instead, unwrap and type assert.
- underlyingErr := errors.Unwrap(err)
- if underlyingErr == nil {
- // something went wrong
- return
- }
-
- switch err := underlyingErr.(type) {
- case *pools.ErrTxPoolFeeError:
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberTagFee, 1)
- return
- case *bookkeeping.TxnDeadError:
- if err.Early {
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberTagTxnEarly, 1)
- } else {
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberTagTxnDead, 1)
- }
- return
- case *ledgercore.TransactionInLedgerError:
- if err.InBlockEvaluator {
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberTagTxIDEval, 1)
- } else {
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberTagTxID, 1)
- }
- return
- case *ledgercore.LeaseInLedgerError:
- if err.InBlockEvaluator {
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberTagLeaseEval, 1)
- } else {
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberTagLease, 1)
- }
- return
- case *ledgercore.TxGroupMalformedError:
- switch err.Reason {
- case ledgercore.TxGroupMalformedErrorReasonExceedMaxSize:
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberTagTooLarge, 1)
- default:
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberTagGroupID, 1)
- }
- return
- }
-
- transactionMessageTxPoolRememberCounter.Add(txPoolRememberTagEvalGeneric, 1)
-}
-
func (handler *TxHandler) postProcessCheckedTxn(wi *txBacklogMsg) {
if wi.verificationErr != nil {
// disconnect from peer.
@@ -541,7 +427,17 @@ func (handler *TxHandler) postProcessCheckedTxn(wi *txBacklogMsg) {
// save the transaction, if it has high enough fee and not already in the cache
err := handler.txPool.Remember(verifiedTxGroup)
if err != nil {
- handler.rememberReportErrors(err)
+ if handler.appLimiter != nil && !wi.rawmsg.Outgoing && wi.rawmsg.Sender != nil {
+ var tde *bookkeeping.TxnDeadError
+ // explicitly avoid penalizing for TxDeadError since another node can be out of sync
+ if !errors.As(err, &tde) {
+ handler.appLimiter.penalizeEvalError(
+ wi.unverifiedTxGroup, wi.rawmsg.Sender.RoutingAddr(),
+ )
+ }
+ }
+
+ transactionMessageTxPoolRememberCounter.Add(pools.ClassifyTxPoolError(err), 1)
logging.Base().Debugf("could not remember tx: %v", err)
// if in synchronous mode, signal the completion of the operation
if wi.syncCh != nil {
@@ -742,7 +638,7 @@ func (eic *erlIPClient) connClosed(ec util.ErlClient) {
// - the capacity guard returned by the elastic rate limiter
// - a boolean indicating if the sender is rate limited
func (handler *TxHandler) incomingMsgErlCheck(sender util.ErlClient) (*util.ErlCapacityGuard, bool) {
- congestedERL := float64(cap(handler.backlogQueue))*handler.backlogCongestionThreshold < float64(len(handler.backlogQueue))
+ congestedERL := handler.backlogCongestionThreshold < len(handler.backlogQueue)
// consume a capacity unit
// if the elastic rate limiter cannot vend a capacity, the error it returns
// is sufficient to indicate that we should enable Congestion Control, because
@@ -963,7 +859,7 @@ func (handler *TxHandler) validateIncomingTxMessage(rawmsg network.IncomingMessa
action = network.Ignore
}
- if hybridNet, ok := handler.net.(HybridRelayer); ok {
+ if hybridNet, ok := handler.net.(HybridRelayer); ok && action == network.Accept {
_ = hybridNet.BridgeP2PToWS(handler.ctx, protocol.TxnTag, reencoded, false, wi.rawmsg.Sender)
}
@@ -1008,7 +904,7 @@ func (handler *TxHandler) checkAlreadyCommitted(tx *txBacklogMsg) (processingDon
// do a quick test to check that this transaction could potentially be committed, to reject dup pending transactions
err := handler.txPool.Test(tx.unverifiedTxGroup)
if err != nil {
- handler.checkReportErrors(err)
+ transactionMessageTxPoolCheckCounter.Add(pools.ClassifyTxPoolError(err), 1)
logging.Base().Debugf("txPool rejected transaction: %v", err)
return true
}
diff --git a/data/txHandler_test.go b/data/txHandler_test.go
index e24d5088ae..439143d1a4 100644
--- a/data/txHandler_test.go
+++ b/data/txHandler_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -60,14 +60,15 @@ import (
// txHandler uses config values to determine backlog size. Tests should use a static value
var txBacklogSize = config.GetDefaultLocal().TxBacklogSize
-// mock sender is used to implement OnClose, since TXHandlers expect to use Senders and ERL Clients
-type mockSender struct{}
+// mockSender is used to implement OnClose, since TXHandlers expect to use Senders and ERL Clients
+type mockSender struct {
+ addr [8]byte
+}
func (m mockSender) OnClose(func()) {}
func (m mockSender) GetNetwork() network.GossipNode { panic("not implemented") }
-func (m mockSender) IPAddr() []byte { return nil }
-func (m mockSender) RoutingAddr() []byte { return nil }
+func (m mockSender) RoutingAddr() []byte { return m.addr[:] }
// txHandlerConfig is a subset of tx handler related options from config.Local
type txHandlerConfig struct {
@@ -120,7 +121,7 @@ func BenchmarkTxHandlerProcessing(b *testing.B) {
cfg.TxPoolSize = 75000
cfg.EnableProcessBlockStats = false
- txHandler, err := makeTestTxHandler(l, cfg)
+ txHandler, _, err := makeTestTxHandler(l, cfg)
require.NoError(b, err)
defer txHandler.txVerificationPool.Shutdown()
defer close(txHandler.streamVerifierDropped)
@@ -822,13 +823,14 @@ func makeTestTxHandlerOrphanedWithContext(ctx context.Context, backlogSize int,
return handler
}
-func makeTestTxHandler(dl *Ledger, cfg config.Local) (*TxHandler, error) {
+func makeTestTxHandler(dl *Ledger, cfg config.Local) (*TxHandler, *pools.TransactionPool, error) {
tp := pools.MakeTransactionPool(dl.Ledger, cfg, logging.Base(), nil)
backlogPool := execpool.MakeBacklog(nil, 0, execpool.LowPriority, nil)
opts := TxHandlerOpts{
tp, backlogPool, dl, &mocks.MockNetwork{}, cfg,
}
- return MakeTxHandler(opts)
+ handler, err := MakeTxHandler(opts)
+ return handler, tp, err
}
func TestTxHandlerProcessIncomingCache(t *testing.T) {
@@ -944,7 +946,7 @@ func TestTxHandlerProcessIncomingCacheRotation(t *testing.T) {
// double enqueue a single txn message, ensure it discarded
ctx := t.Context()
- handler := makeTestTxHandlerOrphanedWithContext(ctx, txBacklogSize, txBacklogSize, txHandlerConfig{true, true}, 10*time.Millisecond)
+ handler := makeTestTxHandlerOrphanedWithContext(ctx, txBacklogSize, txBacklogSize, txHandlerConfig{true, true}, 0)
var action network.OutgoingMessage
var msg *txBacklogMsg
@@ -1055,7 +1057,7 @@ func TestTxHandlerProcessIncomingCacheTxPoolDrop(t *testing.T) {
defer ledger.Close()
l := ledger
- handler, err := makeTestTxHandler(l, cfg)
+ handler, _, err := makeTestTxHandler(l, cfg)
require.NoError(t, err)
defer handler.txVerificationPool.Shutdown()
defer close(handler.streamVerifierDropped)
@@ -1203,17 +1205,14 @@ func incomingTxHandlerProcessing(maxGroupSize, numberOfTransactionGroups int, t
require.NoError(t, err)
defer ledger.Close()
- handler, err := makeTestTxHandler(ledger, cfg)
+ handler, _, err := makeTestTxHandler(ledger, cfg)
require.NoError(t, err)
defer handler.txVerificationPool.Shutdown()
defer close(handler.streamVerifierDropped)
- // since Start is not called, set the context here
- handler.ctx, handler.ctxCancel = context.WithCancel(context.Background())
- defer handler.ctxCancel()
-
// emulate handler.Start() without the backlog
handler.ctx, handler.ctxCancel = context.WithCancel(context.Background())
+ defer handler.ctxCancel()
handler.streamVerifier.Start(handler.ctx)
testResultChan := make(chan *txBacklogMsg, 10)
@@ -1536,7 +1535,7 @@ func BenchmarkHandleMsigTxns(b *testing.B) {
}
}
-// BenchmarkHandleTxnGroups sends signed transaction groups directly to the verifier
+// BenchmarkHandleMsigTxnGroups sends signed transaction groups directly to the verifier
func BenchmarkHandleMsigTxnGroups(b *testing.B) {
maxGroupSize := proto.MaxTxGroupSize / 2
msigSizes := []int{64, 16, 8, 4}
@@ -1583,7 +1582,7 @@ func BenchmarkHandleBLWTxnGroups(b *testing.B) {
}
}
-// BenchmarkHandleTxnGroups sends signed transaction groups directly to the verifier
+// BenchmarkHandleLsigTxnGroups sends signed transaction groups directly to the verifier
func BenchmarkHandleLsigTxnGroups(b *testing.B) {
maxGroupSize := proto.MaxTxGroupSize / 2
invalidRates := []float32{0.5, 0.001}
@@ -1723,7 +1722,7 @@ func runHandlerBenchmarkWithBacklog(b *testing.B, txGen txGenIf, tps int, useBac
// ones are rotated again. If the purpose is to test dedup, then this can be changed by setting
// genTCount = b.N
cfg.TxIncomingFilteringFlags = 0
- handler, err := makeTestTxHandler(ledger, cfg)
+ handler, _, err := makeTestTxHandler(ledger, cfg)
require.NoError(b, err)
defer handler.txVerificationPool.Shutdown()
defer close(handler.streamVerifierDropped)
@@ -2038,20 +2037,18 @@ func TestTxHandlerPostProcessErrorWithVerify(t *testing.T) { //nolint:parallelte
func TestTxHandlerRememberReportErrors(t *testing.T) { //nolint:paralleltest // Not parallel because incomingTxHandlerProcessing mutates global metrics
partitiontest.PartitionTest(t)
+ // Use fresh metrics to avoid cross-test bleed.
defer func() {
transactionMessageTxPoolRememberCounter = metrics.NewTagCounter(
"algod_transaction_messages_txpool_remember_err_{TAG}", "Number of transaction messages not remembered by txpool b/c of {TAG}",
- txPoolRememberTagCap, txPoolRememberPendingEval, txPoolRememberTagNoSpace, txPoolRememberTagFee, txPoolRememberTagTxnDead, txPoolRememberTagTxnEarly, txPoolRememberTagTooLarge, txPoolRememberTagGroupID,
- txPoolRememberTagTxID, txPoolRememberTagLease, txPoolRememberTagTxIDEval, txPoolRememberTagLeaseEval, txPoolRememberTagEvalGeneric,
+ pools.TxPoolErrTags...,
)
}()
transactionMessageTxPoolRememberCounter = metrics.NewTagCounter(
"algod_transaction_messages_txpool_remember_err_{TAG}", "Number of transaction messages not remembered by txpool b/c of {TAG}",
- txPoolRememberTagCap, txPoolRememberPendingEval, txPoolRememberTagNoSpace, txPoolRememberTagFee, txPoolRememberTagTxnDead, txPoolRememberTagTxnEarly, txPoolRememberTagTooLarge, txPoolRememberTagGroupID,
- txPoolRememberTagTxID, txPoolRememberTagLease, txPoolRememberTagTxIDEval, txPoolRememberTagLeaseEval, txPoolRememberTagEvalGeneric,
+ pools.TxPoolErrTags...,
)
- var txh TxHandler
result := map[string]float64{}
getMetricName := func(tag string) string {
@@ -2062,23 +2059,24 @@ func TestTxHandlerRememberReportErrors(t *testing.T) { //nolint:paralleltest //
return int(result[getMetricName(tag)])
}
+ // Unwrapped and wrapped pool-level errors should increment the right tag.
noSpaceErr := ledgercore.ErrNoSpace
- txh.rememberReportErrors(noSpaceErr)
+ transactionMessageTxPoolRememberCounter.Add(pools.ClassifyTxPoolError(noSpaceErr), 1)
transactionMessageTxPoolRememberCounter.AddMetric(result)
- require.Equal(t, 1, getMetricCounter(txPoolRememberTagNoSpace))
+ require.Equal(t, 1, getMetricCounter(pools.TxPoolErrTagNoSpace))
wrapped := fmt.Errorf("wrap: %w", noSpaceErr) // simulate wrapping
- txh.rememberReportErrors(wrapped)
+ transactionMessageTxPoolRememberCounter.Add(pools.ClassifyTxPoolError(wrapped), 1)
transactionMessageTxPoolRememberCounter.AddMetric(result)
- require.Equal(t, 2, getMetricCounter(txPoolRememberTagNoSpace))
+ require.Equal(t, 2, getMetricCounter(pools.TxPoolErrTagNoSpace))
feeErr := pools.ErrTxPoolFeeError{}
wrapped = fmt.Errorf("wrap: %w", &feeErr) // simulate wrapping
- txh.rememberReportErrors(wrapped)
+ transactionMessageTxPoolRememberCounter.Add(pools.ClassifyTxPoolError(wrapped), 1)
transactionMessageTxPoolRememberCounter.AddMetric(result)
- require.Equal(t, 1, getMetricCounter(txPoolRememberTagFee))
+ require.Equal(t, 1, getMetricCounter(pools.TxPoolErrTagFee))
}
func makeBlockTicker() *blockTicker {
@@ -2111,26 +2109,23 @@ func (t *blockTicker) Wait() {
func TestTxHandlerRememberReportErrorsWithTxPool(t *testing.T) { //nolint:paralleltest // Not parallel because it mutates global metrics
partitiontest.PartitionTest(t)
defer func() {
+ // Reset metrics so this test can assert exact counts.
transactionMessageTxPoolRememberCounter = metrics.NewTagCounter(
"algod_transaction_messages_txpool_remember_err_{TAG}", "Number of transaction messages not remembered by txpool b/c of {TAG}",
- txPoolRememberTagCap, txPoolRememberPendingEval, txPoolRememberTagNoSpace, txPoolRememberTagFee, txPoolRememberTagTxnDead, txPoolRememberTagTxnEarly, txPoolRememberTagTooLarge, txPoolRememberTagGroupID,
- txPoolRememberTagTxID, txPoolRememberTagLease, txPoolRememberTagTxIDEval, txPoolRememberTagLeaseEval, txPoolRememberTagEvalGeneric,
+ pools.TxPoolErrTags...,
)
transactionMessageTxPoolCheckCounter = metrics.NewTagCounter(
"algod_transaction_messages_txpool_check_err_{TAG}", "Number of transaction messages that didn't pass check by txpool b/c of {TAG}",
- txPoolRememberTagTxnNotWellFormed, txPoolRememberTagTxnDead, txPoolRememberTagTxnEarly, txPoolRememberTagTooLarge, txPoolRememberTagGroupID,
- txPoolRememberTagTxID, txPoolRememberTagLease, txPoolRememberTagTxIDEval, txPoolRememberTagLeaseEval, txPoolRememberTagEvalGeneric,
+ pools.TxPoolErrTags...,
)
}()
transactionMessageTxPoolRememberCounter = metrics.NewTagCounter(
"algod_transaction_messages_txpool_remember_err_{TAG}", "Number of transaction messages not remembered by txpool b/c of {TAG}",
- txPoolRememberTagCap, txPoolRememberPendingEval, txPoolRememberTagNoSpace, txPoolRememberTagFee, txPoolRememberTagTxnDead, txPoolRememberTagTxnEarly, txPoolRememberTagTooLarge, txPoolRememberTagGroupID,
- txPoolRememberTagTxID, txPoolRememberTagLease, txPoolRememberTagTxIDEval, txPoolRememberTagLeaseEval, txPoolRememberTagEvalGeneric,
+ pools.TxPoolErrTags...,
)
transactionMessageTxPoolCheckCounter = metrics.NewTagCounter(
"algod_transaction_messages_txpool_check_err_{TAG}", "Number of transaction messages that didn't pass check by txpool b/c of {TAG}",
- txPoolRememberTagTxnNotWellFormed, txPoolRememberTagTxnDead, txPoolRememberTagTxnEarly, txPoolRememberTagTooLarge, txPoolRememberTagGroupID,
- txPoolRememberTagTxID, txPoolRememberTagLease, txPoolRememberTagTxIDEval, txPoolRememberTagLeaseEval, txPoolRememberTagEvalGeneric,
+ pools.TxPoolErrTags...,
)
result := map[string]float64{}
@@ -2184,7 +2179,7 @@ func TestTxHandlerRememberReportErrorsWithTxPool(t *testing.T) { //nolint:parall
require.NoError(t, err)
defer ledger.Close()
- handler, err := makeTestTxHandler(ledger, cfg)
+ handler, txPool, err := makeTestTxHandler(ledger, cfg)
require.NoError(t, err)
defer handler.txVerificationPool.Shutdown()
defer close(handler.streamVerifierDropped)
@@ -2192,10 +2187,12 @@ func TestTxHandlerRememberReportErrorsWithTxPool(t *testing.T) { //nolint:parall
handler.ctx, handler.ctxCancel = context.WithCancel(context.Background())
defer handler.ctxCancel()
+ // Trigger a variety of remember/check paths to ensure each tag increments correctly.
var wi txBacklogMsg
+ wi.rawmsg = &network.IncomingMessage{Sender: mockSender{}}
wi.unverifiedTxGroup = []transactions.SignedTxn{{}}
handler.postProcessCheckedTxn(&wi)
- require.Equal(t, 1, getMetricCounter(txPoolRememberTagTxnDead))
+ require.Equal(t, 1, getMetricCounter(pools.TxPoolErrTagTxnDead))
txn1 := transactions.Transaction{
Type: protocol.PaymentTx,
@@ -2219,23 +2216,23 @@ func TestTxHandlerRememberReportErrorsWithTxPool(t *testing.T) { //nolint:parall
wi.unverifiedTxGroup = append(wi.unverifiedTxGroup, txn.Sign(secrets[0]))
}
handler.postProcessCheckedTxn(&wi)
- require.Equal(t, 1, getMetricCounter(txPoolRememberTagCap))
+ require.Equal(t, 1, getMetricCounter(pools.TxPoolErrTagCap))
// trigger not well-formed error
txn2 := txn1
txn2.Sender = basics.Address{}
wi.unverifiedTxGroup = []transactions.SignedTxn{txn2.Sign(secrets[0])}
handler.checkAlreadyCommitted(&wi)
- require.Equal(t, 1, getCheckMetricCounter(txPoolRememberTagTxnNotWellFormed))
+ require.Equal(t, 1, getCheckMetricCounter(pools.TxPoolErrTagNotWell))
// trigger group id error
txn2 = txn1
crypto.RandBytes(txn2.Group[:])
wi.unverifiedTxGroup = []transactions.SignedTxn{txn1.Sign(secrets[0]), txn2.Sign(secrets[0])}
handler.checkAlreadyCommitted(&wi)
- require.Equal(t, 1, getCheckMetricCounter(txPoolRememberTagGroupID))
+ require.Equal(t, 1, getCheckMetricCounter(pools.TxPoolErrTagGroupID))
handler.postProcessCheckedTxn(&wi)
- require.Equal(t, 1, getMetricCounter(txPoolRememberTagGroupID))
+ require.Equal(t, 1, getMetricCounter(pools.TxPoolErrTagGroupID))
// trigger group too large error
wi.unverifiedTxGroup = []transactions.SignedTxn{txn1.Sign(secrets[0])}
@@ -2245,47 +2242,47 @@ func TestTxHandlerRememberReportErrorsWithTxPool(t *testing.T) { //nolint:parall
wi.unverifiedTxGroup = append(wi.unverifiedTxGroup, txn.Sign(secrets[0]))
}
handler.postProcessCheckedTxn(&wi)
- require.Equal(t, 1, getMetricCounter(txPoolRememberTagTooLarge))
+ require.Equal(t, 1, getMetricCounter(pools.TxPoolErrTagTooLarge))
handler.checkAlreadyCommitted(&wi)
- require.Equal(t, 1, getCheckMetricCounter(txPoolRememberTagTooLarge))
+ require.Equal(t, 1, getCheckMetricCounter(pools.TxPoolErrTagTooLarge))
- // trigger eval error
+ // trigger overspend error (unfunded account)
secret := keypair()
addr := basics.Address(secret.SignatureVerifier)
txn2 = txn1
txn2.Sender = addr
wi.unverifiedTxGroup = []transactions.SignedTxn{txn2.Sign(secret)}
handler.postProcessCheckedTxn(&wi)
- require.Equal(t, 1, getMetricCounter(txPoolRememberTagEvalGeneric))
+ require.Equal(t, 1, getMetricCounter(pools.TxPoolErrTagOverspend))
// trigger TxnDeadErr from the evaluator for "early" case
txn2 = txn1
txn2.FirstValid = ledger.LastRound() + 10
- prevTxnEarly := getMetricCounter(txPoolRememberTagTxnEarly)
+ prevTxnEarly := getMetricCounter(pools.TxPoolErrTagTxnEarly)
wi.unverifiedTxGroup = []transactions.SignedTxn{txn2.Sign(secrets[0])}
handler.postProcessCheckedTxn(&wi)
- require.Equal(t, prevTxnEarly+1, getMetricCounter(txPoolRememberTagTxnEarly))
+ require.Equal(t, prevTxnEarly+1, getMetricCounter(pools.TxPoolErrTagTxnEarly))
handler.checkAlreadyCommitted(&wi)
- require.Equal(t, 1, getCheckMetricCounter(txPoolRememberTagTxnEarly))
+ require.Equal(t, 1, getCheckMetricCounter(pools.TxPoolErrTagTxnEarly))
// trigger TxnDeadErr from the evaluator for "late" case
txn2 = txn1
txn2.LastValid = 0
- prevTxnDead := getMetricCounter(txPoolRememberTagTxnDead)
+ prevTxnDead := getMetricCounter(pools.TxPoolErrTagTxnDead)
wi.unverifiedTxGroup = []transactions.SignedTxn{txn2.Sign(secrets[0])}
handler.postProcessCheckedTxn(&wi)
- require.Equal(t, prevTxnDead+1, getMetricCounter(txPoolRememberTagTxnDead))
+ require.Equal(t, prevTxnDead+1, getMetricCounter(pools.TxPoolErrTagTxnDead))
handler.checkAlreadyCommitted(&wi)
- require.Equal(t, 1, getCheckMetricCounter(txPoolRememberTagTxnDead))
+ require.Equal(t, 1, getCheckMetricCounter(pools.TxPoolErrTagTxnDead))
// trigger TransactionInLedgerError (txid) error
wi.unverifiedTxGroup = []transactions.SignedTxn{txn1.Sign(secrets[0])}
- wi.rawmsg = &network.IncomingMessage{}
+ wi.rawmsg = &network.IncomingMessage{Sender: mockSender{}}
handler.postProcessCheckedTxn(&wi)
handler.postProcessCheckedTxn(&wi)
- require.Equal(t, 1, getMetricCounter(txPoolRememberTagTxIDEval))
+ require.Equal(t, 1, getMetricCounter(pools.TxPoolErrTagTxIDEval))
handler.checkAlreadyCommitted(&wi)
- require.Equal(t, 1, getCheckMetricCounter(txPoolRememberTagTxIDEval))
+ require.Equal(t, 1, getCheckMetricCounter(pools.TxPoolErrTagTxIDEval))
// trigger LeaseInLedgerError (lease) error
txn2 = txn1
@@ -2296,9 +2293,9 @@ func TestTxHandlerRememberReportErrorsWithTxPool(t *testing.T) { //nolint:parall
handler.postProcessCheckedTxn(&wi)
wi.unverifiedTxGroup = []transactions.SignedTxn{txn3.Sign(secrets[0])}
handler.postProcessCheckedTxn(&wi)
- require.Equal(t, 1, getMetricCounter(txPoolRememberTagLeaseEval))
+ require.Equal(t, 1, getMetricCounter(pools.TxPoolErrTagLeaseEval))
handler.checkAlreadyCommitted(&wi)
- require.Equal(t, 1, getCheckMetricCounter(txPoolRememberTagLeaseEval))
+ require.Equal(t, 1, getCheckMetricCounter(pools.TxPoolErrTagLeaseEval))
// TODO: not sure how to trigger fee error - need to return ErrNoSpace from ledger
// trigger pool fee error
@@ -2310,7 +2307,7 @@ func TestTxHandlerRememberReportErrorsWithTxPool(t *testing.T) { //nolint:parall
// make an invalid block to fail recompute pool and expose transactionMessageTxGroupRememberNoPendingEval metric
blockTicker := makeBlockTicker()
blockListeners := []ledgercore.BlockListener{
- handler.txPool,
+ txPool,
blockTicker,
}
ledger.RegisterBlockListeners(blockListeners)
@@ -2336,7 +2333,7 @@ func TestTxHandlerRememberReportErrorsWithTxPool(t *testing.T) { //nolint:parall
wi.unverifiedTxGroup = []transactions.SignedTxn{}
handler.postProcessCheckedTxn(&wi)
- require.Equal(t, 1, getMetricCounter(txPoolRememberPendingEval))
+ require.Equal(t, 1, getMetricCounter(pools.TxPoolErrTagPendingEval))
}
func TestMakeTxHandlerErrors(t *testing.T) {
@@ -2420,7 +2417,7 @@ func TestTxHandlerRestartWithBacklogAndTxPool(t *testing.T) { //nolint:parallelt
require.NoError(t, err)
defer ledger.Ledger.Close()
- handler, err := makeTestTxHandler(ledger, cfg)
+ handler, txPool, err := makeTestTxHandler(ledger, cfg)
require.NoError(t, err)
defer handler.txVerificationPool.Shutdown()
defer close(handler.streamVerifierDropped)
@@ -2487,18 +2484,17 @@ func TestTxHandlerRestartWithBacklogAndTxPool(t *testing.T) { //nolint:parallelt
}
inputGoodTxnCount := len(signedTransactionGroups) - len(badTxnGroups)
- tp := handler.txPool
// Wait until all the expected transactions are in the pool
for x := 0; x < 100; x++ {
- if len(tp.PendingTxGroups()) == inputGoodTxnCount {
+ if len(txPool.PendingTxGroups()) == inputGoodTxnCount {
break
}
time.Sleep(40 * time.Millisecond)
}
// check the couters and the accepted transactions
- require.Equal(t, inputGoodTxnCount, len(tp.PendingTxGroups()))
- for _, txg := range tp.PendingTxGroups() {
+ require.Equal(t, inputGoodTxnCount, len(txPool.PendingTxGroups()))
+ for _, txg := range txPool.PendingTxGroups() {
u, _ := binary.Uvarint(txg[0].Txn.Note)
_, inBad := badTxnGroups[u]
require.False(t, inBad, "invalid transaction accepted")
@@ -2524,8 +2520,9 @@ func TestTxHandlerAppRateLimiterERLEnabled(t *testing.T) {
cfg := config.GetDefaultLocal()
cfg.TxBacklogAppTxRateLimiterMaxSize = 100
- cfg.TxBacklogServiceRateWindowSeconds = 1
- cfg.TxBacklogAppTxPerSecondRate = 3
+ cfg.TxBacklogServiceRateWindowSeconds = 3
+ cfg.TxBacklogAppRateLimitingCongestionPct = 50
+ cfg.TxBacklogAppTxPerSecondRate = 1
cfg.TxBacklogSize = 3
l, err := LoadLedger(log, ledgerName, inMem, protocol.ConsensusCurrentVersion, genBal, genesisID, genesisHash, cfg)
require.NoError(t, err)
@@ -2534,7 +2531,7 @@ func TestTxHandlerAppRateLimiterERLEnabled(t *testing.T) {
func() {
cfg.EnableTxBacklogRateLimiting = false
cfg.EnableTxBacklogAppRateLimiting = false
- handler, err := makeTestTxHandler(l, cfg)
+ handler, _, err := makeTestTxHandler(l, cfg)
require.NoError(t, err)
defer handler.txVerificationPool.Shutdown()
defer close(handler.streamVerifierDropped)
@@ -2546,7 +2543,7 @@ func TestTxHandlerAppRateLimiterERLEnabled(t *testing.T) {
func() {
cfg.EnableTxBacklogRateLimiting = true
cfg.EnableTxBacklogAppRateLimiting = false
- handler, err := makeTestTxHandler(l, cfg)
+ handler, _, err := makeTestTxHandler(l, cfg)
require.NoError(t, err)
defer handler.txVerificationPool.Shutdown()
defer close(handler.streamVerifierDropped)
@@ -2557,7 +2554,7 @@ func TestTxHandlerAppRateLimiterERLEnabled(t *testing.T) {
cfg.EnableTxBacklogRateLimiting = true
cfg.EnableTxBacklogAppRateLimiting = true
- handler, err := makeTestTxHandler(l, cfg)
+ handler, _, err := makeTestTxHandler(l, cfg)
require.NoError(t, err)
defer handler.txVerificationPool.Shutdown()
defer close(handler.streamVerifierDropped)
@@ -2636,13 +2633,13 @@ func TestTxHandlerAppRateLimiter(t *testing.T) {
cfg := config.GetDefaultLocal()
cfg.EnableTxBacklogRateLimiting = true
cfg.TxBacklogAppTxRateLimiterMaxSize = 100
- cfg.TxBacklogServiceRateWindowSeconds = 1
- cfg.TxBacklogAppTxPerSecondRate = 3
+ cfg.TxBacklogServiceRateWindowSeconds = 3
+ cfg.TxBacklogAppTxPerSecondRate = 1
l, err := LoadLedger(log, ledgerName, inMem, protocol.ConsensusCurrentVersion, genBal, genesisID, genesisHash, cfg)
require.NoError(t, err)
defer l.Close()
- handler, err := makeTestTxHandler(l, cfg)
+ handler, _, err := makeTestTxHandler(l, cfg)
require.NoError(t, err)
defer handler.txVerificationPool.Shutdown()
defer close(handler.streamVerifierDropped)
@@ -2711,7 +2708,7 @@ func TestTxHandlerCapGuard(t *testing.T) {
require.NoError(t, err)
defer ledger.Close()
- handler, err := makeTestTxHandler(ledger, cfg)
+ handler, _, err := makeTestTxHandler(ledger, cfg)
require.NoError(t, err)
defer handler.txVerificationPool.Shutdown()
defer close(handler.streamVerifierDropped)
@@ -2765,7 +2762,7 @@ func TestTxHandlerValidateIncomingTxMessage(t *testing.T) {
require.NoError(t, err)
defer ledger.Close()
- handler, err := makeTestTxHandler(ledger, cfg)
+ handler, _, err := makeTestTxHandler(ledger, cfg)
require.NoError(t, err)
handler.Start()
defer handler.Stop()
@@ -2800,7 +2797,7 @@ func TestTxHandlerValidateIncomingTxMessage(t *testing.T) {
// make sure the reencoding from the canonical dedup checker's reencoding buf is correctly reused
cfg.TxIncomingFilteringFlags = 2
require.True(t, cfg.TxFilterCanonicalEnabled())
- handler, err := makeTestTxHandler(ledger, cfg)
+ handler, _, err := makeTestTxHandler(ledger, cfg)
require.NoError(t, err)
handler.Start()
defer handler.Stop()
@@ -2947,7 +2944,7 @@ func TestTxHandlerERLIPClient(t *testing.T) {
require.NoError(t, err)
defer l.Close()
- handler, err := makeTestTxHandler(l, cfg)
+ handler, _, err := makeTestTxHandler(l, cfg)
require.NoError(t, err)
defer handler.txVerificationPool.Shutdown()
defer close(handler.streamVerifierDropped)
@@ -2994,3 +2991,271 @@ func TestTxHandlerERLIPClient(t *testing.T) {
require.Equal(t, network.OutgoingMessage{Action: network.Ignore}, action)
require.Equal(t, 4, len(handler.backlogQueue))
}
+
+type mockTxPool struct {
+ appCost uint64
+ errorProbability float64
+ errCount atomic.Int64
+ successCount atomic.Int64
+}
+
+func (m *mockTxPool) Test(txg []transactions.SignedTxn) error {
+ return nil
+}
+
+func (m *mockTxPool) Remember(txg []transactions.SignedTxn) error {
+ if rand.Float64() < m.errorProbability {
+ m.errCount.Add(1)
+ return errors.New("mock tx pool error")
+ }
+ m.successCount.Add(1)
+ return nil
+}
+
+func TestTxHandlerAppRateLimiter_PenalizeEvalError(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ t.Skip("This is 10s test with lots of knobs, better when running manually")
+
+ const numUsers = 4
+ 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.Panic)
+
+ cfg := config.GetDefaultLocal()
+ cfg.EnableTxBacklogRateLimiting = false // disble ERL to simplify the test
+ cfg.EnableTxBacklogAppRateLimiting = true
+ cfg.TxBacklogRateLimitingCongestionPct = 0 // always congested
+ // cfg.TxBacklogAppTxRateLimiterMaxSize = 100
+ cfg.TxBacklogServiceRateWindowSeconds = 10
+ cfg.TxBacklogAppTxPerSecondRate = 1
+ l, err := LoadLedger(log, ledgerName, inMem, protocol.ConsensusCurrentVersion, genBal, genesisID, genesisHash, cfg)
+ require.NoError(t, err)
+ defer l.Close()
+
+ // setup mock tx pool with app cost 1000 and 90% error probability
+ mockPool := &mockTxPool{
+ appCost: 1000,
+ errorProbability: 0.9,
+ }
+ backlogPool := execpool.MakeBacklog(nil, 0, execpool.LowPriority, nil)
+ opts := TxHandlerOpts{
+ mockPool, backlogPool, l, &mocks.MockNetwork{}, cfg,
+ }
+ handler, err := MakeTxHandler(opts)
+ require.NoError(t, err)
+ handler.ctx, handler.ctxCancel = context.WithCancel(t.Context())
+ defer handler.ctxCancel()
+ handler.appLimiterBacklogThreshold = -1 // force the rate limiter to start checking transactions
+
+ defer handler.txVerificationPool.Shutdown()
+
+ getAppCallTx := func(senderAcctIdx int, appID basics.AppIndex) transactions.SignedTxn {
+ tx := transactions.Transaction{
+ Type: protocol.ApplicationCallTx,
+ Header: transactions.Header{
+ Sender: addresses[senderAcctIdx],
+ Fee: basics.MicroAlgos{Raw: proto.MinTxnFee},
+ FirstValid: 1,
+ LastValid: basics.Round(proto.MaxTxnLife),
+ Note: make([]byte, 8),
+ },
+ ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
+ ApplicationID: appID,
+ },
+ }
+ crypto.RandBytes(tx.Note)
+ return tx.Sign(secrets[senderAcctIdx])
+ }
+
+ generateTxnGroup := func() []byte {
+ stx0 := getAppCallTx(0, 1)
+ stx1 := getAppCallTx(0, 2)
+ tx2 := getTransaction(addresses[2], addresses[3], 1000)
+ stx2 := tx2.Sign(secrets[2])
+ stx3 := getAppCallTx(0, 3)
+
+ result := append(protocol.Encode(&stx0), protocol.Encode(&stx1)...)
+ result = append(result, protocol.Encode(&stx2)...)
+ result = append(result, protocol.Encode(&stx3)...)
+ return result
+ }
+
+ wg := sync.WaitGroup{}
+ wg.Add(1)
+ // Make a test backlog worker, which is similar to backlogWorker, but sends the results
+ // through the testResultChan instead of passing it to postProcessCheckedTxn
+ go func() {
+ defer wg.Done()
+ for {
+ select {
+ case wi, ok := <-handler.backlogQueue:
+ if !ok {
+ return
+ }
+
+ wi.verificationErr = nil
+ handler.postProcessCheckedTxn(wi)
+ case <-handler.ctx.Done():
+ return
+ }
+ }
+ }()
+
+ dropsBefore := transactionMessagesAppLimiterDrop.GetUint64Value()
+
+ const numRemoteAddresses = 150
+ const numMessages = 100_000
+ for i := 0; i < numMessages; i++ {
+ msg := network.IncomingMessage{
+ Data: generateTxnGroup(),
+ Sender: mockSender{addr: [8]byte{byte(i % numRemoteAddresses)}},
+ }
+ _ = handler.processIncomingTxn(msg)
+ }
+
+ for {
+ if len(handler.backlogQueue) == 0 {
+ break
+ }
+ time.Sleep(10 * time.Millisecond)
+ }
+ handler.ctxCancel()
+ wg.Wait()
+
+ t.Logf("dropped %d, remember counters e=%d, ok=%d", transactionMessagesAppLimiterDrop.GetUint64Value()-dropsBefore, mockPool.errCount.Load(), mockPool.successCount.Load())
+ require.Greater(t, transactionMessagesAppLimiterDrop.GetUint64Value()-dropsBefore, uint64(0.9*numMessages))
+}
+
+// TestTxHandlerAppLimiter_NotPenalizeOutgoing verifies that penalizeEvalError is only called
+// for incoming messages (Outgoing=false) and not for outgoing messages (Outgoing=true).
+func TestTxHandlerAppLimiter_NotPenalizeOutgoing(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ log := logging.TestingLog(t)
+ log.SetLevel(logging.Warn)
+
+ const numAccts = 2
+ genesis := make(map[basics.Address]basics.AccountData, numAccts+1)
+ addresses := make([]basics.Address, numAccts)
+ secrets := make([]*crypto.SignatureSecrets, numAccts)
+
+ for i := 0; i < numAccts; i++ {
+ secret := keypair()
+ addr := basics.Address(secret.SignatureVerifier)
+ secrets[i] = secret
+ addresses[i] = addr
+ genesis[addr] = basics.AccountData{
+ Status: basics.Online,
+ MicroAlgos: basics.MicroAlgos{Raw: 10000000000000},
+ }
+ }
+ genesis[poolAddr] = basics.AccountData{
+ Status: basics.NotParticipating,
+ MicroAlgos: basics.MicroAlgos{Raw: config.Consensus[protocol.ConsensusCurrentVersion].MinBalance},
+ }
+
+ genBal := bookkeeping.MakeGenesisBalances(genesis, sinkAddr, poolAddr)
+ ledgerName := fmt.Sprintf("%s-mem-%d", t.Name(), rand.Int())
+ const inMem = true
+ cfg := config.GetDefaultLocal()
+ cfg.Archival = true
+ cfg.EnableTxBacklogRateLimiting = true
+ cfg.EnableTxBacklogAppRateLimiting = true
+ cfg.TxBacklogAppTxRateLimiterMaxSize = 100
+ cfg.TxBacklogServiceRateWindowSeconds = 1
+ cfg.TxBacklogAppTxPerSecondRate = 100
+
+ ledger, err := LoadLedger(log, ledgerName, inMem, protocol.ConsensusCurrentVersion, genBal, genesisID, genesisHash, 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)
+ handler.ctx, handler.ctxCancel = context.WithCancel(context.Background())
+ defer handler.ctxCancel()
+
+ require.NotNil(t, handler.appLimiter)
+
+ // Create an app call transaction from an unknown address that will fail in txPool.Remember with overspend
+ unknownSecret := keypair()
+ unknownAddr := basics.Address(unknownSecret.SignatureVerifier)
+
+ appTx := transactions.Transaction{
+ Type: protocol.ApplicationCallTx,
+ Header: transactions.Header{
+ Sender: unknownAddr,
+ Fee: basics.MicroAlgos{Raw: proto.MinTxnFee * 2},
+ FirstValid: 0,
+ LastValid: basics.Round(proto.MaxTxnLife),
+ GenesisHash: genesisHash,
+ },
+ ApplicationCallTxnFields: transactions.ApplicationCallTxnFields{
+ ApplicationID: 1,
+ },
+ }
+
+ var wi txBacklogMsg
+
+ // outgoing message should NOT trigger penalizeEvalError
+ crypto.RandBytes(appTx.Note[:])
+ wi = txBacklogMsg{
+ unverifiedTxGroup: []transactions.SignedTxn{appTx.Sign(unknownSecret)},
+ rawmsg: &network.IncomingMessage{
+ Sender: mockSender{addr: [8]byte{5, 6, 7, 8}},
+ Outgoing: true,
+ },
+ }
+
+ handler.postProcessCheckedTxn(&wi)
+ require.Equal(t, 0, handler.appLimiter.len())
+
+ // incoming message should trigger penalizeEvalError
+ wi.unverifiedTxGroup = []transactions.SignedTxn{appTx.Sign(unknownSecret)}
+ wi.rawmsg = &network.IncomingMessage{
+ Sender: mockSender{addr: [8]byte{1, 2, 3, 4}},
+ Outgoing: false,
+ }
+
+ handler.postProcessCheckedTxn(&wi)
+ // appLimiter should have entries after incoming message with error
+ require.Greater(t, handler.appLimiter.len(), 0)
+}
+
+func TestTxHandlerNilTxPool(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ log := logging.TestingLog(t)
+ log.SetLevel(logging.Panic)
+
+ _, err := MakeTxHandler(TxHandlerOpts{
+ TxPool: nil,
+ })
+ require.ErrorIs(t, err, ErrInvalidTxPool)
+
+ var nilPoll transactionPool = nil
+ _, err = MakeTxHandler(TxHandlerOpts{
+ TxPool: nilPoll,
+ })
+ require.ErrorIs(t, err, ErrInvalidTxPool)
+
+ // This case not handled in MakeTxHandler
+ // var nilPoll2 *mockTxPool
+ // _, err = MakeTxHandler(TxHandlerOpts{
+ // TxPool: nilPoll2,
+ // })
+ // require.ErrorIs(t, err, ErrInvalidTxPool)
+
+ _, err = MakeTxHandler(TxHandlerOpts{
+ TxPool: &mockTxPool{},
+ })
+ require.NotErrorIs(t, err, ErrInvalidTxPool)
+}
diff --git a/data/txntest/defi.go b/data/txntest/defi.go
index 895eb0a54c..490fc35b86 100644
--- a/data/txntest/defi.go
+++ b/data/txntest/defi.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/txntest/program.go b/data/txntest/program.go
index 00b6d95852..f708c32a5e 100644
--- a/data/txntest/program.go
+++ b/data/txntest/program.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/data/txntest/txn.go b/data/txntest/txn.go
index 7b46a93d44..78c1f26261 100644
--- a/data/txntest/txn.go
+++ b/data/txntest/txn.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -86,8 +86,8 @@ type Txn struct {
Access []transactions.ResourceRef
LocalStateSchema basics.StateSchema
GlobalStateSchema basics.StateSchema
- ApprovalProgram interface{} // string, nil, or []bytes if already compiled
- ClearStateProgram interface{} // string, nil or []bytes if already compiled
+ ApprovalProgram any // string, nil, or []bytes if already compiled
+ ClearStateProgram any // string, nil or []bytes if already compiled
ExtraProgramPages uint32
StateProofType protocol.StateProofType
@@ -193,7 +193,11 @@ func (tx *Txn) FillDefaults(params config.ConsensusParams) {
case []byte:
}
}
-
+ if tx.ApplicationID == 0 && tx.ExtraProgramPages == 0 {
+ totalLength := len(assemble(tx.ApprovalProgram)) + len(assemble(tx.ClearStateProgram))
+ totalPages := basics.DivCeil(totalLength, params.MaxAppTotalProgramLen)
+ tx.ExtraProgramPages = uint32(totalPages - 1)
+ }
}
}
@@ -316,13 +320,6 @@ func (tx Txn) SignedTxn() transactions.SignedTxn {
return transactions.SignedTxn{Txn: tx.Txn()}
}
-// SignedTxnWithAD produces unsigned, transactions.SignedTxnWithAD
-// from the fields in this Txn. This seemingly pointless operation
-// exists, again, for convenience when driving tests.
-func (tx Txn) SignedTxnWithAD() transactions.SignedTxnWithAD {
- return transactions.SignedTxnWithAD{SignedTxn: tx.SignedTxn()}
-}
-
// Group turns a list of Txns into a slice of SignedTxns with
// GroupIDs set properly to make them a transaction group. The input
// Txns are modified with the calculated GroupID.
diff --git a/docs/messagepack.md b/docs/messagepack.md
index c81c19fde0..acfcaaeadf 100644
--- a/docs/messagepack.md
+++ b/docs/messagepack.md
@@ -32,7 +32,9 @@ idea of the performance difference, [here are some benchmarks for Transactions](
## Code generation
-Install `msgp` with [install_buildtools.sh](scripts/buildtools/install_buildtools.sh) and use it with `make msgp`.
+Run `make msgp`, which uses `go run` to invoke a specific version of
+`algorand/msgp` (usually the latest, be we hardcode the specific
+version).
The generated Marshal and Unmarshal utilities are located in `msgp_gen.go`
files. Update `MSGP_GENERATE` in the Makefile to add another package.
diff --git a/gen/generate.go b/gen/generate.go
index 7c055b6c03..48818e8a0f 100644
--- a/gen/generate.go
+++ b/gen/generate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/gen/generate_test.go b/gen/generate_test.go
index 36c3bd4a07..c02bf5bd63 100644
--- a/gen/generate_test.go
+++ b/gen/generate_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/gen/walletData.go b/gen/walletData.go
index c5dca94b3e..7a2b301816 100644
--- a/gen/walletData.go
+++ b/gen/walletData.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/go.mod b/go.mod
index ca3cf2f0ce..398c42b4a6 100644
--- a/go.mod
+++ b/go.mod
@@ -49,16 +49,16 @@ require (
github.com/olivere/elastic v6.2.14+incompatible
github.com/prometheus/client_golang v1.20.5
github.com/prometheus/client_model v0.6.1
- github.com/sirupsen/logrus v1.8.1
+ github.com/sirupsen/logrus v1.8.3
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.10.0
go.opencensus.io v0.24.0
go.uber.org/zap v1.27.0
- golang.org/x/crypto v0.37.0
+ golang.org/x/crypto v0.45.0
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
- golang.org/x/sync v0.13.0
- golang.org/x/sys v0.32.0
- golang.org/x/text v0.24.0
+ golang.org/x/sync v0.18.0
+ golang.org/x/sys v0.38.0
+ golang.org/x/text v0.31.0
gopkg.in/sohlich/elogrus.v3 v3.0.0-20180410122755-1fa29e2f2009
pgregory.net/rapid v1.2.0
)
@@ -197,11 +197,12 @@ require (
go.uber.org/fx v1.23.0 // indirect
go.uber.org/mock v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
- golang.org/x/mod v0.21.0 // indirect
- golang.org/x/net v0.39.0 // indirect
- golang.org/x/term v0.31.0 // indirect
+ golang.org/x/mod v0.29.0 // indirect
+ golang.org/x/net v0.47.0 // indirect
+ golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect
+ golang.org/x/term v0.37.0 // indirect
golang.org/x/time v0.8.0 // indirect
- golang.org/x/tools v0.26.0 // indirect
+ golang.org/x/tools v0.38.0 // indirect
gonum.org/v1/gonum v0.15.0 // indirect
google.golang.org/protobuf v1.35.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/go.sum b/go.sum
index d42c15dc5b..ce0354137b 100644
--- a/go.sum
+++ b/go.sum
@@ -613,8 +613,8 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
-github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.8.3 h1:DBBfY8eMYazKEJHb3JKpSPfpgd2mBCoNFlQx6C5fftU=
+github.com/sirupsen/logrus v1.8.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
@@ -738,8 +738,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
-golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
-golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
+golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
+golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
@@ -757,8 +757,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
-golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
+golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
+golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -789,8 +789,8 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
-golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
-golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
+golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
+golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
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=
@@ -806,8 +806,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
-golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
+golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -838,6 +838,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -847,8 +848,10 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
-golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
+golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU=
+golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -856,8 +859,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
-golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
-golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
+golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
+golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
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=
@@ -868,8 +871,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
-golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
+golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
+golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
@@ -896,8 +899,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
-golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
+golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
+golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/heartbeat/abstractions.go b/heartbeat/abstractions.go
index 4e9e24c321..965ad49eec 100644
--- a/heartbeat/abstractions.go
+++ b/heartbeat/abstractions.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/heartbeat/service.go b/heartbeat/service.go
index ad96d7f4f6..4a8d8ac8ba 100644
--- a/heartbeat/service.go
+++ b/heartbeat/service.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/heartbeat/service_test.go b/heartbeat/service_test.go
index e971afa9b4..652cfe153d 100644
--- a/heartbeat/service_test.go
+++ b/heartbeat/service_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/installer/config.json.example b/installer/config.json.example
index f47ffed51f..245017d4e8 100644
--- a/installer/config.json.example
+++ b/installer/config.json.example
@@ -1,5 +1,5 @@
{
- "Version": 37,
+ "Version": 38,
"AccountUpdatesStatsInterval": 5000000000,
"AccountsRebuildSynchronousMode": 1,
"AgreementIncomingBundlesQueueLength": 15,
@@ -29,6 +29,7 @@
"ConnectionsRateLimitingCount": 60,
"ConnectionsRateLimitingWindowSeconds": 1,
"CrashDBDir": "",
+ "DHTMode": "",
"DNSBootstrapID": ".algorand.network?backup=.algorand.net&dedup=.algorand-.(network|net)",
"DNSSecurityFlags": 9,
"DeadlockDetection": 0,
@@ -130,6 +131,7 @@
"TrackerDBDir": "",
"TransactionSyncDataExchangeRate": 0,
"TransactionSyncSignificantMessageThreshold": 0,
+ "TxBacklogAppRateLimitingCongestionPct": 10,
"TxBacklogAppRateLimitingCountERLDrops": false,
"TxBacklogAppTxPerSecondRate": 100,
"TxBacklogAppTxRateLimiterMaxSize": 1048576,
diff --git a/installer/rpm/algorand-devtools/algorand-devtools.spec b/installer/rpm/algorand-devtools/algorand-devtools.spec
index 5c2490653c..3082fc3fa0 100644
--- a/installer/rpm/algorand-devtools/algorand-devtools.spec
+++ b/installer/rpm/algorand-devtools/algorand-devtools.spec
@@ -26,8 +26,8 @@ This package provides development tools for the Algorand blockchain.
mkdir -p %{buildroot}/usr/bin
# NOTE: keep in sync with scripts/build_deb.sh bin_files
# NOTE: keep in sync with %files section below
-for f in carpenter catchupsrv msgpacktool tealcut tealdbg; do
- install -m 755 ${ALGO_BIN}/${f} %{buildroot}/usr/bin/${f}
+for f in carpenter msgpacktool tealdbg; do
+ install -m 755 ${ALGO_TOOLS}/${f} %{buildroot}/usr/bin/${f}
done
mkdir -p %{buildroot}/etc/pki/rpm-gpg
@@ -38,9 +38,7 @@ install -m 644 ${REPO_DIR}/installer/rpm/algorand-devtools/algorand-devtools.rep
%files
/usr/bin/carpenter
-/usr/bin/catchupsrv
/usr/bin/msgpacktool
-/usr/bin/tealcut
/usr/bin/tealdbg
/etc/pki/rpm-gpg/RPM-GPG-KEY-Algorand
/usr/lib/algorand/yum.repos.d/algorand-devtools.repo
diff --git a/installer/rpm/algorand/algorand.spec b/installer/rpm/algorand/algorand.spec
index 02e0909a78..ce703dfc11 100644
--- a/installer/rpm/algorand/algorand.spec
+++ b/installer/rpm/algorand/algorand.spec
@@ -29,7 +29,7 @@ This package provides an implementation of the Algorand protocol.
mkdir -p %{buildroot}/usr/bin
# NOTE: keep in sync with scripts/build_deb.sh bin_files
# NOTE: keep in sync with %files section below
-for f in algocfg algod algoh algokey ddconfig.sh diagcfg goal kmd node_exporter; do
+for f in algocfg algod algoh algokey diagcfg goal kmd node_exporter; do
install -m 755 ${ALGO_BIN}/${f} %{buildroot}/usr/bin/${f}
done
@@ -77,7 +77,6 @@ fi
/usr/bin/algod
/usr/bin/algoh
/usr/bin/algokey
-/usr/bin/ddconfig.sh
/usr/bin/diagcfg
/usr/bin/goal
/usr/bin/kmd
diff --git a/internal/rapidgen/rapidgenerators.go b/internal/rapidgen/rapidgenerators.go
index aa7345dcb9..d8fcf0cace 100644
--- a/internal/rapidgen/rapidgenerators.go
+++ b/internal/rapidgen/rapidgenerators.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/internal/rapidgen/tld.go b/internal/rapidgen/tld.go
index 31228125b2..157fc13f08 100644
--- a/internal/rapidgen/tld.go
+++ b/internal/rapidgen/tld.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/acctdeltas.go b/ledger/acctdeltas.go
index 360d2d1f3f..7ae25b76c8 100644
--- a/ledger/acctdeltas.go
+++ b/ledger/acctdeltas.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -543,7 +543,7 @@ func (c *onlineAccountDelta) append(acctDelta ledgercore.AccountData, deltaRound
c.newStatus = append(c.newStatus, acctDelta.Status)
}
-// makeCompactAccountDeltas takes an array of account AccountDeltas ( one array entry per round ), and compacts the arrays into a single
+// makeCompactOnlineAccountDeltas takes an array of account AccountDeltas ( one array entry per round ), and compacts the arrays into a single
// data structure that contains all the account deltas changes. While doing that, the function eliminate any intermediate account changes.
// It counts the number of changes each account get modified across the round range by specifying it in the nAcctDeltas field of the accountDeltaCount/modifiedCreatable.
func makeCompactOnlineAccountDeltas(accountDeltas []ledgercore.AccountDeltas, baseRound basics.Round, baseOnlineAccounts lruOnlineAccounts) (outAccountDeltas compactOnlineAccountDeltas) {
diff --git a/ledger/acctdeltas_test.go b/ledger/acctdeltas_test.go
index 021d23597a..1e685e3ca8 100644
--- a/ledger/acctdeltas_test.go
+++ b/ledger/acctdeltas_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -2156,7 +2156,7 @@ func BenchmarkBoxDatabaseRead(b *testing.B) {
}
}
-// TestAccountTopOnline ensures accountsOnlineTop return a right subset of accounts
+// TestAccountOnlineQueries ensures accountsOnlineTop return a right subset of accounts
// from the history table.
// Start with two online accounts A, B at round 1
// At round 2 make A offline.
diff --git a/ledger/acctonline.go b/ledger/acctonline.go
index ec4cb0e590..e89399be59 100644
--- a/ledger/acctonline.go
+++ b/ledger/acctonline.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/acctonline_expired_test.go b/ledger/acctonline_expired_test.go
index 90ebc931a1..c35667316a 100644
--- a/ledger/acctonline_expired_test.go
+++ b/ledger/acctonline_expired_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/acctonline_test.go b/ledger/acctonline_test.go
index 6654e8718c..4327f2ae24 100644
--- a/ledger/acctonline_test.go
+++ b/ledger/acctonline_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/acctonlineexp.go b/ledger/acctonlineexp.go
index 4b08b38180..0a772e6b9b 100644
--- a/ledger/acctonlineexp.go
+++ b/ledger/acctonlineexp.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/acctonlineexp_test.go b/ledger/acctonlineexp_test.go
index df53d9ef6f..3f5b943b4e 100644
--- a/ledger/acctonlineexp_test.go
+++ b/ledger/acctonlineexp_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/acctupdates.go b/ledger/acctupdates.go
index 6c6c428ddf..64257813b9 100644
--- a/ledger/acctupdates.go
+++ b/ledger/acctupdates.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -1212,7 +1212,7 @@ func (au *accountUpdates) lookupResource(rnd basics.Round, addr basics.Address,
}
}
-// lookupAllResources returns all the resources for a given address, solely based on what is persisted to disk. It does not
+// lookupAssetResources returns all the resources for a given address, solely based on what is persisted to disk. It does not
// take into account any in-memory deltas; the round number returned is the latest round number that is known to the database.
func (au *accountUpdates) lookupAssetResources(addr basics.Address, assetIDGT basics.AssetIndex, limit uint64) (data []ledgercore.AssetResourceWithIDs, validThrough basics.Round, err error) {
// Look for resources on disk
diff --git a/ledger/acctupdates_test.go b/ledger/acctupdates_test.go
index 71cf03d981..4017a26835 100644
--- a/ledger/acctupdates_test.go
+++ b/ledger/acctupdates_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/applications_test.go b/ledger/applications_test.go
index a0235caec8..70c98837dc 100644
--- a/ledger/applications_test.go
+++ b/ledger/applications_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -20,6 +20,7 @@ import (
"encoding/hex"
"fmt"
"path/filepath"
+ "strings"
"testing"
"time"
@@ -31,6 +32,7 @@ import (
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/transactions"
"github.com/algorand/go-algorand/data/transactions/logic"
+ "github.com/algorand/go-algorand/data/txntest"
"github.com/algorand/go-algorand/ledger/store/trackerdb"
ledgertesting "github.com/algorand/go-algorand/ledger/testing"
"github.com/algorand/go-algorand/logging"
@@ -1465,3 +1467,393 @@ return
a.NoError(err)
}
+
+const resizingAllowed = 42
+
+// TestSchemaUpdates tests that apps can get new global schemas
+func TestSchemaUpdates(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ genBalances, addrs, _ := ledgertesting.NewTestGenesis()
+ ledgertesting.TestConsensusRange(t, 24, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ proto := config.Consensus[cv]
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
+ a := require.New(t)
+
+ // app sets a global based on its args, if they are there
+ setter := main(`
+txn NumAppArgs
+int 2
+==
+bz maybe_del
+txna ApplicationArgs 0
+txna ApplicationArgs 1
+app_global_put
+maybe_del:
+txn NumAppArgs
+int 1
+==
+bz end // "main" puts in "end" label
+txna ApplicationArgs 0
+app_global_del
+`)
+ appID := dl.createApp(addrs[0], setter,
+ basics.StateSchema{NumUint: 2}, // globals, won't allow bytes
+ basics.StateSchema{NumByteSlice: 3}) // locals, won't allow ints
+
+ // call with no args, passes fine
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[0],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{},
+ })
+
+ app := func() basics.AppParams {
+ ap, err := dl.generator.LookupApplication(dl.generator.Latest(), addrs[0], appID)
+ a.NoError(err)
+ return *ap.AppParams
+ }
+
+ mbr := func(addr basics.Address) uint64 {
+ acct := lookup(t, dl.generator, addr)
+ return acct.MinBalance(proto.BalanceRequirements()).Raw
+ }
+ a.Equal(basics.StateSchema{NumUint: 2}, app().GlobalStateSchema)
+ a.Equal(basics.StateSchema{NumByteSlice: 3}, app().LocalStateSchema)
+ a.Zero(app().GlobalState)
+ a.Equal(proto.MinBalance+
+ proto.AppFlatParamsMinBalance+
+ 2*(proto.SchemaMinBalancePerEntry+proto.SchemaUintMinBalance),
+ mbr(addrs[0]))
+ a.Equal(proto.MinBalance, mbr(addrs[1]))
+
+ // call with two args, fails from lack of globals
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[0],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{{'A'}, {'B'}},
+ }, "store bytes count 1 exceeds schema bytes count 0")
+
+ update := txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[1], // Use another sender, to follow MBR changes
+ ApplicationID: appID,
+ OnCompletion: transactions.UpdateApplicationOC,
+ ApprovalProgram: app().ApprovalProgram, // keep it
+ GlobalStateSchema: basics.StateSchema{NumByteSlice: 1},
+ }
+ // update the global schema to allow 1 byteslice
+ if ver < resizingAllowed {
+ dl.txn(&update, "inappropriate non-zero tx.GlobalStateSchema")
+ return // no more tests, growing is disallowed
+ }
+ dl.txn(&update)
+ a.EqualValues(1, app().GlobalStateSchema.NumByteSlice)
+ a.Zero(app().GlobalStateSchema.NumUint) // cleared
+ a.Equal(basics.StateSchema{NumByteSlice: 3}, app().LocalStateSchema) // unchanged
+ a.Empty(app().GlobalState)
+ a.Equal(proto.MinBalance+proto.AppFlatParamsMinBalance, mbr(addrs[0]))
+ a.Equal(proto.MinBalance+
+ 1*(proto.SchemaMinBalancePerEntry+proto.SchemaBytesMinBalance)+
+ 0*(proto.SchemaMinBalancePerEntry+proto.SchemaUintMinBalance),
+ mbr(addrs[1]))
+
+ // call with two args can now succeed
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[0],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{{'A'}, {'B'}},
+ })
+ a.EqualValues(1, app().GlobalStateSchema.NumByteSlice)
+ a.Len(app().GlobalState, 1) // 'A' has been added
+
+ // same global ('A') can be changed
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[0],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{{'A'}, {'C'}},
+ })
+
+ // new global ('X') is too many
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[0],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{{'X'}, {'Y'}},
+ }, "store bytes count 2 exceeds schema bytes count 1")
+
+ update.GlobalStateSchema = basics.StateSchema{NumByteSlice: 2}
+ dl.txn(&update)
+ a.Equal(proto.MinBalance+proto.AppFlatParamsMinBalance, mbr(addrs[0]))
+ a.Equal(proto.MinBalance+
+ 2*(proto.SchemaMinBalancePerEntry+proto.SchemaBytesMinBalance)+
+ 0*(proto.SchemaMinBalancePerEntry+proto.SchemaUintMinBalance),
+ mbr(addrs[1]))
+ // ok now
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[0],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{{'X'}, {'Y'}},
+ })
+
+ // Now that we're using 2 globals, we can't go back
+ update.GlobalStateSchema = basics.StateSchema{NumByteSlice: 1}
+ update.FirstValid = 0 // So it changes when set to default
+ dl.txn(&update, "unable to change global schema: store bytes count 2 exceeds schema bytes count 1")
+
+ // Show that the size change goes into effect during group evaluation by
+ // updating in txn0 and using the global in tx1.
+
+ update.GlobalStateSchema = basics.StateSchema{NumByteSlice: 3}
+ dl.txgroup("", // no problem
+ &update,
+ &txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[0],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{{'J'}, {'1'}},
+ },
+ )
+ a.Equal(proto.MinBalance+proto.AppFlatParamsMinBalance, mbr(addrs[0]))
+ a.Equal(proto.MinBalance+
+ 3*(proto.SchemaMinBalancePerEntry+proto.SchemaBytesMinBalance)+
+ 0*(proto.SchemaMinBalancePerEntry+proto.SchemaUintMinBalance),
+ mbr(addrs[1]))
+
+ // Show that the size change goes into effect across groups in a block
+ // by doing txns separately. This shows that maxCounts are properly
+ // propagated to parent cows.
+ update.GlobalStateSchema = basics.StateSchema{NumByteSlice: 4}
+ update.Group = crypto.Digest{} // was filled above when part of a group
+ dl.beginBlock()
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[0],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{{'J'}, {'2'}}, // allocates storageDelta
+ })
+ dl.txn(&update) // schema change must propagate into existing storageDelta
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[0],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{{'K'}, {'1'}}, // confirms new schema is available
+ })
+ dl.endBlock()
+ a.Equal(proto.MinBalance+proto.AppFlatParamsMinBalance, mbr(addrs[0]))
+ a.Equal(proto.MinBalance+
+ 4*(proto.SchemaMinBalancePerEntry+proto.SchemaBytesMinBalance)+
+ 0*(proto.SchemaMinBalancePerEntry+proto.SchemaUintMinBalance),
+ mbr(addrs[1]))
+
+ // Fail to delete it, because we tried to use another global
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[2],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{{'L'}, {'1'}},
+ OnCompletion: transactions.DeleteApplicationOC,
+ }, "exceeds schema bytes count 4")
+
+ // Delete it so we can check MBR reductions
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[2],
+ ApplicationID: appID,
+ OnCompletion: transactions.DeleteApplicationOC,
+ })
+ a.Equal(proto.MinBalance, mbr(addrs[0]))
+ a.Equal(proto.MinBalance, mbr(addrs[1]))
+ })
+}
+
+// TestExtraPagesUpdate tests how apps can change their extra pages allocation
+func TestExtraPagesUpdate(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ genBalances, addrs, _ := ledgertesting.NewTestGenesis()
+ ledgertesting.TestConsensusRange(t, 28, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ proto := config.Consensus[cv]
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
+ a := require.New(t)
+
+ app := func(id basics.AppIndex) basics.AppParams {
+ c, _, err := dl.generator.GetCreator(basics.CreatableIndex(id), basics.AppCreatable)
+ a.NoError(err)
+ ap, err := dl.generator.LookupApplication(dl.generator.Latest(), c, id)
+ a.NoError(err)
+ return *ap.AppParams
+ }
+
+ mbr := func(addr basics.Address) uint64 {
+ acct := lookup(t, dl.generator, addr)
+ return acct.MinBalance(proto.BalanceRequirements()).Raw
+ }
+
+ small := "int 1000; return"
+ big := strings.Repeat(small+"\n", 1500)
+ smallID := dl.createApp(addrs[0], small)
+ bigID := dl.createApp(addrs[1], big)
+ a.EqualValues(0, app(smallID).ExtraProgramPages)
+ a.EqualValues(2, app(bigID).ExtraProgramPages)
+ a.Equal(proto.MinBalance+proto.AppFlatParamsMinBalance, mbr(addrs[0]))
+ a.Equal(proto.MinBalance+3*proto.AppFlatParamsMinBalance, mbr(addrs[1]))
+
+ update := txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[1],
+ ApplicationID: smallID,
+ OnCompletion: transactions.UpdateApplicationOC,
+ ApprovalProgram: app(smallID).ApprovalProgram, // keep it
+ ExtraProgramPages: 1,
+ }
+
+ // update the apps to have 3 extra pages
+ if ver < resizingAllowed {
+ dl.txn(&update, "inappropriate non-zero tx.ExtraProgramPages (1)")
+ return // no more tests, growing is disallowed
+ }
+ dl.txn(&update)
+ a.Equal(proto.MinBalance+proto.AppFlatParamsMinBalance, mbr(addrs[0]))
+ // addr[1] is now the sponsor for the small app, which now has 1 epp
+ a.Equal(proto.MinBalance+4*proto.AppFlatParamsMinBalance, mbr(addrs[1]))
+
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[2],
+ ApplicationID: bigID,
+ OnCompletion: transactions.UpdateApplicationOC,
+ ApprovalProgram: app(bigID).ApprovalProgram, // keep it
+ ExtraProgramPages: 3,
+ })
+ a.Equal(proto.MinBalance+proto.AppFlatParamsMinBalance, mbr(addrs[0]))
+ // addr[1] is still the sponsor for the small appp, which now has 1 epp (and big creator)
+ a.Equal(proto.MinBalance+2*proto.AppFlatParamsMinBalance, mbr(addrs[1]))
+ // but addr[2] has taken over rent for the big app (which is now 3)
+ a.Equal(proto.MinBalance+3*proto.AppFlatParamsMinBalance, mbr(addrs[2]))
+
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[3],
+ ApplicationID: bigID,
+ OnCompletion: transactions.DeleteApplicationOC,
+ })
+ a.Equal(proto.MinBalance+proto.AppFlatParamsMinBalance, mbr(addrs[0]))
+ // addr[1] is only the sponsor for the small app, which now has 1 epp
+ a.Equal(proto.MinBalance+1*proto.AppFlatParamsMinBalance, mbr(addrs[1]))
+ // addr[2] responsibility for big app is gone
+ a.Equal(proto.MinBalance, mbr(addrs[2]))
+
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[1],
+ ApplicationID: smallID,
+ OnCompletion: transactions.DeleteApplicationOC,
+ })
+ a.Equal(proto.MinBalance, mbr(addrs[0]))
+ a.Equal(proto.MinBalance, mbr(addrs[1]))
+ a.Equal(proto.MinBalance, mbr(addrs[2]))
+ })
+}
+
+// TestInnerUpdateResizing shows that apps can be grown (programs and globals) with inner transactions
+func TestInnerUpdateResizing(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ genBalances, addrs, _ := ledgertesting.NewTestGenesis()
+ const innerAppls = 31
+ ledgertesting.TestConsensusRange(t, innerAppls, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ proto := config.Consensus[cv]
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
+ a := require.New(t)
+
+ app := func(id basics.AppIndex) basics.AppParams {
+ c, _, err := dl.generator.GetCreator(basics.CreatableIndex(id), basics.AppCreatable)
+ a.NoError(err)
+ ap, err := dl.generator.LookupApplication(dl.generator.Latest(), c, id)
+ a.NoError(err)
+ return *ap.AppParams
+ }
+
+ mbr := func(addr basics.Address) uint64 {
+ acct := lookup(t, dl.generator, addr)
+ return acct.MinBalance(proto.BalanceRequirements()).Raw
+ }
+
+ // if we give an app arg, the app will use another global
+ small := main(`txn NumAppArgs; bz end; txn ApplicationArgs 0; byte "X"; app_global_put;`)
+ smallID := dl.createApp(addrs[0], small)
+ a.Zero(0, app(smallID).ExtraProgramPages)
+ a.Equal(proto.MinBalance+proto.AppFlatParamsMinBalance, mbr(addrs[0]))
+
+ dl.txn(&txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[0],
+ ApplicationID: smallID,
+ ApplicationArgs: [][]byte{{'A'}},
+ }, "store bytes count 1 exceeds schema bytes count 0")
+
+ // An app that will update another app with 1 epp, 2 ints, 3 byteslices
+ updater := main(`
+itxn_begin
+int appl; itxn_field TypeEnum
+txn Applications 1; itxn_field ApplicationID
+int UpdateApplication; itxn_field OnCompletion
+txn Applications 1; app_params_get AppApprovalProgram; assert; itxn_field ApprovalProgram
+txn Applications 1; app_params_get AppClearStateProgram; assert; itxn_field ClearStateProgram
+int 2; itxn_field ExtraProgramPages
+int 3; itxn_field GlobalNumUint
+int 4; itxn_field GlobalNumByteSlice
+itxn_next // right after updating, try call again, schema should be ok
+int appl; itxn_field TypeEnum
+txn Applications 1; itxn_field ApplicationID
+byte "A"; itxn_field ApplicationArgs
+itxn_submit
+// for good measure, do it again in another inner group
+itxn_begin
+int appl; itxn_field TypeEnum
+txn Applications 1; itxn_field ApplicationID
+byte "B"; itxn_field ApplicationArgs
+itxn_submit
+`)
+ updaterID := dl.fundedApp(addrs[2], 3_000_000, updater)
+
+ // call the updater on smallID
+ innerUpdate := txntest.Txn{
+ Type: protocol.ApplicationCallTx,
+ Sender: addrs[3],
+ ApplicationID: updaterID,
+ ForeignApps: []basics.AppIndex{smallID},
+ }
+ if ver < resizingAllowed {
+ dl.txn(&innerUpdate, "inappropriate non-zero tx.GlobalStateSchema")
+ return // no more tests, growing is disallowed
+ }
+ dl.txn(&innerUpdate)
+ // no extra MBR on the original creator
+ a.Equal(proto.MinBalance+proto.AppFlatParamsMinBalance, mbr(addrs[0]))
+ // the app account is now the sponsor for the app, which now has 2,3,4
+ a.Equal(proto.MinBalance+
+ 2*proto.AppFlatParamsMinBalance+ // epp
+ 3*(proto.SchemaMinBalancePerEntry+proto.SchemaUintMinBalance)+
+ 4*(proto.SchemaMinBalancePerEntry+proto.SchemaBytesMinBalance),
+ mbr(updaterID.Address()))
+ a.Equal(app(smallID).GlobalState["A"], basics.TealValue{
+ Type: basics.TealBytesType, Bytes: "X",
+ })
+ a.Equal(app(smallID).GlobalState["B"], basics.TealValue{
+ Type: basics.TealBytesType, Bytes: "X",
+ })
+ })
+}
diff --git a/ledger/apply/application.go b/ledger/apply/application.go
index 298668c3bd..31b6d6fdc5 100644
--- a/ledger/apply/application.go
+++ b/ledger/apply/application.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -25,9 +25,9 @@ import (
"github.com/algorand/go-algorand/ledger/ledgercore"
)
-// getAppParams fetches the creator address and basics.AppParams for the app index,
-// if they exist. It does *not* clone the basics.AppParams, so the returned params
-// must not be modified directly.
+// getAppParams fetches the creator address and basics.AppParams for the app
+// index, if they exist. It does not deep copy the basics.AppParams, so internal
+// reference types (programs, globals) must not be modified directly.
func getAppParams(balances Balances, aidx basics.AppIndex) (params basics.AppParams, creator basics.Address, exists bool, err error) {
creator, exists, err = balances.GetCreator(basics.CreatableIndex(aidx), basics.AppCreatable)
if err != nil {
@@ -136,32 +136,38 @@ func createApplication(ac *transactions.ApplicationCallTxnFields, balances Balan
}
func deleteApplication(balances Balances, creator basics.Address, appIdx basics.AppIndex) error {
- // Deleting the application. Fetch the creator's balance record
- record, err := balances.Get(creator, false)
+ // We need the AppParams to know how much space/MBR to deallocate
+ params, _, err := balances.GetAppParams(creator, appIdx)
if err != nil {
return err
}
- var params basics.AppParams
- params, _, err = balances.GetAppParams(creator, appIdx)
+ // Remove the MBR for application creation
+ record, err := balances.Get(creator, false)
if err != nil {
return err
}
-
- // Update the TotalAppSchema used for MinBalance calculation,
- // since the creator no longer has to store the GlobalState
- totalSchema := record.TotalAppSchema
- globalSchema := params.GlobalStateSchema
- totalSchema = totalSchema.SubSchema(globalSchema)
- record.TotalAppSchema = totalSchema
record.TotalAppParams = basics.SubSaturate(record.TotalAppParams, 1)
+ err = balances.Put(creator, record)
+ if err != nil {
+ return err
+ }
+ // Remove the MBR for globals and pages for the app from the sponsor
+ sponsor := params.SizeSponsor
+ if sponsor.IsZero() {
+ sponsor = creator
+ }
+ record, err = balances.Get(sponsor, false)
+ if err != nil {
+ return err
+ }
+ record.TotalAppSchema = record.TotalAppSchema.SubSchema(params.GlobalStateSchema)
// There was a short-lived bug so in one version, pages were not deallocated.
if balances.ConsensusParams().EnableProperExtraPageAccounting {
record.TotalExtraAppPages = basics.SubSaturate(record.TotalExtraAppPages, params.ExtraProgramPages)
}
-
- err = balances.Put(creator, record)
+ err = balances.Put(sponsor, record)
if err != nil {
return err
}
@@ -181,7 +187,7 @@ func deleteApplication(balances Balances, creator basics.Address, appIdx basics.
return nil
}
-func updateApplication(ac *transactions.ApplicationCallTxnFields, balances Balances, creator basics.Address, appIdx basics.AppIndex) error {
+func updateApplication(ac *transactions.ApplicationCallTxnFields, balances Balances, creator basics.Address, appIdx basics.AppIndex, updater basics.Address) error {
// Updating the application. Fetch the creator's balance record
params, _, err := balances.GetAppParams(creator, appIdx)
if err != nil {
@@ -189,20 +195,77 @@ func updateApplication(ac *transactions.ApplicationCallTxnFields, balances Balan
}
proto := balances.ConsensusParams()
-
- // The pre-application well-formedness check rejects big programs
- // conservatively, it doesn't know the actual params.ExtraProgramPages, so
- // it allows any programs that fit under the absolute max.
- if err = ac.WellSizedPrograms(params.ExtraProgramPages, proto); err != nil {
- return err
+ sizeChange := ac.UpdatingSizes()
+
+ if !sizeChange {
+ // The wellFormed() check rejects big programs conservatively, but it
+ // doesn't know the actual params.ExtraProgramPages, so it allows any
+ // programs that fit under the absolute max. (if there is a size change,
+ // that check is precise because the programs are in the transaction)
+ if err = ac.WellSizedPrograms(params.ExtraProgramPages, proto); err != nil {
+ return err
+ }
}
-
params.ApprovalProgram = ac.ApprovalProgram
params.ClearStateProgram = ac.ClearStateProgram
if proto.EnableAppVersioning {
params.Version++
}
+ // Install the new epp and schema (if its sufficient for current globals)
+ if sizeChange {
+ // We'll call the account that is currently on the hook for MBR space
+ // the "size sponsor". It begins as the creator, but changes whenever
+ // there is a sizeChange update.
+
+ sponsor := params.SizeSponsor
+ if sponsor.IsZero() {
+ sponsor = creator
+ }
+
+ // Since the sponsor and the updater may be the same account, we make the
+ // entire change to the sponsor, including Put(), before we Get() the
+ // updater. (similar to how Move() works)
+
+ sponsorRecord, err := balances.Get(sponsor, false)
+ if err != nil {
+ return err
+ }
+ sponsorRecord.TotalAppSchema =
+ sponsorRecord.TotalAppSchema.SubSchema(params.GlobalStateSchema)
+ sponsorRecord.TotalExtraAppPages =
+ basics.SubSaturate(sponsorRecord.TotalExtraAppPages, params.ExtraProgramPages)
+ err = balances.Put(sponsor, sponsorRecord)
+ if err != nil {
+ return err
+ }
+
+ err = balances.SetAppGlobalSchema(creator, appIdx, ac.GlobalStateSchema)
+ if err != nil {
+ return fmt.Errorf("unable to change global schema: %w", err)
+ }
+ params.GlobalStateSchema = ac.GlobalStateSchema
+ params.ExtraProgramPages = ac.ExtraProgramPages
+ if updater == creator {
+ params.SizeSponsor = basics.Address{}
+ } else {
+ params.SizeSponsor = updater
+ }
+
+ updaterRecord, err := balances.Get(updater, false)
+ if err != nil {
+ return err
+ }
+ updaterRecord.TotalAppSchema =
+ updaterRecord.TotalAppSchema.AddSchema(params.GlobalStateSchema)
+ updaterRecord.TotalExtraAppPages =
+ basics.AddSaturate(updaterRecord.TotalExtraAppPages, params.ExtraProgramPages)
+ err = balances.Put(updater, updaterRecord)
+ if err != nil {
+ return err
+ }
+ }
+
return balances.PutAppParams(creator, appIdx, params)
}
@@ -441,7 +504,7 @@ func ApplicationCall(ac transactions.ApplicationCallTxnFields, header transactio
}
if !approved {
- return fmt.Errorf("transaction rejected by ApprovalProgram")
+ return &ledgercore.ApprovalProgramRejectedError{}
}
switch ac.OnCompletion {
@@ -464,7 +527,7 @@ func ApplicationCall(ac transactions.ApplicationCallTxnFields, header transactio
}
case transactions.UpdateApplicationOC:
- err = updateApplication(&ac, balances, creator, appIdx)
+ err = updateApplication(&ac, balances, creator, appIdx, header.Sender)
if err != nil {
return err
}
diff --git a/ledger/apply/application_test.go b/ledger/apply/application_test.go
index 1437e02550..3c724ca47a 100644
--- a/ledger/apply/application_test.go
+++ b/ledger/apply/application_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -18,15 +18,14 @@ package apply
import (
"bytes"
+ "crypto/rand"
"fmt"
"maps"
- "math/rand"
"testing"
"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/transactions"
"github.com/algorand/go-algorand/data/transactions/logic"
@@ -36,14 +35,10 @@ import (
)
func getRandomAddress(a *require.Assertions) basics.Address {
- const rl = 16
- b := make([]byte, rl)
- n, err := rand.Read(b)
+ address := basics.Address{}
+ _, err := rand.Read(address[:])
a.NoError(err)
- a.Equal(rl, n)
-
- address := crypto.Hash(b)
- return basics.Address(address)
+ return address
}
type testBalances struct {
@@ -1201,7 +1196,7 @@ func TestAppCallApplyDelete(t *testing.T) {
err = ApplicationCall(ac, h, b, ad, 0, &ep, txnCounter)
a.NoError(err)
a.Equal(appIdx, b.deAllocatedAppIdx)
- a.Equal(1, b.put)
+ a.Equal(2, b.put) // creator + sponsor (who happen to be the same here)
a.Zero(b.putAppParams)
a.Equal(1, b.deleteAppParams)
br = b.balances[creator]
@@ -1233,7 +1228,7 @@ func TestAppCallApplyDelete(t *testing.T) {
err = ApplicationCall(ac, h, b, ad, 0, &ep, txnCounter)
a.NoError(err)
a.Equal(appIdx, b.deAllocatedAppIdx)
- a.Equal(1, b.put)
+ a.Equal(2, b.put) // creator + sponsor (who happen to be the same here)
a.Zero(b.putAppParams)
a.Equal(1, b.deleteAppParams)
br = b.balances[creator]
diff --git a/ledger/apply/apply.go b/ledger/apply/apply.go
index f8bf1dc2ee..d3c7964cb0 100644
--- a/ledger/apply/apply.go
+++ b/ledger/apply/apply.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -68,6 +68,8 @@ type Balances interface {
PutAppLocalState(addr basics.Address, aidx basics.AppIndex, state basics.AppLocalState) error
DeleteAppLocalState(addr basics.Address, aidx basics.AppIndex) error
+ SetAppGlobalSchema(addr basics.Address, aidx basics.AppIndex, limits basics.StateSchema) error
+
GetAssetHolding(addr basics.Address, aidx basics.AssetIndex) (basics.AssetHolding, bool, error)
PutAssetHolding(addr basics.Address, aidx basics.AssetIndex, data basics.AssetHolding) error
DeleteAssetHolding(addr basics.Address, aidx basics.AssetIndex) error
diff --git a/ledger/apply/asset.go b/ledger/apply/asset.go
index 9b85f5b31a..907db0fb11 100644
--- a/ledger/apply/asset.go
+++ b/ledger/apply/asset.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -21,6 +21,7 @@ import (
"github.com/algorand/go-algorand/data/basics"
"github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/ledger/ledgercore"
)
func getParams(balances Balances, aidx basics.AssetIndex) (params basics.AssetParams, creator basics.Address, err error) {
@@ -214,7 +215,10 @@ func takeOut(balances Balances, addr basics.Address, asset basics.AssetIndex, am
newAmount, overflowed := basics.OSub(sndHolding.Amount, amount)
if overflowed {
- return fmt.Errorf("underflow on subtracting %d from sender amount %d", amount, sndHolding.Amount)
+ return &ledgercore.AssetBalanceError{
+ Amount: amount,
+ SenderAmount: sndHolding.Amount,
+ }
}
sndHolding.Amount = newAmount
diff --git a/ledger/apply/asset_test.go b/ledger/apply/asset_test.go
index 2e988a7b59..47532b59a0 100644
--- a/ledger/apply/asset_test.go
+++ b/ledger/apply/asset_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/apply/challenge.go b/ledger/apply/challenge.go
index 19d9828daa..a40436076f 100644
--- a/ledger/apply/challenge.go
+++ b/ledger/apply/challenge.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/apply/challenge_test.go b/ledger/apply/challenge_test.go
index 24389cf3e8..b0362a846b 100644
--- a/ledger/apply/challenge_test.go
+++ b/ledger/apply/challenge_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/apply/heartbeat.go b/ledger/apply/heartbeat.go
index 898e0e269d..6bcf42c651 100644
--- a/ledger/apply/heartbeat.go
+++ b/ledger/apply/heartbeat.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/apply/heartbeat_test.go b/ledger/apply/heartbeat_test.go
index 8e1fe05d52..dbb0322ea4 100644
--- a/ledger/apply/heartbeat_test.go
+++ b/ledger/apply/heartbeat_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/apply/keyreg.go b/ledger/apply/keyreg.go
index f1d0ff630c..9edfe1e30c 100644
--- a/ledger/apply/keyreg.go
+++ b/ledger/apply/keyreg.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/apply/keyreg_test.go b/ledger/apply/keyreg_test.go
index 2acf9fb615..a282c95552 100644
--- a/ledger/apply/keyreg_test.go
+++ b/ledger/apply/keyreg_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/apply/mockBalances_test.go b/ledger/apply/mockBalances_test.go
index ed5b7b2f41..dc0f216abc 100644
--- a/ledger/apply/mockBalances_test.go
+++ b/ledger/apply/mockBalances_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -148,6 +148,13 @@ func (b *mockCreatableBalances) GetAppLocalState(addr basics.Address, aidx basic
ret, ok = acct.AppLocalStates[aidx]
return
}
+
+// SetAppGlobalSchema is supposed set the running schema limits in the
+// evaluation, but the mockCreatableBalances does not enforce those limits.
+func (b *mockCreatableBalances) SetAppGlobalSchema(addr basics.Address, aidx basics.AppIndex, limits basics.StateSchema) error {
+ return nil
+}
+
func (b *mockCreatableBalances) GetAssetHolding(addr basics.Address, aidx basics.AssetIndex) (ret basics.AssetHolding, ok bool, err error) {
acct, err := b.access.getAccount(addr, false)
if err != nil {
diff --git a/ledger/apply/payment.go b/ledger/apply/payment.go
index ba1efea2cf..067915459c 100644
--- a/ledger/apply/payment.go
+++ b/ledger/apply/payment.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/apply/payment_test.go b/ledger/apply/payment_test.go
index 82c8f28f72..0c457d6280 100644
--- a/ledger/apply/payment_test.go
+++ b/ledger/apply/payment_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/apply/stateproof.go b/ledger/apply/stateproof.go
index 8838af7161..14dcb12c5f 100644
--- a/ledger/apply/stateproof.go
+++ b/ledger/apply/stateproof.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/apply/stateproof_test.go b/ledger/apply/stateproof_test.go
index a09ef8a61c..f8e64f4240 100644
--- a/ledger/apply/stateproof_test.go
+++ b/ledger/apply/stateproof_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/apptxn_test.go b/ledger/apptxn_test.go
index b66eae15d9..02b0479c91 100644
--- a/ledger/apptxn_test.go
+++ b/ledger/apptxn_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -633,7 +633,7 @@ func TestDuplicatePayAction(t *testing.T) {
})
}
-// TestInnerTxCount ensures that inner transactions increment the TxnCounter
+// TestInnerTxnCount ensures that inner transactions increment the TxnCounter
func TestInnerTxnCount(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
@@ -3765,6 +3765,7 @@ func TestUnfundedSenders(t *testing.T) {
// no min balance.
func TestAppCallAppDuringInit(t *testing.T) {
partitiontest.PartitionTest(t)
+ t.Parallel()
genBalances, addrs, _ := ledgertesting.NewTestGenesis()
ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
@@ -3810,3 +3811,168 @@ func TestAppCallAppDuringInit(t *testing.T) {
dl.txn(&callInInit, problem)
})
}
+
+// TestZeroAppLocalsAccess confirms that a 0, used as the app in a LocalRef indicates the current app.
+func TestZeroAppLocalsAccess(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ genBalances, addrs, _ := ledgertesting.NewTestGenesis()
+ ledgertesting.TestConsensusRange(t, accessVersion, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
+
+ // readFromArg0 tries to read the local named in Arg0 from the
+ // address given in Arg1. This allows testing of various ways to provide
+ // access to locals.
+ readFromArg0 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
+txn ApplicationArgs 0 // An address
+byte "XXX"
+app_local_get
+`),
+ }
+
+ appID := dl.txn(&readFromArg0).ApplicationID
+
+ dl.txn(&txntest.Txn{
+ Type: "appl",
+ Sender: addrs[1],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{addrs[2][:]},
+ }, "unavailable Account "+addrs[2].String())
+
+ // The old way: foreign account, with the implied access the cross product with current app
+ dl.txn(&txntest.Txn{
+ Type: "appl",
+ Sender: addrs[1],
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{addrs[2][:]},
+ Accounts: []basics.Address{addrs[2]},
+ }, addrs[2].String()+" has not opted in") // shows that it's available now
+
+ // The long way with Access: specify the called app as a resource ref,
+ // then have the localref point to it.
+ dl.txn(&txntest.Txn{
+ Type: "appl",
+ Sender: addrs[1], // opt-in
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{addrs[2][:]},
+ Access: []transactions.ResourceRef{{
+ Address: addrs[2],
+ }, {
+ App: appID,
+ }, {
+ Locals: transactions.LocalsRef{
+ Address: 1, App: 2,
+ },
+ }},
+ }, addrs[2].String()+" has not opted in") // shows that it's available now
+
+ // The short way with Access: use 0 to mean the called app
+ problem := "0 App in LocalsRef is not supported"
+ if ver >= 42 { // 0 app is allowed now. (Remove this after consensus change)
+ problem = addrs[2].String() + " has not opted in"
+ }
+
+ dl.txn(&txntest.Txn{
+ Type: "appl",
+ Sender: addrs[1], // opt-in
+ ApplicationID: appID,
+ ApplicationArgs: [][]byte{addrs[2][:]},
+ Access: []transactions.ResourceRef{{
+ Address: addrs[2],
+ }, {
+ Locals: transactions.LocalsRef{
+ Address: 1, App: 0,
+ },
+ }},
+ }, problem)
+
+ })
+
+}
+
+// TestLocalAccessInNewApps shows that in a group that creates a new app, that
+// app can access any available account's locals for that app. Of course,
+// although the locals may be available, it's quite hard to construct examples
+// in which an account is opted-in to the new app.
+func TestLocalAccessInNewApps(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ genBalances, addrs, _ := ledgertesting.NewTestGenesis()
+ ledgertesting.TestConsensusRange(t, accessVersion, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) {
+ dl := NewDoubleLedger(t, genBalances, cv, cfg)
+ defer dl.Close()
+
+ // callArg0WithArg1 is an app that simply calls the appID provided in
+ // the 0th argument. It supplies its own 1st arg as the callee's
+ // 0th. It is intended to be called by a top-level app in a group where
+ // a previous transactions has created a new app. The caller of this
+ // app determines the id of that newly created app and provides it to
+ // `readFromArg0`. The goal is to re-invoke the newly created app and
+ // show it can access locals for an available account even though the
+ // Locals do not explcitly appear in an access list.
+
+ callArg0WithArg1 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
+itxn_begin
+int appl; itxn_field TypeEnum
+txn ApplicationArgs 0; btoi; itxn_field ApplicationID
+txn ApplicationArgs 1; itxn_field ApplicationArgs
+itxn_submit
+int 1
+`),
+ }
+
+ callID := dl.txn(&callArg0WithArg1).ApplicationID
+
+ // readFromArg0 tries to read the local named in Arg0 from the
+ // address given in Arg1. This allows testing of various ways to provide
+ // access to locals.
+ readFromArg0 := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: main(`
+txn ApplicationArgs 0 // An address
+byte "XXX"
+app_local_get
+`),
+ }
+
+ callFirst := txntest.Txn{
+ Type: "appl",
+ Sender: addrs[0],
+ ApprovalProgram: ` // Don't use main(), so this runs at creation time
+itxn_begin
+int appl; itxn_field TypeEnum
+gtxn 0 CreatedApplicationID // get the app ID created in first txn
+itob
+itxn_field ApplicationArgs
+txn ApplicationArgs 0; itxn_field ApplicationArgs
+int ` + strconv.FormatUint(uint64(callID), 10) + `
+itxn_field ApplicationID
+itxn_submit
+`,
+ Access: []transactions.ResourceRef{{
+ App: callID,
+ }},
+ Fee: 1_000_000, // Oversize fee, so that newly created app can make inner call
+ }
+
+ dl.txgroup("unavailable Account "+addrs[2].String(), &readFromArg0, callFirst.Args(string(addrs[2][:])))
+
+ callWithAcctAccess := callFirst
+ callWithAcctAccess.Access = append(callWithAcctAccess.Access, transactions.ResourceRef{Address: addrs[2]})
+ // The "not opted in" error shows that the local ref has become
+ // available because addr[2] because available, this demonstrates that
+ // the LocalRef is not needed because the app in question was made
+ // earlier in the same group.
+ dl.txgroup(addrs[2].String()+" has not opted in", &readFromArg0, callWithAcctAccess.Args(string(addrs[2][:])))
+ })
+}
diff --git a/ledger/archival_test.go b/ledger/archival_test.go
index 6c83d74ce2..b730bb14f2 100644
--- a/ledger/archival_test.go
+++ b/ledger/archival_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -655,11 +655,9 @@ func TestArchivalCreatables(t *testing.T) {
func makeSignedTxnInBlock(tx transactions.Transaction) transactions.SignedTxnInBlock {
return transactions.SignedTxnInBlock{
- SignedTxnWithAD: transactions.SignedTxnWithAD{
- SignedTxn: transactions.SignedTxn{
- Txn: tx,
- },
- },
+ SignedTxnWithAD: transactions.SignedTxn{
+ Txn: tx,
+ }.WithAD(),
HasGenesisID: true,
}
}
diff --git a/ledger/blockqueue.go b/ledger/blockqueue.go
index 03e7125725..cad7c140c9 100644
--- a/ledger/blockqueue.go
+++ b/ledger/blockqueue.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/blockqueue_test.go b/ledger/blockqueue_test.go
index 2084a67971..ff7f8ec366 100644
--- a/ledger/blockqueue_test.go
+++ b/ledger/blockqueue_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/boxtxn_test.go b/ledger/boxtxn_test.go
index a4f5b1c5d0..e1af25a8d9 100644
--- a/ledger/boxtxn_test.go
+++ b/ledger/boxtxn_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -130,9 +130,8 @@ var passThruSource = main(`
const (
boxVersion = 36
- accessVersion = 38
+ accessVersion = 41
boxQuotaBumpVersion = 41
- newAppCreateVersion = 41
)
func boxFee(p config.ConsensusParams, nameAndValueSize uint64) uint64 {
@@ -514,9 +513,10 @@ assert
for i := 0; i < 330; i++ {
dl.fullBlock()
}
- time.Sleep(5 * time.Second) // balancesFlushInterval, so commit happens
dl.fullBlock(call.Args("check", "x", string(make([]byte, 16))))
- time.Sleep(100 * time.Millisecond) // give commit time to run, and prune au caches
+ // commit au deltas so the box app is executed on of data from ledger, not trackers
+ commitRoundLookback(0, dl.generator)
+ commitRoundLookback(0, dl.validator)
dl.fullBlock(call.Args("check", "x", string(make([]byte, 16))))
// Still the same after caches are flushed
@@ -737,7 +737,7 @@ var passThruCreator = main(`
itxn_submit
`)
-// TestNewAppBoxCreate exercised proto.EnableUnnamedBoxCreate
+// TestNewAppBoxCreate exercises the creation of boxes in newly created apps
func TestNewAppBoxCreate(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
@@ -775,7 +775,7 @@ func testNewAppBoxCreate(t *testing.T, requestedTealVersion int) {
// 2) a) Use the predicted appID to name the box ref.
// or b) Use 0 as the app in the box ref, meaning "this app"
- // or c) EnableUnnamedBoxCreate will allow such a creation if there are empty box refs.
+ // or c) v41 (accessVersion) will allow it if there are empty box refs.
// 2a is pretty much impossible in practice, we can only do it here
// because our blockchain is "quiet" we know the upcoming appID.
@@ -864,52 +864,46 @@ func testNewAppBoxCreate(t *testing.T, requestedTealVersion int) {
{Index: 0, Name: []byte{0x02}},
}})
- if ver >= newAppCreateVersion {
- // 2c. Create it with an empty box ref
- dl.txn(&txntest.Txn{Type: "appl", Sender: addrs[0],
- ApprovalProgram: createSrcVer, ApplicationArgs: [][]byte{{0x01}},
- Boxes: []transactions.BoxRef{{}}})
+ // 2c. Create it with an empty box ref
+ dl.txn(&txntest.Txn{Type: "appl", Sender: addrs[0],
+ ApprovalProgram: createSrcVer, ApplicationArgs: [][]byte{{0x01}},
+ Boxes: []transactions.BoxRef{{}}})
+ if ver >= accessVersion {
// 2c. Create it with an empty box ref
dl.txn(&txntest.Txn{Type: "appl", Sender: addrs[0],
ApprovalProgram: createSrcVer, ApplicationArgs: [][]byte{{0x01}},
Access: []transactions.ResourceRef{{Box: transactions.BoxRef{}}}})
+ }
- // but you can't do a second create
- dl.txn(&txntest.Txn{Type: "appl", Sender: addrs[0],
- ApprovalProgram: doubleSrc, ApplicationArgs: [][]byte{{0x01}, {0x02}},
- Boxes: []transactions.BoxRef{{}}},
- "invalid Box reference 0x02")
+ // but you can't do a second create
+ dl.txn(&txntest.Txn{Type: "appl", Sender: addrs[0],
+ ApprovalProgram: doubleSrc, ApplicationArgs: [][]byte{{0x01}, {0x02}},
+ Boxes: []transactions.BoxRef{{}}},
+ "invalid Box reference 0x02")
- // until you add a second box ref
- dl.txn(&txntest.Txn{Type: "appl", Sender: addrs[0],
- ApprovalProgram: doubleSrc, ApplicationArgs: [][]byte{{0x01}, {0x02}},
- Boxes: []transactions.BoxRef{{}, {}}})
-
- // Now confirm that 2c also works for an inner created app
- ops, err := logic.AssembleString("#pragma version 12\n" + createSrc)
- require.NoError(t, err, ops.Errors)
- createSrcByteCode := ops.Program
- // create app as an inner, fails w/o empty box ref
- dl.txn(&txntest.Txn{Sender: addrs[0],
- Type: "appl",
- ApplicationID: passID,
- ApplicationArgs: [][]byte{createSrcByteCode, {0x01}},
- }, "invalid Box reference 0x01")
- // create app as an inner, succeeds w/ empty box ref
- dl.txn(&txntest.Txn{Sender: addrs[0],
- Type: "appl",
- ApplicationID: passID,
- ApplicationArgs: [][]byte{createSrcByteCode, {0x01}},
- Boxes: []transactions.BoxRef{{}},
- })
- } else {
- // 2c. Doesn't work yet until `newAppCreateVersion`
- dl.txn(&txntest.Txn{Type: "appl", Sender: addrs[0],
- ApprovalProgram: createSrcVer, ApplicationArgs: [][]byte{{0x01}},
- Boxes: []transactions.BoxRef{{}}},
- "invalid Box reference 0x01")
- }
+ // until you add a second box ref
+ dl.txn(&txntest.Txn{Type: "appl", Sender: addrs[0],
+ ApprovalProgram: doubleSrc, ApplicationArgs: [][]byte{{0x01}, {0x02}},
+ Boxes: []transactions.BoxRef{{}, {}}})
+
+ // Now confirm that 2c also works for an inner created app
+ ops, err := logic.AssembleString("#pragma version 8\n" + createSrc)
+ require.NoError(t, err, ops.Errors)
+ createSrcByteCode := ops.Program
+ // create app as an inner, fails w/o empty box ref
+ dl.txn(&txntest.Txn{Sender: addrs[0],
+ Type: "appl",
+ ApplicationID: passID,
+ ApplicationArgs: [][]byte{createSrcByteCode, {0x01}},
+ }, "invalid Box reference 0x01")
+ // create app as an inner, succeeds w/ empty box ref
+ dl.txn(&txntest.Txn{Sender: addrs[0],
+ Type: "appl",
+ ApplicationID: passID,
+ ApplicationArgs: [][]byte{createSrcByteCode, {0x01}},
+ Boxes: []transactions.BoxRef{{}},
+ })
}
})
}
diff --git a/ledger/bulletin.go b/ledger/bulletin.go
index 64d360e8b3..39a7818851 100644
--- a/ledger/bulletin.go
+++ b/ledger/bulletin.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/bulletin_test.go b/ledger/bulletin_test.go
index 0b3348481e..d5ecaa8558 100644
--- a/ledger/bulletin_test.go
+++ b/ledger/bulletin_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/catchpointfileheader.go b/ledger/catchpointfileheader.go
index be1e82c205..2011e05704 100644
--- a/ledger/catchpointfileheader.go
+++ b/ledger/catchpointfileheader.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/catchpointfilewriter.go b/ledger/catchpointfilewriter.go
index 7daf0f86bc..7502f8f59b 100644
--- a/ledger/catchpointfilewriter.go
+++ b/ledger/catchpointfilewriter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -483,7 +483,7 @@ type catchpointOnlineAccountsIterWrapper struct {
params config.ConsensusParams
}
-// makeCatchpointOrderedOnlineAccountsIter wraps the MakeOrderedOnlineAccountsIter iterator to deterministically set
+// makeCatchpointOrderedOnlineAccountsIterFactory wraps the MakeOrderedOnlineAccountsIter iterator to deterministically set
// the UpdateRound number to zero for online accounts beyond the "horizon" of online history of 320 rounds (defined by
// MaxBalLookback).
func makeCatchpointOrderedOnlineAccountsIterFactory(
diff --git a/ledger/catchpointfilewriter_test.go b/ledger/catchpointfilewriter_test.go
index c7f786a60d..b534995eb7 100644
--- a/ledger/catchpointfilewriter_test.go
+++ b/ledger/catchpointfilewriter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/catchpointtracker.go b/ledger/catchpointtracker.go
index bd98d6dffc..d95d299ea6 100644
--- a/ledger/catchpointtracker.go
+++ b/ledger/catchpointtracker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/catchpointtracker_test.go b/ledger/catchpointtracker_test.go
index 9f8df68b7c..2b5c814590 100644
--- a/ledger/catchpointtracker_test.go
+++ b/ledger/catchpointtracker_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -1882,7 +1882,7 @@ func TestHashContract(t *testing.T) {
}
}
-// TestCatchpoint_FastUpdates tests catchpoint label writing data race
+// TestCatchpointFastUpdates tests catchpoint label writing data race
func TestCatchpointFastUpdates(t *testing.T) {
partitiontest.PartitionTest(t)
@@ -1978,7 +1978,7 @@ func TestCatchpointFastUpdates(t *testing.T) {
require.NotEmpty(t, ct.GetLastCatchpointLabel())
}
-// TestCatchpoint_LargeAccountCountCatchpointGeneration creates a ledger containing a large set of accounts ( i.e. 100K accounts )
+// TestCatchpointLargeAccountCountCatchpointGeneration creates a ledger containing a large set of accounts ( i.e. 100K accounts )
// and attempts to have the catchpoint tracker create the associated catchpoint. It's designed precisely around setting an
// environment which would quickly ( i.e. after 32 rounds ) would start producing catchpoints.
func TestCatchpointLargeAccountCountCatchpointGeneration(t *testing.T) {
diff --git a/ledger/catchupaccessor.go b/ledger/catchupaccessor.go
index e42cfc1a9b..5000426433 100644
--- a/ledger/catchupaccessor.go
+++ b/ledger/catchupaccessor.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/catchupaccessor_test.go b/ledger/catchupaccessor_test.go
index 9e9971f83b..87cb32aed8 100644
--- a/ledger/catchupaccessor_test.go
+++ b/ledger/catchupaccessor_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/double_test.go b/ledger/double_test.go
index 151f1dda2a..728d4e65c6 100644
--- a/ledger/double_test.go
+++ b/ledger/double_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -157,14 +157,24 @@ func (dl *DoubleLedger) endBlock(proposer ...basics.Address) *ledgercore.Validat
return vb
}
-func (dl *DoubleLedger) createApp(sender basics.Address, source string) basics.AppIndex {
+func (dl *DoubleLedger) createApp(sender basics.Address, source string, schemas ...basics.StateSchema) basics.AppIndex {
createapp := txntest.Txn{
Type: "appl",
Sender: sender,
ApprovalProgram: source,
}
+ switch len(schemas) {
+ case 0:
+ case 1:
+ createapp.GlobalStateSchema = schemas[0]
+ case 2:
+ createapp.GlobalStateSchema = schemas[0]
+ createapp.LocalStateSchema = schemas[1]
+ }
vb := dl.fullBlock(&createapp)
- return vb.Block().Payset[0].ApplyData.ApplicationID
+ return basics.AppIndex(vb.Block().BlockHeader.TxnCounter)
+ // The following only works for v30 and above, when we start recording the id in AD.
+ // return vb.Block().Payset[0].ApplyData.ApplicationID
}
func (dl *DoubleLedger) fundedApp(sender basics.Address, amount uint64, source string) basics.AppIndex {
diff --git a/ledger/encoded/msgp_gen.go b/ledger/encoded/msgp_gen.go
index 129a37aa7a..07518c2924 100644
--- a/ledger/encoded/msgp_gen.go
+++ b/ledger/encoded/msgp_gen.go
@@ -1,7 +1,7 @@
-package encoded
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package encoded
+
import (
"sort"
@@ -199,7 +199,7 @@ func (z *BalanceRecordV5) MsgIsZero() bool {
return ((*z).Address.MsgIsZero()) && ((*z).AccountData.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// BalanceRecordV5MaxSize returns a maximum valid message size for this message type
func BalanceRecordV5MaxSize() (s int) {
s = 1 + 3 + basics.AddressMaxSize() + 3
panic("Unable to determine max size: MaxSize() not implemented for Raw type")
@@ -467,7 +467,7 @@ func (z *BalanceRecordV6) MsgIsZero() bool {
return ((*z).Address.MsgIsZero()) && ((*z).AccountData.MsgIsZero()) && (len((*z).Resources) == 0) && ((*z).ExpectingMoreEntries == false)
}
-// MaxSize returns a maximum valid message size for this message type
+// BalanceRecordV6MaxSize returns a maximum valid message size for this message type
func BalanceRecordV6MaxSize() (s int) {
s = 1 + 2 + basics.AddressMaxSize() + 2
panic("Unable to determine max size: MaxSize() not implemented for Raw type")
@@ -650,7 +650,7 @@ func (z *KVRecordV6) MsgIsZero() bool {
return (len((*z).Key) == 0) && (len((*z).Value) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// KVRecordV6MaxSize returns a maximum valid message size for this message type
func KVRecordV6MaxSize() (s int) {
s = 1 + 2 + msgp.BytesPrefixSize + KVRecordV6MaxKeyLength + 2 + msgp.BytesPrefixSize + KVRecordV6MaxValueLength
return
@@ -862,7 +862,7 @@ func (z *OnlineAccountRecordV6) MsgIsZero() bool {
return ((*z).Address.MsgIsZero()) && ((*z).UpdateRound.MsgIsZero()) && ((*z).NormalizedOnlineBalance == 0) && ((*z).VoteLastValid.MsgIsZero()) && ((*z).Data.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// OnlineAccountRecordV6MaxSize returns a maximum valid message size for this message type
func OnlineAccountRecordV6MaxSize() (s int) {
s = 1 + 5 + basics.AddressMaxSize() + 4 + basics.RoundMaxSize() + 4 + msgp.Uint64Size + 4 + basics.RoundMaxSize() + 5
panic("Unable to determine max size: MaxSize() not implemented for Raw type")
@@ -1005,7 +1005,7 @@ func (z *OnlineRoundParamsRecordV6) MsgIsZero() bool {
return ((*z).Round.MsgIsZero()) && ((*z).Data.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// OnlineRoundParamsRecordV6MaxSize returns a maximum valid message size for this message type
func OnlineRoundParamsRecordV6MaxSize() (s int) {
s = 1 + 4 + basics.RoundMaxSize() + 5
panic("Unable to determine max size: MaxSize() not implemented for Raw type")
diff --git a/ledger/encoded/msgp_gen_test.go b/ledger/encoded/msgp_gen_test.go
index b905d9616e..0400e1c118 100644
--- a/ledger/encoded/msgp_gen_test.go
+++ b/ledger/encoded/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package encoded
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package encoded
+
import (
"testing"
diff --git a/ledger/encoded/recordsV5.go b/ledger/encoded/recordsV5.go
index 00bb202c99..12c133c251 100644
--- a/ledger/encoded/recordsV5.go
+++ b/ledger/encoded/recordsV5.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/encoded/recordsV6.go b/ledger/encoded/recordsV6.go
index 06b38f1e86..12df070e64 100644
--- a/ledger/encoded/recordsV6.go
+++ b/ledger/encoded/recordsV6.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/encoded/recordsV6_test.go b/ledger/encoded/recordsV6_test.go
index 11122ba983..42fb6c2e55 100644
--- a/ledger/encoded/recordsV6_test.go
+++ b/ledger/encoded/recordsV6_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval/appcow.go b/ledger/eval/appcow.go
index c64cc1a939..b3609a0d55 100644
--- a/ledger/eval/appcow.go
+++ b/ledger/eval/appcow.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -151,6 +151,19 @@ func (cb *roundCowState) ensureStorageDelta(addr basics.Address, aidx basics.App
return lsd, nil
}
+// SetAppGlobalSchema sets the maximum allowed counts for app globals. It can
+// be changed during evaluation by an app update.
+func (cb *roundCowState) SetAppGlobalSchema(addr basics.Address, aidx basics.AppIndex, limits basics.StateSchema) error {
+ // Obtain a storageDelta to record the schema change
+ lsd, err := cb.ensureStorageDelta(addr, aidx, true, remainAllocAction, 0)
+ if err != nil {
+ return err
+ }
+
+ lsd.maxCounts = limits
+ return lsd.checkCounts()
+}
+
// getStorageCounts returns current storage usage for a given {addr, aidx, global} as basics.StateSchema
func (cb *roundCowState) getStorageCounts(addr basics.Address, aidx basics.AppIndex, global bool) (basics.StateSchema, error) {
// If we haven't allocated storage, then our used storage count is zero
@@ -226,7 +239,7 @@ func errAlreadyStorage(addr basics.Address, aidx basics.AppIndex, global bool) e
return fmt.Errorf("%v has already opted in to app %d", addr, aidx)
}
-// Allocate creates kv storage for a given {addr, aidx, global}. It is called on app creation (global) or opting in (local)
+// AllocateApp creates kv storage for a given {addr, aidx, global}. It is called on app creation (global) or opting in (local)
func (cb *roundCowState) AllocateApp(addr basics.Address, aidx basics.AppIndex, global bool, space basics.StateSchema) error {
// Check that account is not already opted in
allocated, err := cb.allocated(addr, aidx, global)
@@ -256,7 +269,7 @@ func (cb *roundCowState) AllocateApp(addr basics.Address, aidx basics.AppIndex,
return nil
}
-// Deallocate clears storage for {addr, aidx, global}. It happens on app deletion (global) or closing out (local)
+// DeallocateApp clears storage for {addr, aidx, global}. It happens on app deletion (global) or closing out (local)
func (cb *roundCowState) DeallocateApp(addr basics.Address, aidx basics.AppIndex, global bool) error {
// Check that account has allocated storage
allocated, err := cb.allocated(addr, aidx, global)
@@ -600,33 +613,29 @@ func (lsd *storageDelta) applyChild(child *storageDelta) {
// completely overwrite those of the parent.
lsd.action = child.action
lsd.kvCow = child.kvCow
- lsd.counts = child.counts
- lsd.maxCounts = child.maxCounts
} else {
- // Otherwise, the child's deltas get merged with those of the
- // parent, and we keep whatever the parent's state was.
- for key := range child.kvCow {
+ // Otherwise, the child's new values get merged into the delta of the
+ // parent, but we keep the parent's old/oldExists values.
+ for key, childVal := range child.kvCow {
delta, ok := lsd.kvCow[key]
if !ok {
- lsd.kvCow[key] = child.kvCow[key]
+ lsd.kvCow[key] = childVal
continue
}
- delta.new = child.kvCow[key].new
- delta.newExists = child.kvCow[key].newExists
+ delta.new = childVal.new
+ delta.newExists = childVal.newExists
lsd.kvCow[key] = delta
}
-
- // counts can just get overwritten because they are absolute
- // see ensureStorageDelta: child.counts is initialized from parent cow
- lsd.counts = child.counts
}
+ // counts can just get overwritten because they are absolute
+ // see ensureStorageDelta: counts are initialized from parent cow
+ lsd.counts = child.counts // propagate addition/deletion of globals
+ lsd.maxCounts = child.maxCounts // propagate updates to global schema
// sanity checks
- if lsd.action == deallocAction {
- if len(lsd.kvCow) > 0 {
- panic("dealloc state delta, but nonzero kv change")
- }
+ if lsd.action == deallocAction && len(lsd.kvCow) > 0 {
+ panic("dealloc state delta, but nonzero kv change")
}
}
diff --git a/ledger/eval/appcow_test.go b/ledger/eval/appcow_test.go
index e94b08a0e4..8935673621 100644
--- a/ledger/eval/appcow_test.go
+++ b/ledger/eval/appcow_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval/applications.go b/ledger/eval/applications.go
index 85a5ad4ab7..08dd68e587 100644
--- a/ledger/eval/applications.go
+++ b/ledger/eval/applications.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval/assetcow.go b/ledger/eval/assetcow.go
index c64710e133..b24a79ec98 100644
--- a/ledger/eval/assetcow.go
+++ b/ledger/eval/assetcow.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval/cow.go b/ledger/eval/cow.go
index 382ff9d25d..23a363a141 100644
--- a/ledger/eval/cow.go
+++ b/ledger/eval/cow.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval/cow_creatables.go b/ledger/eval/cow_creatables.go
index daed36592e..6e109117cd 100644
--- a/ledger/eval/cow_creatables.go
+++ b/ledger/eval/cow_creatables.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -91,7 +91,7 @@ func (cs *roundCowState) GetAssetParams(addr basics.Address, aidx basics.AssetIn
return
}
if d.Params == nil {
- // found and not deleled => must exist. Err if not
+ // found and not deleted => must exist. Err if not
err = fmt.Errorf("GetAppLocalState got a nil entry for (%s, %d): %p, %v", addr.String(), aidx, d.Params, d.Deleted)
}
ret = *d.Params
diff --git a/ledger/eval/cow_test.go b/ledger/eval/cow_test.go
index a3af28b1ec..a45ba3645c 100644
--- a/ledger/eval/cow_test.go
+++ b/ledger/eval/cow_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval/eval.go b/ledger/eval/eval.go
index 6016eae39d..5c44073e0a 100644
--- a/ledger/eval/eval.go
+++ b/ledger/eval/eval.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -70,7 +70,7 @@ var ErrNotInCowCache = errors.New("can't find object in cow cache")
// is considerably slower.
const averageEncodedTxnSizeHint = 150
-// Creatable represent a single creatable object.
+// creatable represent a single creatable object.
type creatable struct {
cindex basics.CreatableIndex
ctype basics.CreatableType
@@ -470,13 +470,8 @@ func (x *roundCowBase) getKey(addr basics.Address, aidx basics.AppIndex, global
// getStorageCounts counts the storage types used by some account
// associated with an application globally or locally
func (x *roundCowBase) getStorageCounts(addr basics.Address, aidx basics.AppIndex, global bool) (basics.StateSchema, error) {
- var err error
- count := basics.StateSchema{}
- exist := false
- kv := basics.TealKeyValue{}
if global {
- var app ledgercore.AppParamsDelta
- app, exist, err = x.lookupAppParams(addr, aidx, false)
+ app, exist, err := x.lookupAppParams(addr, aidx, false)
if err != nil {
return basics.StateSchema{}, err
}
@@ -484,11 +479,10 @@ func (x *roundCowBase) getStorageCounts(addr basics.Address, aidx basics.AppInde
return basics.StateSchema{}, fmt.Errorf("getStorageCounts: lookupAppParams returned deleted entry for (%s, %d, %v)", addr.String(), aidx, global)
}
if exist {
- kv = app.Params.GlobalState
+ return app.Params.GlobalState.ToStateSchema()
}
} else {
- var ls ledgercore.AppLocalStateDelta
- ls, exist, err = x.lookupAppLocalState(addr, aidx, false)
+ ls, exist, err := x.lookupAppLocalState(addr, aidx, false)
if err != nil {
return basics.StateSchema{}, err
}
@@ -496,21 +490,10 @@ func (x *roundCowBase) getStorageCounts(addr basics.Address, aidx basics.AppInde
return basics.StateSchema{}, fmt.Errorf("getStorageCounts: lookupAppLocalState returned deleted entry for (%s, %d, %v)", addr.String(), aidx, global)
}
if exist {
- kv = ls.LocalState.KeyValue
- }
- }
- if !exist {
- return count, nil
- }
-
- for _, v := range kv {
- if v.Type == basics.TealUintType {
- count.NumUint++
- } else {
- count.NumByteSlice++
+ return ls.LocalState.KeyValue.ToStateSchema()
}
}
- return count, nil
+ return basics.StateSchema{}, nil
}
func (x *roundCowBase) getStorageLimits(addr basics.Address, aidx basics.AppIndex, global bool) (basics.StateSchema, error) {
@@ -604,7 +587,11 @@ func (cs *roundCowState) Move(from basics.Address, to basics.Address, amt basics
var overflowed bool
fromBalNew.MicroAlgos, overflowed = basics.OSubA(fromBalNew.MicroAlgos, amt)
if overflowed {
- return fmt.Errorf("overspend (account %v, data %+v, tried to spend %v)", from, fromBal, amt)
+ return &ledgercore.OverspendError{
+ Account: from,
+ Data: fromBal,
+ Tried: amt,
+ }
}
fromBalNew = cs.autoHeartbeat(fromBal, fromBalNew)
err = cs.putAccount(from, fromBalNew)
@@ -949,7 +936,7 @@ func (eval *BlockEvaluator) TestTransactionGroup(txgroup []transactions.SignedTx
var group transactions.TxGroup
for gi, txn := range txgroup {
- err := eval.TestTransaction(txn)
+ err := eval.testTransaction(txn)
if err != nil {
return err
}
@@ -990,10 +977,10 @@ func (eval *BlockEvaluator) TestTransactionGroup(txgroup []transactions.SignedTx
return nil
}
-// TestTransaction performs basic duplicate detection and well-formedness checks
+// testTransaction performs basic duplicate detection and well-formedness checks
// on a single transaction, but does not actually add the transaction to the block
// evaluator, or modify the block evaluator state in any other visible way.
-func (eval *BlockEvaluator) TestTransaction(txn transactions.SignedTxn) error {
+func (eval *BlockEvaluator) testTransaction(txn transactions.SignedTxn) error {
// Transaction valid (not expired)?
err := eval.block.Alive(txn.Txn.Header)
if err != nil {
@@ -1016,22 +1003,10 @@ func (eval *BlockEvaluator) TestTransaction(txn transactions.SignedTxn) error {
return nil
}
-// Transaction tentatively adds a new transaction as part of this block evaluation.
-// If the transaction cannot be added to the block without violating some constraints,
-// an error is returned and the block evaluator state is unchanged.
-func (eval *BlockEvaluator) Transaction(txn transactions.SignedTxn, ad transactions.ApplyData) error {
- return eval.TransactionGroup([]transactions.SignedTxnWithAD{
- {
- SignedTxn: txn,
- ApplyData: ad,
- },
- })
-}
-
// TransactionGroup tentatively adds a new transaction group as part of this block evaluation.
// If the transaction group cannot be added to the block without violating some constraints,
// an error is returned and the block evaluator state is unchanged.
-func (eval *BlockEvaluator) TransactionGroup(txgroup []transactions.SignedTxnWithAD) (err error) {
+func (eval *BlockEvaluator) TransactionGroup(txgroup ...transactions.SignedTxnWithAD) (err error) {
// Nothing to do if there are no transactions.
if len(txgroup) == 0 {
return nil
@@ -1159,8 +1134,12 @@ func (eval *BlockEvaluator) checkMinBalance(cow *roundCowState) error {
dataNew := data.WithUpdatedRewards(eval.proto.RewardUnit, rewardlvl)
effectiveMinBalance := dataNew.MinBalance(&eval.proto)
if dataNew.MicroAlgos.Raw < effectiveMinBalance.Raw {
- return fmt.Errorf("account %v balance %d below min %d (%d assets)",
- addr, dataNew.MicroAlgos.Raw, effectiveMinBalance.Raw, dataNew.TotalAssets)
+ return &ledgercore.MinBalanceError{
+ Account: addr,
+ Balance: dataNew.MicroAlgos.Raw,
+ MinBalance: effectiveMinBalance.Raw,
+ TotalAssets: dataNew.TotalAssets,
+ }
}
// Check if we have exceeded the maximum minimum balance
@@ -2185,7 +2164,7 @@ transactionGroupLoop:
}
}
}
- err = eval.TransactionGroup(txgroup.TxnGroup)
+ err = eval.TransactionGroup(txgroup.TxnGroup...)
if err != nil {
return ledgercore.StateDelta{}, err
}
diff --git a/ledger/eval/eval_test.go b/ledger/eval/eval_test.go
index fe44c0a6aa..37417f90d2 100644
--- a/ledger/eval/eval_test.go
+++ b/ledger/eval/eval_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -165,7 +165,7 @@ ok:
if err != nil {
return eval, addrs[0], err
}
- err = eval.TransactionGroup(g)
+ err = eval.TransactionGroup(g...)
return eval, addrs[0], err
}
@@ -221,12 +221,12 @@ func TestPrivateTransactionGroup(t *testing.T) {
var txgroup []transactions.SignedTxnWithAD
eval := BlockEvaluator{}
- err := eval.TransactionGroup(txgroup)
+ err := eval.TransactionGroup(txgroup...)
require.NoError(t, err) // nothing to do, no problem
eval.proto = config.Consensus[protocol.ConsensusCurrentVersion]
txgroup = make([]transactions.SignedTxnWithAD, eval.proto.MaxTxGroupSize+1)
- err = eval.TransactionGroup(txgroup)
+ err = eval.TransactionGroup(txgroup...)
require.ErrorContains(t, err, "group size")
}
@@ -399,7 +399,7 @@ int 1`,
require.Len(t, eval.block.Payset, 0)
- err = eval.TransactionGroup(txgroup)
+ err = eval.TransactionGroup(txgroup...)
switch testCase.firstTxnBehavior {
case "approve":
if len(scenario.ExpectedError) != 0 {
@@ -666,7 +666,7 @@ func testnetFixupExecution(t *testing.T, headerRound basics.Round, poolBonus uin
},
}
st := txn.Sign(keys[0])
- err = eval.Transaction(st, transactions.ApplyData{})
+ err = eval.TransactionGroup(st.WithAD())
require.NoError(t, err)
poolOld, err := eval.workaroundOverspentRewards(rewardPoolBalance, headerRound)
@@ -857,7 +857,7 @@ func (ledger *evalTestLedger) GenesisProto() config.ConsensusParams {
return config.Consensus[ledger.genesisProtoVersion]
}
-// GenesisProto returns the genesis consensus version for this ledger.
+// GenesisProtoVersion returns the genesis consensus version for this ledger.
func (ledger *evalTestLedger) GenesisProtoVersion() protocol.ConsensusVersion {
return ledger.genesisProtoVersion
}
@@ -1420,12 +1420,11 @@ func TestAbsenteeChecks(t *testing.T) {
return pay(i, addrs[i]).Sign(keys[i])
}
- require.NoError(t, blkEval.Transaction(selfpay(0), transactions.ApplyData{}))
- require.NoError(t, blkEval.Transaction(selfpay(1), transactions.ApplyData{}))
- require.NoError(t, blkEval.Transaction(selfpay(2), transactions.ApplyData{}))
+ require.NoError(t, blkEval.TransactionGroup(selfpay(0).WithAD()))
+ require.NoError(t, blkEval.TransactionGroup(selfpay(1).WithAD()))
+ require.NoError(t, blkEval.TransactionGroup(selfpay(2).WithAD()))
for i := 0; i < 32; i++ {
- require.NoError(t, blkEval.Transaction(pay(0, basics.Address{byte(i << 3), 0xaa}).Sign(keys[0]),
- transactions.ApplyData{}))
+ require.NoError(t, blkEval.TransactionGroup(pay(0, basics.Address{byte(i << 3), 0xaa}).Sign(keys[0]).WithAD()))
}
// Make sure we validate our block as well
diff --git a/ledger/eval/evalindexer.go b/ledger/eval/evalindexer.go
index 1d2b217922..648b000097 100644
--- a/ledger/eval/evalindexer.go
+++ b/ledger/eval/evalindexer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -33,7 +33,7 @@ func (eval *BlockEvaluator) ProcessBlockForIndexer(block *bookkeeping.Block) (le
}
for _, group := range paysetgroups {
- err = eval.TransactionGroup(group)
+ err = eval.TransactionGroup(group...)
if err != nil {
return ledgercore.StateDelta{}, []transactions.SignedTxnInBlock{},
fmt.Errorf("ProcessBlockForIndexer() err: %w", err)
diff --git a/ledger/eval/prefetcher/error.go b/ledger/eval/prefetcher/error.go
index 0e2d3a4850..9525525e2a 100644
--- a/ledger/eval/prefetcher/error.go
+++ b/ledger/eval/prefetcher/error.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval/prefetcher/prefetcher.go b/ledger/eval/prefetcher/prefetcher.go
index 2ed9a38894..891611ffc6 100644
--- a/ledger/eval/prefetcher/prefetcher.go
+++ b/ledger/eval/prefetcher/prefetcher.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval/prefetcher/prefetcher_alignment_test.go b/ledger/eval/prefetcher/prefetcher_alignment_test.go
index 8344ddb269..433f518172 100644
--- a/ledger/eval/prefetcher/prefetcher_alignment_test.go
+++ b/ledger/eval/prefetcher/prefetcher_alignment_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -331,7 +331,7 @@ func runEval(t *testing.T, l *prefetcherAlignmentTestLedger, txn transactions.Tr
eval, err := eval.StartEvaluator(l, block.BlockHeader, eval.EvaluatorOptions{})
require.NoError(t, err)
- err = eval.TransactionGroup(makeGroupFromTxn(txn))
+ err = eval.TransactionGroup(makeGroupFromTxn(txn)...)
require.NoError(t, err)
}
diff --git a/ledger/eval/prefetcher/prefetcher_test.go b/ledger/eval/prefetcher/prefetcher_test.go
index b47cd7648a..cd7c7f27b2 100644
--- a/ledger/eval/prefetcher/prefetcher_test.go
+++ b/ledger/eval/prefetcher/prefetcher_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval/prefetcher/prefetcher_whitebox_test.go b/ledger/eval/prefetcher/prefetcher_whitebox_test.go
index 28d1371010..bf18164091 100644
--- a/ledger/eval/prefetcher/prefetcher_whitebox_test.go
+++ b/ledger/eval/prefetcher/prefetcher_whitebox_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval/txntracer.go b/ledger/eval/txntracer.go
index 1a94850f89..500577a4f9 100644
--- a/ledger/eval/txntracer.go
+++ b/ledger/eval/txntracer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/eval/txntracer_test.go b/ledger/eval/txntracer_test.go
index ca00414dba..e97664bc53 100644
--- a/ledger/eval/txntracer_test.go
+++ b/ledger/eval/txntracer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -212,7 +212,7 @@ int 1`
require.Len(t, eval.block.Payset, 0)
- err = eval.TransactionGroup(txgroup)
+ err = eval.TransactionGroup(txgroup...)
require.NoError(t, err)
require.Len(t, eval.block.Payset, 4)
@@ -226,10 +226,7 @@ int 1`
Fee: minFee,
GenesisHash: genHash,
}
- secondTxGroup := transactions.WrapSignedTxnsWithAD([]transactions.SignedTxn{
- secondPayTxn.Txn().Sign(keys[2]),
- })
- err = eval.TransactionGroup(secondTxGroup)
+ err = eval.TransactionGroup(secondPayTxn.Txn().Sign(keys[2]).WithAD())
require.NoError(t, err)
// Calculate expected balances dynamically based on proto.MinTxnFee
diff --git a/ledger/eval_simple_test.go b/ledger/eval_simple_test.go
index cb650bfe56..45566a8a02 100644
--- a/ledger/eval_simple_test.go
+++ b/ledger/eval_simple_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -79,7 +79,7 @@ func TestBlockEvaluator(t *testing.T) {
// Correct signature should work
st := txn.Sign(keys[0])
- err = eval.Transaction(st, transactions.ApplyData{})
+ err = eval.TransactionGroup(st.WithAD())
require.NoError(t, err)
// Broken signature should fail
@@ -93,7 +93,7 @@ func TestBlockEvaluator(t *testing.T) {
txgroup = []transactions.SignedTxn{st}
err = eval.TestTransactionGroup(txgroup)
require.Error(t, err)
- err = eval.Transaction(st, transactions.ApplyData{})
+ err = eval.TransactionGroup(st.WithAD())
require.Error(t, err)
// out of range should fail
@@ -104,7 +104,7 @@ func TestBlockEvaluator(t *testing.T) {
txgroup = []transactions.SignedTxn{st}
err = eval.TestTransactionGroup(txgroup)
require.Error(t, err)
- err = eval.Transaction(st, transactions.ApplyData{})
+ err = eval.TransactionGroup(st.WithAD())
require.Error(t, err)
// bogus group should fail
@@ -114,7 +114,7 @@ func TestBlockEvaluator(t *testing.T) {
txgroup = []transactions.SignedTxn{st}
err = eval.TestTransactionGroup(txgroup)
require.Error(t, err)
- err = eval.Transaction(st, transactions.ApplyData{})
+ err = eval.TransactionGroup(st.WithAD())
require.Error(t, err)
// mixed fields should fail
@@ -149,7 +149,7 @@ func TestBlockEvaluator(t *testing.T) {
err = eval.TestTransactionGroup(txgroup)
require.NoError(t, err)
- err = eval.Transaction(stxn, transactions.ApplyData{})
+ err = eval.TransactionGroup(stxn.WithAD())
require.NoError(t, err)
t3 := txn
@@ -164,7 +164,7 @@ func TestBlockEvaluator(t *testing.T) {
err = eval.TestTransactionGroup(txgroup)
require.Error(t, err)
txgroupad := transactions.WrapSignedTxnsWithAD(txgroup)
- err = eval.TransactionGroup(txgroupad)
+ err = eval.TransactionGroup(txgroupad...)
require.Error(t, err)
// Test a group that should work
@@ -186,7 +186,7 @@ func TestBlockEvaluator(t *testing.T) {
err = eval.TestTransactionGroup(txgroup)
require.Error(t, err)
txgroupad = transactions.WrapSignedTxnsWithAD(txgroup)
- err = eval.TransactionGroup(txgroupad)
+ err = eval.TransactionGroup(txgroupad...)
require.Error(t, err)
// missing part of the group should fail
@@ -1290,7 +1290,7 @@ func TestRekeying(t *testing.T) {
require.NoError(t, err)
for _, stxn := range stxns {
- err = eval.Transaction(stxn, transactions.ApplyData{})
+ err = eval.TransactionGroup(stxn.WithAD())
if err != nil {
return err
}
@@ -1358,13 +1358,13 @@ func testEvalAppPoolingGroup(t *testing.T, schema basics.StateSchema, approvalPr
appcall2 := txntest.Txn{
Sender: addrs[0],
Type: protocol.ApplicationCallTx,
- ApplicationID: basics.AppIndex(1),
+ ApplicationID: 1,
}
appcall3 := txntest.Txn{
Sender: addrs[1],
Type: protocol.ApplicationCallTx,
- ApplicationID: basics.AppIndex(1),
+ ApplicationID: 1,
}
return txgroup(t, l, eval, &appcall1, &appcall2, &appcall3)
diff --git a/ledger/evalbench_test.go b/ledger/evalbench_test.go
index a9cc6d4fad..acd855d6b4 100644
--- a/ledger/evalbench_test.go
+++ b/ledger/evalbench_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -520,7 +520,7 @@ func benchmarkPreparePaymentTransactionsTesting(b *testing.B, numTxns int, txnSo
// there might be more transactions than MaxTxnBytesPerBlock allows so
// make smaller blocks to fit
for i, stxn := range initSignedTxns {
- err := bev.Transaction(stxn, transactions.ApplyData{})
+ err := bev.TransactionGroup(stxn.WithAD())
require.NoError(b, err)
if maxTxnPerBlock > 0 && i%maxTxnPerBlock == 0 || i == len(initSignedTxns)-1 {
unfinishedBlock, err = bev.GenerateBlock(nil)
@@ -564,7 +564,7 @@ func benchmarkPreparePaymentTransactionsTesting(b *testing.B, numTxns int, txnSo
for i := 0; i < numTxns; i++ {
stxn := txnSource.Txn(b, addrs, keys, newBlock.Round(), genHash)
- err = bev.Transaction(stxn, transactions.ApplyData{})
+ err = bev.TransactionGroup(stxn.WithAD())
require.NoError(b, err)
}
diff --git a/ledger/fullblock_perf_test.go b/ledger/fullblock_perf_test.go
index b2c86c20f8..c596b46105 100644
--- a/ledger/fullblock_perf_test.go
+++ b/ledger/fullblock_perf_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -302,7 +302,7 @@ func addNewAccount(bc *benchConfig) (acct basics.Address) {
}
func addTransaction(bc *benchConfig, stxn transactions.SignedTxn) uint64 {
- err := bc.eval.Transaction(stxn, transactions.ApplyData{})
+ err := bc.eval.TransactionGroup(stxn.WithAD())
if err == ledgercore.ErrNoSpace {
addBlock(bc)
addTransaction(bc, stxn)
diff --git a/ledger/ledger.go b/ledger/ledger.go
index 908548a0b2..e1c962129f 100644
--- a/ledger/ledger.go
+++ b/ledger/ledger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledger_perf_test.go b/ledger/ledger_perf_test.go
index 80ecbf227f..754b8319da 100644
--- a/ledger/ledger_perf_test.go
+++ b/ledger/ledger_perf_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -256,7 +256,7 @@ func benchmarkFullBlocks(params testParams, b *testing.B) {
var stxn transactions.SignedTxn
stxn.Txn = tx
stxn.Sig = crypto.Signature{1}
- err = eval.Transaction(stxn, transactions.ApplyData{})
+ err = eval.TransactionGroup(stxn.WithAD())
}
@@ -287,7 +287,7 @@ func benchmarkFullBlocks(params testParams, b *testing.B) {
var stxn transactions.SignedTxn
stxn.Txn = tx
stxn.Sig = crypto.Signature{1}
- err = eval.Transaction(stxn, transactions.ApplyData{})
+ err = eval.TransactionGroup(stxn.WithAD())
require.NoError(b, err)
}
break
diff --git a/ledger/ledger_test.go b/ledger/ledger_test.go
index 3249efc50a..55b28c4e3c 100644
--- a/ledger/ledger_test.go
+++ b/ledger/ledger_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -1514,10 +1514,6 @@ func benchLedgerCache(b *testing.B, startRound basics.Round) {
// triggerTrackerFlush is based in the commit flow but executed it in a single (this) goroutine.
func triggerTrackerFlush(t *testing.T, l *Ledger) {
- l.trackers.mu.Lock()
- dbRound := l.trackers.dbRound
- l.trackers.mu.Unlock()
-
rnd := l.Latest()
minBlock := rnd
maxLookback := basics.Round(0)
@@ -1538,6 +1534,7 @@ func triggerTrackerFlush(t *testing.T, l *Ledger) {
}
l.trackers.mu.RLock()
+ dbRound := l.trackers.dbRound
cdr := l.trackers.produceCommittingTask(rnd, dbRound, &dcc.deferredCommitRange)
if cdr != nil {
dcc.deferredCommitRange = *cdr
@@ -2551,7 +2548,7 @@ func TestLedgerMigrateV6ShrinkDeltas(t *testing.T) {
onlineTotals := make([]basics.MicroAlgos, maxBlocks+1)
curAddressIdx := 0
- maxValidity := basics.Round(20) // some number different from number of txns in blocks
+ const maxValidity = basics.Round(20) // some number different from number of txns in blocks
txnIDs := make(map[basics.Round]map[transactions.Txid]struct{})
// run for maxBlocks rounds with random payment transactions
// generate numTxns txn per block
@@ -2624,6 +2621,8 @@ func TestLedgerMigrateV6ShrinkDeltas(t *testing.T) {
require.NoError(t, err)
}
+ triggerTrackerFlush(t, l)
+
latest := l.Latest()
nextRound := latest + 1
balancesRound := nextRound.SubSaturate(basics.Round(proto.MaxBalLookback))
@@ -2670,7 +2669,13 @@ func TestLedgerMigrateV6ShrinkDeltas(t *testing.T) {
// check an error latest-1
for txid := range txnIDs[latest-1] {
- require.Error(t, l.CheckDup(proto, nextRound, latest-maxValidity, latest-1, txid, ledgercore.Txlease{}))
+ var missingRoundErr *errTxTailMissingRound
+ require.ErrorAs(
+ t,
+ l.CheckDup(proto, nextRound, latest-maxValidity, latest-1, txid, ledgercore.Txlease{}),
+ &missingRoundErr,
+ )
+ require.Equal(t, latest-1, missingRoundErr.round)
}
shorterLookback := config.GetDefaultLocal().MaxAcctLookback
@@ -2724,7 +2729,13 @@ func TestLedgerMigrateV6ShrinkDeltas(t *testing.T) {
// check an error latest-1
for txid := range txnIDs[latest-1] {
- require.Error(t, l2.CheckDup(proto, nextRound, latest-maxValidity, latest-1, txid, ledgercore.Txlease{}))
+ var missingRoundErr *errTxTailMissingRound
+ require.ErrorAs(
+ t,
+ l2.CheckDup(proto, nextRound, latest-maxValidity, latest-1, txid, ledgercore.Txlease{}),
+ &missingRoundErr,
+ )
+ require.Equal(t, latest-1, missingRoundErr.round)
}
}
diff --git a/ledger/ledgercore/accountdata.go b/ledger/ledgercore/accountdata.go
index 5d11b7563e..da1260a519 100644
--- a/ledger/ledgercore/accountdata.go
+++ b/ledger/ledgercore/accountdata.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/accountdata_test.go b/ledger/ledgercore/accountdata_test.go
index 80da77714a..caa1a672aa 100644
--- a/ledger/ledgercore/accountdata_test.go
+++ b/ledger/ledgercore/accountdata_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/accountresource.go b/ledger/ledgercore/accountresource.go
index cd5876fb2d..8a08c7b935 100644
--- a/ledger/ledgercore/accountresource.go
+++ b/ledger/ledgercore/accountresource.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/catchpointlabel.go b/ledger/ledgercore/catchpointlabel.go
index e77e898d7c..13ed410f82 100644
--- a/ledger/ledgercore/catchpointlabel.go
+++ b/ledger/ledgercore/catchpointlabel.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/catchpointlabel_test.go b/ledger/ledgercore/catchpointlabel_test.go
index 5ac7e75d84..b8bdce6ab6 100644
--- a/ledger/ledgercore/catchpointlabel_test.go
+++ b/ledger/ledgercore/catchpointlabel_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/error.go b/ledger/ledgercore/error.go
index d39890df6b..06094039ad 100644
--- a/ledger/ledgercore/error.go
+++ b/ledger/ledgercore/error.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -30,6 +30,10 @@ var ErrNoSpace = errors.New("block does not have space for transaction")
// Verify each custom error type implements the error interface, and declare which are pointer/value receivers.
var (
_ error = (*TxnNotWellFormedError)(nil)
+ _ error = (*OverspendError)(nil)
+ _ error = (*MinBalanceError)(nil)
+ _ error = (*AssetBalanceError)(nil)
+ _ error = (*ApprovalProgramRejectedError)(nil)
_ error = (*TransactionInLedgerError)(nil)
_ error = (*LeaseInLedgerError)(nil)
_ error = BlockInLedgerError{}
@@ -47,6 +51,46 @@ func (err *TxnNotWellFormedError) Error() string {
return string(*err)
}
+// OverspendError indicates a transaction attempted to spend more than available funds.
+type OverspendError struct {
+ Account basics.Address
+ Data AccountData
+ Tried basics.MicroAlgos
+}
+
+func (err *OverspendError) Error() string {
+ return fmt.Sprintf("overspend (account %v, data %+v, tried to spend %v)", err.Account, err.Data, err.Tried)
+}
+
+// MinBalanceError indicates a transaction would drop an account below minimum balance.
+type MinBalanceError struct {
+ Account basics.Address
+ Balance uint64
+ MinBalance uint64
+ TotalAssets uint64
+}
+
+func (err *MinBalanceError) Error() string {
+ return fmt.Sprintf("account %v balance %d below min %d (%d assets)", err.Account, err.Balance, err.MinBalance, err.TotalAssets)
+}
+
+// AssetBalanceError indicates a transaction attempted to transfer more of an asset than held.
+type AssetBalanceError struct {
+ Amount uint64
+ SenderAmount uint64
+}
+
+func (err *AssetBalanceError) Error() string {
+ return fmt.Sprintf("underflow on subtracting %d from sender amount %d", err.Amount, err.SenderAmount)
+}
+
+// ApprovalProgramRejectedError indicates an app call was rejected by its approval program.
+type ApprovalProgramRejectedError struct{}
+
+func (err *ApprovalProgramRejectedError) Error() string {
+ return "transaction rejected by ApprovalProgram"
+}
+
// TransactionInLedgerError is returned when a transaction cannot be added because it has already been committed, either
// to the blockchain's ledger or to the history of changes tracked by a BlockEvaluator.
type TransactionInLedgerError struct {
diff --git a/ledger/ledgercore/misc.go b/ledger/ledgercore/misc.go
index 82ad02d563..b405bfbfee 100644
--- a/ledger/ledgercore/misc.go
+++ b/ledger/ledgercore/misc.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/msgp_gen.go b/ledger/ledgercore/msgp_gen.go
index 0f89af32aa..6c77736287 100644
--- a/ledger/ledgercore/msgp_gen.go
+++ b/ledger/ledgercore/msgp_gen.go
@@ -1,7 +1,7 @@
-package ledgercore
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package ledgercore
+
import (
"github.com/algorand/msgp/msgp"
@@ -685,7 +685,7 @@ func (z *AccountTotals) MsgIsZero() bool {
return (((*z).Online.Money.MsgIsZero()) && ((*z).Online.RewardUnits == 0)) && (((*z).Offline.Money.MsgIsZero()) && ((*z).Offline.RewardUnits == 0)) && (((*z).NotParticipating.Money.MsgIsZero()) && ((*z).NotParticipating.RewardUnits == 0)) && ((*z).RewardsLevel == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// AccountTotalsMaxSize returns a maximum valid message size for this message type
func AccountTotalsMaxSize() (s int) {
s = 1 + 7 + 1 + 4 + basics.MicroAlgosMaxSize() + 4 + msgp.Uint64Size + 8 + 1 + 4 + basics.MicroAlgosMaxSize() + 4 + msgp.Uint64Size + 8 + 1 + 4 + basics.MicroAlgosMaxSize() + 4 + msgp.Uint64Size + 7 + msgp.Uint64Size
return
@@ -828,7 +828,7 @@ func (z *AlgoCount) MsgIsZero() bool {
return ((*z).Money.MsgIsZero()) && ((*z).RewardUnits == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// AlgoCountMaxSize returns a maximum valid message size for this message type
func AlgoCountMaxSize() (s int) {
s = 1 + 4 + basics.MicroAlgosMaxSize() + 4 + msgp.Uint64Size
return
@@ -994,7 +994,7 @@ func (z *OnlineRoundParamsData) MsgIsZero() bool {
return ((*z).OnlineSupply == 0) && ((*z).RewardsLevel == 0) && ((*z).CurrentProtocol.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// OnlineRoundParamsDataMaxSize returns a maximum valid message size for this message type
func OnlineRoundParamsDataMaxSize() (s int) {
s = 1 + 7 + msgp.Uint64Size + 7 + msgp.Uint64Size + 6 + protocol.ConsensusVersionMaxSize()
return
@@ -1183,7 +1183,7 @@ func (z *StateProofVerificationContext) MsgIsZero() bool {
return ((*z).LastAttestedRound.MsgIsZero()) && ((*z).VotersCommitment.MsgIsZero()) && ((*z).OnlineTotalWeight.MsgIsZero()) && ((*z).Version.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// StateProofVerificationContextMaxSize returns a maximum valid message size for this message type
func StateProofVerificationContextMaxSize() (s int) {
s = 1 + 8 + basics.RoundMaxSize() + 3 + crypto.GenericDigestMaxSize() + 3 + basics.MicroAlgosMaxSize() + 2 + protocol.ConsensusVersionMaxSize()
return
diff --git a/ledger/ledgercore/msgp_gen_test.go b/ledger/ledgercore/msgp_gen_test.go
index 8478b9d8bc..41976ee333 100644
--- a/ledger/ledgercore/msgp_gen_test.go
+++ b/ledger/ledgercore/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package ledgercore
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package ledgercore
+
import (
"testing"
diff --git a/ledger/ledgercore/onlineacct.go b/ledger/ledgercore/onlineacct.go
index 557a496161..c520d207b6 100644
--- a/ledger/ledgercore/onlineacct.go
+++ b/ledger/ledgercore/onlineacct.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/statedelta.go b/ledger/ledgercore/statedelta.go
index 55d947ee28..c329cc9416 100644
--- a/ledger/ledgercore/statedelta.go
+++ b/ledger/ledgercore/statedelta.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/statedelta_test.go b/ledger/ledgercore/statedelta_test.go
index 56962c872d..1f17a4f136 100644
--- a/ledger/ledgercore/statedelta_test.go
+++ b/ledger/ledgercore/statedelta_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/stateproofverification.go b/ledger/ledgercore/stateproofverification.go
index ad6c727800..b2134c9fbb 100644
--- a/ledger/ledgercore/stateproofverification.go
+++ b/ledger/ledgercore/stateproofverification.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/totals.go b/ledger/ledgercore/totals.go
index 31ac5a44dc..8660a9000e 100644
--- a/ledger/ledgercore/totals.go
+++ b/ledger/ledgercore/totals.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/totals_test.go b/ledger/ledgercore/totals_test.go
index c2bdfd9e4f..c1a287a3df 100644
--- a/ledger/ledgercore/totals_test.go
+++ b/ledger/ledgercore/totals_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/validatedBlock.go b/ledger/ledgercore/validatedBlock.go
index 0adab21ee8..63a0a485d4 100644
--- a/ledger/ledgercore/validatedBlock.go
+++ b/ledger/ledgercore/validatedBlock.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/ledgercore/votersForRound.go b/ledger/ledgercore/votersForRound.go
index 05ce84f91d..4a981bc5e0 100644
--- a/ledger/ledgercore/votersForRound.go
+++ b/ledger/ledgercore/votersForRound.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/lruaccts.go b/ledger/lruaccts.go
index b0ddc9b37a..c344235515 100644
--- a/ledger/lruaccts.go
+++ b/ledger/lruaccts.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/lruaccts_test.go b/ledger/lruaccts_test.go
index 5fd2a0e9e1..2d1fb041d4 100644
--- a/ledger/lruaccts_test.go
+++ b/ledger/lruaccts_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/lrukv.go b/ledger/lrukv.go
index 75f01cb67d..3c75daa684 100644
--- a/ledger/lrukv.go
+++ b/ledger/lrukv.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/lrukv_test.go b/ledger/lrukv_test.go
index 02b0e5c316..72c62a275a 100644
--- a/ledger/lrukv_test.go
+++ b/ledger/lrukv_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/lruonlineaccts.go b/ledger/lruonlineaccts.go
index 47e39d6b9a..70456c51a0 100644
--- a/ledger/lruonlineaccts.go
+++ b/ledger/lruonlineaccts.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -23,7 +23,7 @@ import (
"github.com/algorand/go-algorand/util"
)
-// lruAccounts provides a storage class for the most recently used accounts data.
+// lruOnlineAccounts provides a storage class for the most recently used accounts data.
// It doesn't have any synchronization primitive on its own and so is required to be
// synchronized by the caller.
type lruOnlineAccounts struct {
diff --git a/ledger/lruonlineaccts_test.go b/ledger/lruonlineaccts_test.go
index e432584523..03cedb2d62 100644
--- a/ledger/lruonlineaccts_test.go
+++ b/ledger/lruonlineaccts_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/lruresources.go b/ledger/lruresources.go
index 303dd86e66..1623b54c79 100644
--- a/ledger/lruresources.go
+++ b/ledger/lruresources.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/lruresources_test.go b/ledger/lruresources_test.go
index 333a17e986..13be87168a 100644
--- a/ledger/lruresources_test.go
+++ b/ledger/lruresources_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/metrics.go b/ledger/metrics.go
index 36d4290c92..52e3ebd0c6 100644
--- a/ledger/metrics.go
+++ b/ledger/metrics.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -31,31 +31,38 @@ type metricsTracker struct {
ledgerRewardClaimsTotal *metrics.Counter
ledgerRound *metrics.Gauge
ledgerDBRound *metrics.Gauge
+ registry *metrics.Registry
}
func (mt *metricsTracker) loadFromDisk(l ledgerForTracker, _ basics.Round) error {
- mt.ledgerTransactionsTotal = metrics.MakeCounter(metrics.LedgerTransactionsTotal)
- mt.ledgerRewardClaimsTotal = metrics.MakeCounter(metrics.LedgerRewardClaimsTotal)
- mt.ledgerRound = metrics.MakeGauge(metrics.LedgerRound)
- mt.ledgerDBRound = metrics.MakeGauge(metrics.LedgerDBRound)
+ reg := mt.registry
+ mt.ledgerTransactionsTotal = metrics.MakeCounterUnregistered(metrics.LedgerTransactionsTotal)
+ mt.ledgerTransactionsTotal.Register(reg)
+ mt.ledgerRewardClaimsTotal = metrics.MakeCounterUnregistered(metrics.LedgerRewardClaimsTotal)
+ mt.ledgerRewardClaimsTotal.Register(reg)
+ mt.ledgerRound = metrics.MakeGaugeUnregistered(metrics.LedgerRound)
+ mt.ledgerRound.Register(reg)
+ mt.ledgerDBRound = metrics.MakeGaugeUnregistered(metrics.LedgerDBRound)
+ mt.ledgerDBRound.Register(reg)
return nil
}
func (mt *metricsTracker) close() {
+ reg := mt.registry
if mt.ledgerTransactionsTotal != nil {
- mt.ledgerTransactionsTotal.Deregister(nil)
+ mt.ledgerTransactionsTotal.Deregister(reg)
mt.ledgerTransactionsTotal = nil
}
if mt.ledgerRewardClaimsTotal != nil {
- mt.ledgerRewardClaimsTotal.Deregister(nil)
+ mt.ledgerRewardClaimsTotal.Deregister(reg)
mt.ledgerRewardClaimsTotal = nil
}
if mt.ledgerRound != nil {
- mt.ledgerRound.Deregister(nil)
+ mt.ledgerRound.Deregister(reg)
mt.ledgerRound = nil
}
if mt.ledgerDBRound != nil {
- mt.ledgerDBRound.Deregister(nil)
+ mt.ledgerDBRound.Deregister(reg)
mt.ledgerDBRound = nil
}
}
diff --git a/ledger/metrics_test.go b/ledger/metrics_test.go
index ff42311072..943b44fcf8 100644
--- a/ledger/metrics_test.go
+++ b/ledger/metrics_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -34,7 +34,11 @@ import (
func TestMetricsReload(t *testing.T) {
partitiontest.PartitionTest(t)
- mt := metricsTracker{}
+ // Use a non-default registry so the test is not affected by metrics
+ // registered by other packages when running with -coverpkg.
+ registry := metrics.MakeRegistry()
+
+ mt := metricsTracker{registry: registry}
accts := ledgertesting.RandomAccounts(1, true)
ml := makeMockLedgerForTracker(t, true, 1, protocol.ConsensusCurrentVersion, []map[basics.Address]basics.AccountData{accts})
@@ -48,7 +52,7 @@ func TestMetricsReload(t *testing.T) {
mt.newBlock(blk, ledgercore.StateDelta{})
var buf strings.Builder
- metrics.DefaultRegistry().WriteMetrics(&buf, "")
+ registry.WriteMetrics(&buf, "")
lines := strings.Split(buf.String(), "\n")
txCount := 0
rcCount := 0
diff --git a/ledger/msgp_gen.go b/ledger/msgp_gen.go
index 415c2bb6ae..d3d6aa5048 100644
--- a/ledger/msgp_gen.go
+++ b/ledger/msgp_gen.go
@@ -1,7 +1,7 @@
-package ledger
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package ledger
+
import (
"github.com/algorand/msgp/msgp"
@@ -116,7 +116,7 @@ func (z CatchpointCatchupState) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// CatchpointCatchupStateMaxSize returns a maximum valid message size for this message type
func CatchpointCatchupStateMaxSize() (s int) {
s = msgp.Int32Size
return
@@ -466,7 +466,7 @@ func (z *CatchpointFileHeader) MsgIsZero() bool {
return ((*z).Version == 0) && ((*z).BalancesRound.MsgIsZero()) && ((*z).BlocksRound.MsgIsZero()) && ((*z).Totals.MsgIsZero()) && ((*z).TotalAccounts == 0) && ((*z).TotalChunks == 0) && ((*z).TotalKVs == 0) && ((*z).TotalOnlineAccounts == 0) && ((*z).TotalOnlineRoundParams == 0) && ((*z).Catchpoint == "") && ((*z).BlockHeaderDigest.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// CatchpointFileHeaderMaxSize returns a maximum valid message size for this message type
func CatchpointFileHeaderMaxSize() (s int) {
s = 1 + 8 + msgp.Uint64Size + 14 + basics.RoundMaxSize() + 12 + basics.RoundMaxSize() + 14 + ledgercore.AccountTotalsMaxSize() + 14 + msgp.Uint64Size + 12 + msgp.Uint64Size + 9 + msgp.Uint64Size + 20 + msgp.Uint64Size + 23 + msgp.Uint64Size + 11
panic("Unable to determine max size: String type z.Catchpoint is unbounded")
@@ -638,7 +638,7 @@ func (z *CatchpointSnapshotChunkV5) MsgIsZero() bool {
return (len((*z).Balances) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// CatchpointSnapshotChunkV5MaxSize returns a maximum valid message size for this message type
func CatchpointSnapshotChunkV5MaxSize() (s int) {
s = 1 + 3
// Calculating size of slice: z.Balances
@@ -1040,7 +1040,7 @@ func (z *CatchpointSnapshotChunkV6) MsgIsZero() bool {
return (len((*z).Balances) == 0) && (len((*z).KVs) == 0) && (len((*z).OnlineAccounts) == 0) && (len((*z).OnlineRoundParams) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// CatchpointSnapshotChunkV6MaxSize returns a maximum valid message size for this message type
func CatchpointSnapshotChunkV6MaxSize() (s int) {
s = 1 + 3
// Calculating size of slice: z.Balances
@@ -1223,7 +1223,7 @@ func (z *catchpointStateProofVerificationContext) MsgIsZero() bool {
return (len((*z).Data) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// CatchpointStateProofVerificationContextMaxSize returns a maximum valid message size for this message type
func CatchpointStateProofVerificationContextMaxSize() (s int) {
s = 1 + 4
// Calculating size of slice: z.Data
diff --git a/ledger/msgp_gen_test.go b/ledger/msgp_gen_test.go
index 42660acb9b..aac1bef669 100644
--- a/ledger/msgp_gen_test.go
+++ b/ledger/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package ledger
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package ledger
+
import (
"testing"
diff --git a/ledger/notifier.go b/ledger/notifier.go
index 7bf6a9802a..3dcd4a6298 100644
--- a/ledger/notifier.go
+++ b/ledger/notifier.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/onlineaccountscache.go b/ledger/onlineaccountscache.go
index e3a44e08d4..f0d4a52cc1 100644
--- a/ledger/onlineaccountscache.go
+++ b/ledger/onlineaccountscache.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/onlineaccountscache_test.go b/ledger/onlineaccountscache_test.go
index 17f09561d7..c14d879c2b 100644
--- a/ledger/onlineaccountscache_test.go
+++ b/ledger/onlineaccountscache_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/onlinetopheap.go b/ledger/onlinetopheap.go
index 6f8cc81325..bfc7da0370 100644
--- a/ledger/onlinetopheap.go
+++ b/ledger/onlinetopheap.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/onlinetopheap_test.go b/ledger/onlinetopheap_test.go
index 6c16a0b3eb..4a0d542505 100644
--- a/ledger/onlinetopheap_test.go
+++ b/ledger/onlinetopheap_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/perf_test.go b/ledger/perf_test.go
index 3b3d404b3f..7b76483d33 100644
--- a/ledger/perf_test.go
+++ b/ledger/perf_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/simple_test.go b/ledger/simple_test.go
index d8c24c1c14..638f8055b7 100644
--- a/ledger/simple_test.go
+++ b/ledger/simple_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -137,7 +137,7 @@ func txns(t testing.TB, ledger *Ledger, eval *eval.BlockEvaluator, txns ...*txnt
func txn(t testing.TB, ledger *Ledger, eval *eval.BlockEvaluator, txn *txntest.Txn, problem ...string) {
t.Helper()
fillDefaults(t, ledger, eval, txn)
- err := eval.Transaction(txn.SignedTxn(), transactions.ApplyData{})
+ err := eval.TransactionGroup(txn.SignedTxn().WithAD())
if err != nil {
if len(problem) == 1 && problem[0] != "" {
require.Contains(t, err.Error(), problem[0])
@@ -156,7 +156,7 @@ func txgroup(t testing.TB, ledger *Ledger, eval *eval.BlockEvaluator, txns ...*t
}
txgroup := txntest.Group(txns...)
- return eval.TransactionGroup(transactions.WrapSignedTxnsWithAD(txgroup))
+ return eval.TransactionGroup(transactions.WrapSignedTxnsWithAD(txgroup)...)
}
// endBlock completes the block being created, returning the ValidatedBlock for
diff --git a/ledger/simulation/initialStates.go b/ledger/simulation/initialStates.go
index f9750c929a..869ebbe999 100644
--- a/ledger/simulation/initialStates.go
+++ b/ledger/simulation/initialStates.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/simulation/resources.go b/ledger/simulation/resources.go
index 9394bd8fbd..c33d45e081 100644
--- a/ledger/simulation/resources.go
+++ b/ledger/simulation/resources.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/simulation/resources_test.go b/ledger/simulation/resources_test.go
index 0970b6eb54..c7f20c0b6a 100644
--- a/ledger/simulation/resources_test.go
+++ b/ledger/simulation/resources_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/simulation/simulation_eval_test.go b/ledger/simulation/simulation_eval_test.go
index 899dfc6b3f..7e60d829e0 100644
--- a/ledger/simulation/simulation_eval_test.go
+++ b/ledger/simulation/simulation_eval_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/simulation/simulator.go b/ledger/simulation/simulator.go
index 47e4f4b819..82d941b0da 100644
--- a/ledger/simulation/simulator.go
+++ b/ledger/simulation/simulator.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -191,7 +191,7 @@ func (s Simulator) evaluate(hdr bookkeeping.BlockHeader, group []transactions.Si
return nil, err
}
- err = eval.TransactionGroup(group)
+ err = eval.TransactionGroup(group...)
if err != nil {
return nil, EvalFailureError{SimulatorError{err}}
}
diff --git a/ledger/simulation/simulator_test.go b/ledger/simulation/simulator_test.go
index 8e4a6d0b24..7f416021a6 100644
--- a/ledger/simulation/simulator_test.go
+++ b/ledger/simulation/simulator_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/simulation/testing/utils.go b/ledger/simulation/testing/utils.go
index 27f45a4e13..0910e0061f 100644
--- a/ledger/simulation/testing/utils.go
+++ b/ledger/simulation/testing/utils.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -118,7 +118,7 @@ func (env *Environment) Txn(txn transactions.SignedTxn) transactions.ApplyData {
env.t.Helper()
evaluator := env.nextBlock()
- err := evaluator.Transaction(txn, transactions.ApplyData{})
+ err := evaluator.TransactionGroup(txn.WithAD())
require.NoError(env.t, err)
newBlock := env.endBlock(evaluator).Block()
diff --git a/ledger/simulation/trace.go b/ledger/simulation/trace.go
index 7808be54d9..e43ce35ae2 100644
--- a/ledger/simulation/trace.go
+++ b/ledger/simulation/trace.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -77,9 +77,7 @@ type TxnGroupResult struct {
func makeTxnGroupResult(txgroup []transactions.SignedTxn) TxnGroupResult {
groupResult := TxnGroupResult{Txns: make([]TxnResult, len(txgroup))}
for i, tx := range txgroup {
- groupResult.Txns[i] = TxnResult{Txn: transactions.SignedTxnWithAD{
- SignedTxn: tx,
- }}
+ groupResult.Txns[i] = TxnResult{Txn: tx.WithAD()}
}
return groupResult
}
diff --git a/ledger/simulation/tracer.go b/ledger/simulation/tracer.go
index ea03718f0b..249093f8bb 100644
--- a/ledger/simulation/tracer.go
+++ b/ledger/simulation/tracer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/simulation/tracer_test.go b/ledger/simulation/tracer_test.go
index 7c3f32e5ae..8335d5ac43 100644
--- a/ledger/simulation/tracer_test.go
+++ b/ledger/simulation/tracer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/spverificationtracker.go b/ledger/spverificationtracker.go
index 05a064ea66..aa71d823d3 100644
--- a/ledger/spverificationtracker.go
+++ b/ledger/spverificationtracker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/spverificationtracker_test.go b/ledger/spverificationtracker_test.go
index 5a5b82a0d6..a46ba5bde4 100644
--- a/ledger/spverificationtracker_test.go
+++ b/ledger/spverificationtracker_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/blockdb/blockdb.go b/ledger/store/blockdb/blockdb.go
index 0fbcbdc42c..2dc6fbb448 100644
--- a/ledger/store/blockdb/blockdb.go
+++ b/ledger/store/blockdb/blockdb.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/blockdb/blockdb_test.go b/ledger/store/blockdb/blockdb_test.go
index e9cd0742fe..3b172ae833 100644
--- a/ledger/store/blockdb/blockdb_test.go
+++ b/ledger/store/blockdb/blockdb_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/testing/helpers.go b/ledger/store/testing/helpers.go
index 544f67a488..f05093c924 100644
--- a/ledger/store/testing/helpers.go
+++ b/ledger/store/testing/helpers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/catchpoint.go b/ledger/store/trackerdb/catchpoint.go
index 3c1aaa205f..dfa1b7b45f 100644
--- a/ledger/store/trackerdb/catchpoint.go
+++ b/ledger/store/trackerdb/catchpoint.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/data.go b/ledger/store/trackerdb/data.go
index 3629fff186..e1684a4b4c 100644
--- a/ledger/store/trackerdb/data.go
+++ b/ledger/store/trackerdb/data.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -133,6 +133,8 @@ type ResourcesData struct {
UpdateRound uint64 `codec:"z"`
Version uint64 `codec:"A"`
+
+ SizeSponsor basics.Address `codec:"B"`
}
// BaseVotingData is the base struct used to store voting data
@@ -554,7 +556,8 @@ func (rd *ResourcesData) IsEmptyAppFields() bool {
rd.GlobalStateSchemaNumUint == 0 &&
rd.GlobalStateSchemaNumByteSlice == 0 &&
rd.ExtraProgramPages == 0 &&
- rd.Version == 0
+ rd.Version == 0 &&
+ rd.SizeSponsor.IsZero()
}
// IsApp returns true if the flag is ResourceFlagsEmptyApp and the fields are not empty.
@@ -733,6 +736,7 @@ func (rd *ResourcesData) ClearAppParams() {
rd.GlobalStateSchemaNumByteSlice = 0
rd.ExtraProgramPages = 0
rd.Version = 0
+ rd.SizeSponsor = basics.Address{}
hadHolding := (rd.ResourceFlags & ResourceFlagsNotHolding) == ResourceFlagsHolding
rd.ResourceFlags -= rd.ResourceFlags & ResourceFlagsOwnership
rd.ResourceFlags &= ^ResourceFlagsEmptyApp
@@ -752,6 +756,7 @@ func (rd *ResourcesData) SetAppParams(ap basics.AppParams, haveHoldings bool) {
rd.GlobalStateSchemaNumByteSlice = ap.GlobalStateSchema.NumByteSlice
rd.ExtraProgramPages = ap.ExtraProgramPages
rd.Version = ap.Version
+ rd.SizeSponsor = ap.SizeSponsor
rd.ResourceFlags |= ResourceFlagsOwnership
if !haveHoldings {
rd.ResourceFlags |= ResourceFlagsNotHolding
@@ -780,6 +785,7 @@ func (rd *ResourcesData) GetAppParams() basics.AppParams {
},
ExtraProgramPages: rd.ExtraProgramPages,
Version: rd.Version,
+ SizeSponsor: rd.SizeSponsor,
}
}
diff --git a/ledger/store/trackerdb/data_test.go b/ledger/store/trackerdb/data_test.go
index 1900ab3836..3078f0b1a3 100644
--- a/ledger/store/trackerdb/data_test.go
+++ b/ledger/store/trackerdb/data_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -26,10 +26,12 @@ import (
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/crypto"
"github.com/algorand/go-algorand/data/basics"
+ basics_testing "github.com/algorand/go-algorand/data/basics/testing"
"github.com/algorand/go-algorand/ledger/ledgercore"
ledgertesting "github.com/algorand/go-algorand/ledger/testing"
"github.com/algorand/go-algorand/protocol"
"github.com/algorand/go-algorand/test/partitiontest"
+ "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -1275,3 +1277,72 @@ func TestBaseAccountDataDecodeEmpty(t *testing.T) {
err = protocol.Decode([]byte{0x80}, &b)
require.NoError(t, err)
}
+
+func TestCopyFunctions(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ // AssetParams are copied into and out of ResourceData losslessly
+ assetToRD := func(ap basics.AssetParams) ResourcesData {
+ var rd ResourcesData
+ rd.SetAssetParams(ap, false)
+ return rd
+ }
+ rdToAsset := func(rd ResourcesData) basics.AssetParams {
+ return rd.GetAssetParams()
+ }
+ for _, nz := range basics_testing.NearZeros(t, basics.AssetParams{}) {
+ assert.True(t, basics_testing.RoundTrip(t, nz, assetToRD, rdToAsset), nz)
+ }
+
+ // Asset holdings are copied into and out of ResourceData losslessly
+ holdingToRD := func(ap basics.AssetHolding) ResourcesData {
+ var rd ResourcesData
+ rd.SetAssetHolding(ap)
+ return rd
+ }
+ rdToHolding := func(rd ResourcesData) basics.AssetHolding {
+ return rd.GetAssetHolding()
+ }
+ for _, nz := range basics_testing.NearZeros(t, basics.AssetHolding{}) {
+ assert.True(t, basics_testing.RoundTrip(t, nz, holdingToRD, rdToHolding), nz)
+ }
+
+ // AppParams are copied into and out of ResourceData losslessly
+ apToRD := func(ap basics.AppParams) ResourcesData {
+ var rd ResourcesData
+ rd.SetAppParams(ap, false)
+ return rd
+ }
+ rdToAP := func(rd ResourcesData) basics.AppParams {
+ return rd.GetAppParams()
+ }
+ for _, nz := range basics_testing.NearZeros(t, basics.AppParams{}) {
+ assert.True(t, basics_testing.RoundTrip(t, nz, apToRD, rdToAP), nz)
+ }
+
+ // AppLocalStates are copied into and out of ResourceData losslessly
+ localsToRD := func(ap basics.AppLocalState) ResourcesData {
+ var rd ResourcesData
+ rd.SetAppLocalState(ap)
+ return rd
+ }
+ rdToLocals := func(rd ResourcesData) basics.AppLocalState {
+ return rd.GetAppLocalState()
+ }
+ for _, nz := range basics_testing.NearZeros(t, basics.AppLocalState{}) {
+ assert.True(t, basics_testing.RoundTrip(t, nz, localsToRD, rdToLocals), nz)
+ }
+
+}
+
+func TestIsEmptyAppFields(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ for _, nz := range basics_testing.NearZeros(t, basics.AppParams{}) {
+ var rd ResourcesData
+ rd.SetAppParams(nz, false)
+ assert.False(t, rd.IsEmptyAppFields(), nz)
+ }
+}
diff --git a/ledger/store/trackerdb/dualdriver/accounts_reader.go b/ledger/store/trackerdb/dualdriver/accounts_reader.go
index 8220a70f33..27bede02b7 100644
--- a/ledger/store/trackerdb/dualdriver/accounts_reader.go
+++ b/ledger/store/trackerdb/dualdriver/accounts_reader.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/dualdriver/accounts_reader_ext.go b/ledger/store/trackerdb/dualdriver/accounts_reader_ext.go
index 07bf8f2244..5696955516 100644
--- a/ledger/store/trackerdb/dualdriver/accounts_reader_ext.go
+++ b/ledger/store/trackerdb/dualdriver/accounts_reader_ext.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/dualdriver/accounts_writer.go b/ledger/store/trackerdb/dualdriver/accounts_writer.go
index 36f4dbed2a..b788cfc8cb 100644
--- a/ledger/store/trackerdb/dualdriver/accounts_writer.go
+++ b/ledger/store/trackerdb/dualdriver/accounts_writer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/dualdriver/accounts_writer_ext.go b/ledger/store/trackerdb/dualdriver/accounts_writer_ext.go
index 73d5eb8918..ced4d0aa72 100644
--- a/ledger/store/trackerdb/dualdriver/accounts_writer_ext.go
+++ b/ledger/store/trackerdb/dualdriver/accounts_writer_ext.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/dualdriver/dualdriver.go b/ledger/store/trackerdb/dualdriver/dualdriver.go
index 09e4cf085d..c88729636d 100644
--- a/ledger/store/trackerdb/dualdriver/dualdriver.go
+++ b/ledger/store/trackerdb/dualdriver/dualdriver.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/dualdriver/online_accounts_reader.go b/ledger/store/trackerdb/dualdriver/online_accounts_reader.go
index 7fe0d1163a..8ffcb91334 100644
--- a/ledger/store/trackerdb/dualdriver/online_accounts_reader.go
+++ b/ledger/store/trackerdb/dualdriver/online_accounts_reader.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/dualdriver/online_accounts_writer.go b/ledger/store/trackerdb/dualdriver/online_accounts_writer.go
index 5f25d388c8..36fc283953 100644
--- a/ledger/store/trackerdb/dualdriver/online_accounts_writer.go
+++ b/ledger/store/trackerdb/dualdriver/online_accounts_writer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/dualdriver/stateproof_reader.go b/ledger/store/trackerdb/dualdriver/stateproof_reader.go
index bf8354db6a..ef15ed2ee6 100644
--- a/ledger/store/trackerdb/dualdriver/stateproof_reader.go
+++ b/ledger/store/trackerdb/dualdriver/stateproof_reader.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/dualdriver/stateproof_writer.go b/ledger/store/trackerdb/dualdriver/stateproof_writer.go
index 188e86e83d..026522bf77 100644
--- a/ledger/store/trackerdb/dualdriver/stateproof_writer.go
+++ b/ledger/store/trackerdb/dualdriver/stateproof_writer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/dualdriver/transaction_for_testing.go b/ledger/store/trackerdb/dualdriver/transaction_for_testing.go
index a5aea91797..698f796a1f 100644
--- a/ledger/store/trackerdb/dualdriver/transaction_for_testing.go
+++ b/ledger/store/trackerdb/dualdriver/transaction_for_testing.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/accounts_ext_reader.go b/ledger/store/trackerdb/generickv/accounts_ext_reader.go
index 2624a400e6..b765001de6 100644
--- a/ledger/store/trackerdb/generickv/accounts_ext_reader.go
+++ b/ledger/store/trackerdb/generickv/accounts_ext_reader.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/accounts_ext_writer.go b/ledger/store/trackerdb/generickv/accounts_ext_writer.go
index e92197ceba..9813bef8dd 100644
--- a/ledger/store/trackerdb/generickv/accounts_ext_writer.go
+++ b/ledger/store/trackerdb/generickv/accounts_ext_writer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/accounts_reader.go b/ledger/store/trackerdb/generickv/accounts_reader.go
index 15bbe4aa9d..8726ab4fa7 100644
--- a/ledger/store/trackerdb/generickv/accounts_reader.go
+++ b/ledger/store/trackerdb/generickv/accounts_reader.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/accounts_writer.go b/ledger/store/trackerdb/generickv/accounts_writer.go
index 887acbec37..a61b87ad7c 100644
--- a/ledger/store/trackerdb/generickv/accounts_writer.go
+++ b/ledger/store/trackerdb/generickv/accounts_writer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/catchpoint.go b/ledger/store/trackerdb/generickv/catchpoint.go
index d10666dbd0..cfd67ce601 100644
--- a/ledger/store/trackerdb/generickv/catchpoint.go
+++ b/ledger/store/trackerdb/generickv/catchpoint.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/init_accounts.go b/ledger/store/trackerdb/generickv/init_accounts.go
index b85b6f531c..e38b77093a 100644
--- a/ledger/store/trackerdb/generickv/init_accounts.go
+++ b/ledger/store/trackerdb/generickv/init_accounts.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/migrations.go b/ledger/store/trackerdb/generickv/migrations.go
index 3fc31ec7d5..6202fdd472 100644
--- a/ledger/store/trackerdb/generickv/migrations.go
+++ b/ledger/store/trackerdb/generickv/migrations.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/msgp_gen.go b/ledger/store/trackerdb/generickv/msgp_gen.go
index c15ead158c..0d3c09ab03 100644
--- a/ledger/store/trackerdb/generickv/msgp_gen.go
+++ b/ledger/store/trackerdb/generickv/msgp_gen.go
@@ -1,7 +1,7 @@
-package generickv
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package generickv
+
import (
"github.com/algorand/msgp/msgp"
@@ -157,7 +157,7 @@ func (z *creatableEntry) MsgIsZero() bool {
return ((*z).Ctype.MsgIsZero()) && (len((*z).CreatorAddr) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// CreatableEntryMaxSize returns a maximum valid message size for this message type
func CreatableEntryMaxSize() (s int) {
s = 1 + 6 + basics.CreatableTypeMaxSize() + 12
panic("Unable to determine max size: Byteslice type z.CreatorAddr is unbounded")
diff --git a/ledger/store/trackerdb/generickv/msgp_gen_test.go b/ledger/store/trackerdb/generickv/msgp_gen_test.go
index 88d79eec21..70cd6e503a 100644
--- a/ledger/store/trackerdb/generickv/msgp_gen_test.go
+++ b/ledger/store/trackerdb/generickv/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package generickv
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package generickv
+
import (
"testing"
diff --git a/ledger/store/trackerdb/generickv/onlineaccounts_reader.go b/ledger/store/trackerdb/generickv/onlineaccounts_reader.go
index 2d693f68ff..7021d4850d 100644
--- a/ledger/store/trackerdb/generickv/onlineaccounts_reader.go
+++ b/ledger/store/trackerdb/generickv/onlineaccounts_reader.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/onlineaccounts_writer.go b/ledger/store/trackerdb/generickv/onlineaccounts_writer.go
index d01daef9e8..82ef657112 100644
--- a/ledger/store/trackerdb/generickv/onlineaccounts_writer.go
+++ b/ledger/store/trackerdb/generickv/onlineaccounts_writer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/reader.go b/ledger/store/trackerdb/generickv/reader.go
index bada2007c4..67ff0423ae 100644
--- a/ledger/store/trackerdb/generickv/reader.go
+++ b/ledger/store/trackerdb/generickv/reader.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/schema.go b/ledger/store/trackerdb/generickv/schema.go
index 510b69ccec..a1f9ee423f 100644
--- a/ledger/store/trackerdb/generickv/schema.go
+++ b/ledger/store/trackerdb/generickv/schema.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/stateproof_reader.go b/ledger/store/trackerdb/generickv/stateproof_reader.go
index eb6c0e0be5..1f3e83a11c 100644
--- a/ledger/store/trackerdb/generickv/stateproof_reader.go
+++ b/ledger/store/trackerdb/generickv/stateproof_reader.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/stateproof_writer.go b/ledger/store/trackerdb/generickv/stateproof_writer.go
index 48b29f3bc6..bb479c5d4e 100644
--- a/ledger/store/trackerdb/generickv/stateproof_writer.go
+++ b/ledger/store/trackerdb/generickv/stateproof_writer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/generickv/writer.go b/ledger/store/trackerdb/generickv/writer.go
index 0dac0082d6..71866e8b58 100644
--- a/ledger/store/trackerdb/generickv/writer.go
+++ b/ledger/store/trackerdb/generickv/writer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/hashing.go b/ledger/store/trackerdb/hashing.go
index 250a127511..908dcc9983 100644
--- a/ledger/store/trackerdb/hashing.go
+++ b/ledger/store/trackerdb/hashing.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -29,7 +29,7 @@ import (
// By encoding HashKind at a known-offset, it's possible for hash readers to
// disambiguate the hashed resource.
//
-//go:generate stringer -type=HashKind
+//go:generate go tool -modfile=../../../tool.mod stringer -type=HashKind
//msgp:ignore HashKind
type HashKind byte
diff --git a/ledger/store/trackerdb/hashkind_string.go b/ledger/store/trackerdb/hashkind_string.go
index 1a8c0f196b..6f9fbcf98d 100644
--- a/ledger/store/trackerdb/hashkind_string.go
+++ b/ledger/store/trackerdb/hashkind_string.go
@@ -19,8 +19,9 @@ const _HashKind_name = "AccountHKAssetHKAppHKKvHK"
var _HashKind_index = [...]uint8{0, 9, 16, 21, 25}
func (i HashKind) String() string {
- if i >= HashKind(len(_HashKind_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_HashKind_index)-1 {
return "HashKind(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _HashKind_name[_HashKind_index[i]:_HashKind_index[i+1]]
+ return _HashKind_name[_HashKind_index[idx]:_HashKind_index[idx+1]]
}
diff --git a/ledger/store/trackerdb/interface.go b/ledger/store/trackerdb/interface.go
index d067556171..7009939a81 100644
--- a/ledger/store/trackerdb/interface.go
+++ b/ledger/store/trackerdb/interface.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/msgp_gen.go b/ledger/store/trackerdb/msgp_gen.go
index a2387a7e56..f146d75c49 100644
--- a/ledger/store/trackerdb/msgp_gen.go
+++ b/ledger/store/trackerdb/msgp_gen.go
@@ -1,7 +1,7 @@
-package trackerdb
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package trackerdb
+
import (
"github.com/algorand/msgp/msgp"
@@ -738,7 +738,7 @@ func (z *BaseAccountData) MsgIsZero() bool {
return ((*z).Status.MsgIsZero()) && ((*z).MicroAlgos.MsgIsZero()) && ((*z).RewardsBase == 0) && ((*z).RewardedMicroAlgos.MsgIsZero()) && ((*z).AuthAddr.MsgIsZero()) && ((*z).TotalAppSchemaNumUint == 0) && ((*z).TotalAppSchemaNumByteSlice == 0) && ((*z).TotalExtraAppPages == 0) && ((*z).TotalAssetParams == 0) && ((*z).TotalAssets == 0) && ((*z).TotalAppParams == 0) && ((*z).TotalAppLocalStates == 0) && ((*z).TotalBoxes == 0) && ((*z).TotalBoxBytes == 0) && ((*z).IncentiveEligible == false) && ((*z).LastProposed.MsgIsZero()) && ((*z).LastHeartbeat.MsgIsZero()) && ((*z).BaseVotingData.VoteID.MsgIsZero()) && ((*z).BaseVotingData.SelectionID.MsgIsZero()) && ((*z).BaseVotingData.VoteFirstValid.MsgIsZero()) && ((*z).BaseVotingData.VoteLastValid.MsgIsZero()) && ((*z).BaseVotingData.VoteKeyDilution == 0) && ((*z).BaseVotingData.StateProofID.MsgIsZero()) && ((*z).UpdateRound == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// BaseAccountDataMaxSize returns a maximum valid message size for this message type
func BaseAccountDataMaxSize() (s int) {
s = 3 + 2 + basics.StatusMaxSize() + 2 + basics.MicroAlgosMaxSize() + 2 + msgp.Uint64Size + 2 + basics.MicroAlgosMaxSize() + 2 + basics.AddressMaxSize() + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.Uint32Size + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.BoolSize + 2 + basics.RoundMaxSize() + 2 + basics.RoundMaxSize() + 2 + crypto.OneTimeSignatureVerifierMaxSize() + 2 + crypto.VRFVerifierMaxSize() + 2 + basics.RoundMaxSize() + 2 + basics.RoundMaxSize() + 2 + msgp.Uint64Size + 2 + merklesignature.CommitmentMaxSize() + 2 + msgp.Uint64Size
return
@@ -1088,7 +1088,7 @@ func (z *BaseOnlineAccountData) MsgIsZero() bool {
return ((*z).BaseVotingData.VoteID.MsgIsZero()) && ((*z).BaseVotingData.SelectionID.MsgIsZero()) && ((*z).BaseVotingData.VoteFirstValid.MsgIsZero()) && ((*z).BaseVotingData.VoteLastValid.MsgIsZero()) && ((*z).BaseVotingData.VoteKeyDilution == 0) && ((*z).BaseVotingData.StateProofID.MsgIsZero()) && ((*z).LastProposed.MsgIsZero()) && ((*z).LastHeartbeat.MsgIsZero()) && ((*z).IncentiveEligible == false) && ((*z).MicroAlgos.MsgIsZero()) && ((*z).RewardsBase == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// BaseOnlineAccountDataMaxSize returns a maximum valid message size for this message type
func BaseOnlineAccountDataMaxSize() (s int) {
s = 1 + 2 + crypto.OneTimeSignatureVerifierMaxSize() + 2 + crypto.VRFVerifierMaxSize() + 2 + basics.RoundMaxSize() + 2 + basics.RoundMaxSize() + 2 + msgp.Uint64Size + 2 + merklesignature.CommitmentMaxSize() + 2 + basics.RoundMaxSize() + 2 + basics.RoundMaxSize() + 2 + msgp.BoolSize + 2 + basics.MicroAlgosMaxSize() + 2 + msgp.Uint64Size
return
@@ -1323,7 +1323,7 @@ func (z *BaseVotingData) MsgIsZero() bool {
return ((*z).VoteID.MsgIsZero()) && ((*z).SelectionID.MsgIsZero()) && ((*z).VoteFirstValid.MsgIsZero()) && ((*z).VoteLastValid.MsgIsZero()) && ((*z).VoteKeyDilution == 0) && ((*z).StateProofID.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// BaseVotingDataMaxSize returns a maximum valid message size for this message type
func BaseVotingDataMaxSize() (s int) {
s = 1 + 2 + crypto.OneTimeSignatureVerifierMaxSize() + 2 + crypto.VRFVerifierMaxSize() + 2 + basics.RoundMaxSize() + 2 + basics.RoundMaxSize() + 2 + msgp.Uint64Size + 2 + merklesignature.CommitmentMaxSize()
return
@@ -1673,7 +1673,7 @@ func (z *CatchpointFirstStageInfo) MsgIsZero() bool {
return ((*z).Totals.MsgIsZero()) && ((*z).TrieBalancesHash.MsgIsZero()) && ((*z).TotalAccounts == 0) && ((*z).TotalKVs == 0) && ((*z).TotalOnlineAccounts == 0) && ((*z).TotalOnlineRoundParams == 0) && ((*z).TotalChunks == 0) && ((*z).BiggestChunkLen == 0) && ((*z).StateProofVerificationHash.MsgIsZero()) && ((*z).OnlineAccountsHash.MsgIsZero()) && ((*z).OnlineRoundParamsHash.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// CatchpointFirstStageInfoMaxSize returns a maximum valid message size for this message type
func CatchpointFirstStageInfoMaxSize() (s int) {
s = 1 + 14 + ledgercore.AccountTotalsMaxSize() + 17 + crypto.DigestMaxSize() + 14 + msgp.Uint64Size + 9 + msgp.Uint64Size + 20 + msgp.Uint64Size + 23 + msgp.Uint64Size + 12 + msgp.Uint64Size + 13 + msgp.Uint64Size + 19 + crypto.DigestMaxSize() + 19 + crypto.DigestMaxSize() + 22 + crypto.DigestMaxSize()
return
@@ -1733,7 +1733,7 @@ func (z ResourceFlags) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// ResourceFlagsMaxSize returns a maximum valid message size for this message type
func ResourceFlagsMaxSize() (s int) {
s = msgp.Uint8Size
return
@@ -1743,115 +1743,119 @@ func ResourceFlagsMaxSize() (s int) {
func (z *ResourcesData) MarshalMsg(b []byte) (o []byte) {
o = msgp.Require(b, z.Msgsize())
// omitempty: check for empty values
- zb0002Len := uint32(27)
- var zb0002Mask uint32 /* 28 bits */
+ zb0002Len := uint32(28)
+ var zb0002Mask uint32 /* 29 bits */
if (*z).Version == 0 {
zb0002Len--
zb0002Mask |= 0x1
}
+ if (*z).SizeSponsor.MsgIsZero() {
+ zb0002Len--
+ zb0002Mask |= 0x2
+ }
if (*z).Total == 0 {
zb0002Len--
- zb0002Mask |= 0x4
+ zb0002Mask |= 0x8
}
if (*z).Decimals == 0 {
zb0002Len--
- zb0002Mask |= 0x8
+ zb0002Mask |= 0x10
}
if (*z).DefaultFrozen == false {
zb0002Len--
- zb0002Mask |= 0x10
+ zb0002Mask |= 0x20
}
if (*z).UnitName == "" {
zb0002Len--
- zb0002Mask |= 0x20
+ zb0002Mask |= 0x40
}
if (*z).AssetName == "" {
zb0002Len--
- zb0002Mask |= 0x40
+ zb0002Mask |= 0x80
}
if (*z).URL == "" {
zb0002Len--
- zb0002Mask |= 0x80
+ zb0002Mask |= 0x100
}
if (*z).MetadataHash == ([32]byte{}) {
zb0002Len--
- zb0002Mask |= 0x100
+ zb0002Mask |= 0x200
}
if (*z).Manager.MsgIsZero() {
zb0002Len--
- zb0002Mask |= 0x200
+ zb0002Mask |= 0x400
}
if (*z).Reserve.MsgIsZero() {
zb0002Len--
- zb0002Mask |= 0x400
+ zb0002Mask |= 0x800
}
if (*z).Freeze.MsgIsZero() {
zb0002Len--
- zb0002Mask |= 0x800
+ zb0002Mask |= 0x1000
}
if (*z).Clawback.MsgIsZero() {
zb0002Len--
- zb0002Mask |= 0x1000
+ zb0002Mask |= 0x2000
}
if (*z).Amount == 0 {
zb0002Len--
- zb0002Mask |= 0x2000
+ zb0002Mask |= 0x4000
}
if (*z).Frozen == false {
zb0002Len--
- zb0002Mask |= 0x4000
+ zb0002Mask |= 0x8000
}
if (*z).SchemaNumUint == 0 {
zb0002Len--
- zb0002Mask |= 0x8000
+ zb0002Mask |= 0x10000
}
if (*z).SchemaNumByteSlice == 0 {
zb0002Len--
- zb0002Mask |= 0x10000
+ zb0002Mask |= 0x20000
}
if (*z).KeyValue.MsgIsZero() {
zb0002Len--
- zb0002Mask |= 0x20000
+ zb0002Mask |= 0x40000
}
if len((*z).ApprovalProgram) == 0 {
zb0002Len--
- zb0002Mask |= 0x40000
+ zb0002Mask |= 0x80000
}
if len((*z).ClearStateProgram) == 0 {
zb0002Len--
- zb0002Mask |= 0x80000
+ zb0002Mask |= 0x100000
}
if (*z).GlobalState.MsgIsZero() {
zb0002Len--
- zb0002Mask |= 0x100000
+ zb0002Mask |= 0x200000
}
if (*z).LocalStateSchemaNumUint == 0 {
zb0002Len--
- zb0002Mask |= 0x200000
+ zb0002Mask |= 0x400000
}
if (*z).LocalStateSchemaNumByteSlice == 0 {
zb0002Len--
- zb0002Mask |= 0x400000
+ zb0002Mask |= 0x800000
}
if (*z).GlobalStateSchemaNumUint == 0 {
zb0002Len--
- zb0002Mask |= 0x800000
+ zb0002Mask |= 0x1000000
}
if (*z).GlobalStateSchemaNumByteSlice == 0 {
zb0002Len--
- zb0002Mask |= 0x1000000
+ zb0002Mask |= 0x2000000
}
if (*z).ExtraProgramPages == 0 {
zb0002Len--
- zb0002Mask |= 0x2000000
+ zb0002Mask |= 0x4000000
}
if (*z).ResourceFlags == 0 {
zb0002Len--
- zb0002Mask |= 0x4000000
+ zb0002Mask |= 0x8000000
}
if (*z).UpdateRound == 0 {
zb0002Len--
- zb0002Mask |= 0x8000000
+ zb0002Mask |= 0x10000000
}
// variable map header, size zb0002Len
o = msgp.AppendMapHeader(o, zb0002Len)
@@ -1861,132 +1865,137 @@ func (z *ResourcesData) MarshalMsg(b []byte) (o []byte) {
o = append(o, 0xa1, 0x41)
o = msgp.AppendUint64(o, (*z).Version)
}
- if (zb0002Mask & 0x4) == 0 { // if not empty
+ if (zb0002Mask & 0x2) == 0 { // if not empty
+ // string "B"
+ o = append(o, 0xa1, 0x42)
+ o = (*z).SizeSponsor.MarshalMsg(o)
+ }
+ if (zb0002Mask & 0x8) == 0 { // if not empty
// string "a"
o = append(o, 0xa1, 0x61)
o = msgp.AppendUint64(o, (*z).Total)
}
- if (zb0002Mask & 0x8) == 0 { // if not empty
+ if (zb0002Mask & 0x10) == 0 { // if not empty
// string "b"
o = append(o, 0xa1, 0x62)
o = msgp.AppendUint32(o, (*z).Decimals)
}
- if (zb0002Mask & 0x10) == 0 { // if not empty
+ if (zb0002Mask & 0x20) == 0 { // if not empty
// string "c"
o = append(o, 0xa1, 0x63)
o = msgp.AppendBool(o, (*z).DefaultFrozen)
}
- if (zb0002Mask & 0x20) == 0 { // if not empty
+ if (zb0002Mask & 0x40) == 0 { // if not empty
// string "d"
o = append(o, 0xa1, 0x64)
o = msgp.AppendString(o, (*z).UnitName)
}
- if (zb0002Mask & 0x40) == 0 { // if not empty
+ if (zb0002Mask & 0x80) == 0 { // if not empty
// string "e"
o = append(o, 0xa1, 0x65)
o = msgp.AppendString(o, (*z).AssetName)
}
- if (zb0002Mask & 0x80) == 0 { // if not empty
+ if (zb0002Mask & 0x100) == 0 { // if not empty
// string "f"
o = append(o, 0xa1, 0x66)
o = msgp.AppendString(o, (*z).URL)
}
- if (zb0002Mask & 0x100) == 0 { // if not empty
+ if (zb0002Mask & 0x200) == 0 { // if not empty
// string "g"
o = append(o, 0xa1, 0x67)
o = msgp.AppendBytes(o, ((*z).MetadataHash)[:])
}
- if (zb0002Mask & 0x200) == 0 { // if not empty
+ if (zb0002Mask & 0x400) == 0 { // if not empty
// string "h"
o = append(o, 0xa1, 0x68)
o = (*z).Manager.MarshalMsg(o)
}
- if (zb0002Mask & 0x400) == 0 { // if not empty
+ if (zb0002Mask & 0x800) == 0 { // if not empty
// string "i"
o = append(o, 0xa1, 0x69)
o = (*z).Reserve.MarshalMsg(o)
}
- if (zb0002Mask & 0x800) == 0 { // if not empty
+ if (zb0002Mask & 0x1000) == 0 { // if not empty
// string "j"
o = append(o, 0xa1, 0x6a)
o = (*z).Freeze.MarshalMsg(o)
}
- if (zb0002Mask & 0x1000) == 0 { // if not empty
+ if (zb0002Mask & 0x2000) == 0 { // if not empty
// string "k"
o = append(o, 0xa1, 0x6b)
o = (*z).Clawback.MarshalMsg(o)
}
- if (zb0002Mask & 0x2000) == 0 { // if not empty
+ if (zb0002Mask & 0x4000) == 0 { // if not empty
// string "l"
o = append(o, 0xa1, 0x6c)
o = msgp.AppendUint64(o, (*z).Amount)
}
- if (zb0002Mask & 0x4000) == 0 { // if not empty
+ if (zb0002Mask & 0x8000) == 0 { // if not empty
// string "m"
o = append(o, 0xa1, 0x6d)
o = msgp.AppendBool(o, (*z).Frozen)
}
- if (zb0002Mask & 0x8000) == 0 { // if not empty
+ if (zb0002Mask & 0x10000) == 0 { // if not empty
// string "n"
o = append(o, 0xa1, 0x6e)
o = msgp.AppendUint64(o, (*z).SchemaNumUint)
}
- if (zb0002Mask & 0x10000) == 0 { // if not empty
+ if (zb0002Mask & 0x20000) == 0 { // if not empty
// string "o"
o = append(o, 0xa1, 0x6f)
o = msgp.AppendUint64(o, (*z).SchemaNumByteSlice)
}
- if (zb0002Mask & 0x20000) == 0 { // if not empty
+ if (zb0002Mask & 0x40000) == 0 { // if not empty
// string "p"
o = append(o, 0xa1, 0x70)
o = (*z).KeyValue.MarshalMsg(o)
}
- if (zb0002Mask & 0x40000) == 0 { // if not empty
+ if (zb0002Mask & 0x80000) == 0 { // if not empty
// string "q"
o = append(o, 0xa1, 0x71)
o = msgp.AppendBytes(o, (*z).ApprovalProgram)
}
- if (zb0002Mask & 0x80000) == 0 { // if not empty
+ if (zb0002Mask & 0x100000) == 0 { // if not empty
// string "r"
o = append(o, 0xa1, 0x72)
o = msgp.AppendBytes(o, (*z).ClearStateProgram)
}
- if (zb0002Mask & 0x100000) == 0 { // if not empty
+ if (zb0002Mask & 0x200000) == 0 { // if not empty
// string "s"
o = append(o, 0xa1, 0x73)
o = (*z).GlobalState.MarshalMsg(o)
}
- if (zb0002Mask & 0x200000) == 0 { // if not empty
+ if (zb0002Mask & 0x400000) == 0 { // if not empty
// string "t"
o = append(o, 0xa1, 0x74)
o = msgp.AppendUint64(o, (*z).LocalStateSchemaNumUint)
}
- if (zb0002Mask & 0x400000) == 0 { // if not empty
+ if (zb0002Mask & 0x800000) == 0 { // if not empty
// string "u"
o = append(o, 0xa1, 0x75)
o = msgp.AppendUint64(o, (*z).LocalStateSchemaNumByteSlice)
}
- if (zb0002Mask & 0x800000) == 0 { // if not empty
+ if (zb0002Mask & 0x1000000) == 0 { // if not empty
// string "v"
o = append(o, 0xa1, 0x76)
o = msgp.AppendUint64(o, (*z).GlobalStateSchemaNumUint)
}
- if (zb0002Mask & 0x1000000) == 0 { // if not empty
+ if (zb0002Mask & 0x2000000) == 0 { // if not empty
// string "w"
o = append(o, 0xa1, 0x77)
o = msgp.AppendUint64(o, (*z).GlobalStateSchemaNumByteSlice)
}
- if (zb0002Mask & 0x2000000) == 0 { // if not empty
+ if (zb0002Mask & 0x4000000) == 0 { // if not empty
// string "x"
o = append(o, 0xa1, 0x78)
o = msgp.AppendUint32(o, (*z).ExtraProgramPages)
}
- if (zb0002Mask & 0x4000000) == 0 { // if not empty
+ if (zb0002Mask & 0x8000000) == 0 { // if not empty
// string "y"
o = append(o, 0xa1, 0x79)
o = msgp.AppendUint8(o, uint8((*z).ResourceFlags))
}
- if (zb0002Mask & 0x8000000) == 0 { // if not empty
+ if (zb0002Mask & 0x10000000) == 0 { // if not empty
// string "z"
o = append(o, 0xa1, 0x7a)
o = msgp.AppendUint64(o, (*z).UpdateRound)
@@ -2258,6 +2267,14 @@ func (z *ResourcesData) UnmarshalMsgWithState(bts []byte, st msgp.UnmarshalState
return
}
}
+ if zb0002 > 0 {
+ zb0002--
+ bts, err = (*z).SizeSponsor.UnmarshalMsgWithState(bts, st)
+ if err != nil {
+ err = msgp.WrapError(err, "struct-from-array", "SizeSponsor")
+ return
+ }
+ }
if zb0002 > 0 {
err = msgp.ErrTooManyArrayFields(zb0002)
if err != nil {
@@ -2467,6 +2484,12 @@ func (z *ResourcesData) UnmarshalMsgWithState(bts []byte, st msgp.UnmarshalState
err = msgp.WrapError(err, "Version")
return
}
+ case "B":
+ bts, err = (*z).SizeSponsor.UnmarshalMsgWithState(bts, st)
+ if err != nil {
+ err = msgp.WrapError(err, "SizeSponsor")
+ return
+ }
default:
err = msgp.ErrNoField(string(field))
if err != nil {
@@ -2490,16 +2513,16 @@ func (_ *ResourcesData) CanUnmarshalMsg(z interface{}) bool {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *ResourcesData) Msgsize() (s int) {
- s = 3 + 2 + msgp.Uint64Size + 2 + msgp.Uint32Size + 2 + msgp.BoolSize + 2 + msgp.StringPrefixSize + len((*z).UnitName) + 2 + msgp.StringPrefixSize + len((*z).AssetName) + 2 + msgp.StringPrefixSize + len((*z).URL) + 2 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 2 + (*z).Manager.Msgsize() + 2 + (*z).Reserve.Msgsize() + 2 + (*z).Freeze.Msgsize() + 2 + (*z).Clawback.Msgsize() + 2 + msgp.Uint64Size + 2 + msgp.BoolSize + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + (*z).KeyValue.Msgsize() + 2 + msgp.BytesPrefixSize + len((*z).ApprovalProgram) + 2 + msgp.BytesPrefixSize + len((*z).ClearStateProgram) + 2 + (*z).GlobalState.Msgsize() + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.Uint32Size + 2 + msgp.Uint8Size + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size
+ s = 3 + 2 + msgp.Uint64Size + 2 + msgp.Uint32Size + 2 + msgp.BoolSize + 2 + msgp.StringPrefixSize + len((*z).UnitName) + 2 + msgp.StringPrefixSize + len((*z).AssetName) + 2 + msgp.StringPrefixSize + len((*z).URL) + 2 + msgp.ArrayHeaderSize + (32 * (msgp.ByteSize)) + 2 + (*z).Manager.Msgsize() + 2 + (*z).Reserve.Msgsize() + 2 + (*z).Freeze.Msgsize() + 2 + (*z).Clawback.Msgsize() + 2 + msgp.Uint64Size + 2 + msgp.BoolSize + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + (*z).KeyValue.Msgsize() + 2 + msgp.BytesPrefixSize + len((*z).ApprovalProgram) + 2 + msgp.BytesPrefixSize + len((*z).ClearStateProgram) + 2 + (*z).GlobalState.Msgsize() + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + msgp.Uint32Size + 2 + msgp.Uint8Size + 2 + msgp.Uint64Size + 2 + msgp.Uint64Size + 2 + (*z).SizeSponsor.Msgsize()
return
}
// MsgIsZero returns whether this is a zero value
func (z *ResourcesData) MsgIsZero() bool {
- return ((*z).Total == 0) && ((*z).Decimals == 0) && ((*z).DefaultFrozen == false) && ((*z).UnitName == "") && ((*z).AssetName == "") && ((*z).URL == "") && ((*z).MetadataHash == ([32]byte{})) && ((*z).Manager.MsgIsZero()) && ((*z).Reserve.MsgIsZero()) && ((*z).Freeze.MsgIsZero()) && ((*z).Clawback.MsgIsZero()) && ((*z).Amount == 0) && ((*z).Frozen == false) && ((*z).SchemaNumUint == 0) && ((*z).SchemaNumByteSlice == 0) && ((*z).KeyValue.MsgIsZero()) && (len((*z).ApprovalProgram) == 0) && (len((*z).ClearStateProgram) == 0) && ((*z).GlobalState.MsgIsZero()) && ((*z).LocalStateSchemaNumUint == 0) && ((*z).LocalStateSchemaNumByteSlice == 0) && ((*z).GlobalStateSchemaNumUint == 0) && ((*z).GlobalStateSchemaNumByteSlice == 0) && ((*z).ExtraProgramPages == 0) && ((*z).ResourceFlags == 0) && ((*z).UpdateRound == 0) && ((*z).Version == 0)
+ return ((*z).Total == 0) && ((*z).Decimals == 0) && ((*z).DefaultFrozen == false) && ((*z).UnitName == "") && ((*z).AssetName == "") && ((*z).URL == "") && ((*z).MetadataHash == ([32]byte{})) && ((*z).Manager.MsgIsZero()) && ((*z).Reserve.MsgIsZero()) && ((*z).Freeze.MsgIsZero()) && ((*z).Clawback.MsgIsZero()) && ((*z).Amount == 0) && ((*z).Frozen == false) && ((*z).SchemaNumUint == 0) && ((*z).SchemaNumByteSlice == 0) && ((*z).KeyValue.MsgIsZero()) && (len((*z).ApprovalProgram) == 0) && (len((*z).ClearStateProgram) == 0) && ((*z).GlobalState.MsgIsZero()) && ((*z).LocalStateSchemaNumUint == 0) && ((*z).LocalStateSchemaNumByteSlice == 0) && ((*z).GlobalStateSchemaNumUint == 0) && ((*z).GlobalStateSchemaNumByteSlice == 0) && ((*z).ExtraProgramPages == 0) && ((*z).ResourceFlags == 0) && ((*z).UpdateRound == 0) && ((*z).Version == 0) && ((*z).SizeSponsor.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// ResourcesDataMaxSize returns a maximum valid message size for this message type
func ResourcesDataMaxSize() (s int) {
s = 3 + 2 + msgp.Uint64Size + 2 + msgp.Uint32Size + 2 + msgp.BoolSize + 2
panic("Unable to determine max size: String type z.UnitName is unbounded")
@@ -2817,7 +2840,7 @@ func (z *TxTailRound) MsgIsZero() bool {
return (len((*z).TxnIDs) == 0) && (len((*z).LastValid) == 0) && (len((*z).Leases) == 0) && ((*z).Hdr.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// TxTailRoundMaxSize returns a maximum valid message size for this message type
func TxTailRoundMaxSize() (s int) {
s = 1 + 2
// Calculating size of slice: z.TxnIDs
@@ -2984,7 +3007,7 @@ func (z *TxTailRoundLease) MsgIsZero() bool {
return ((*z).Sender.MsgIsZero()) && ((*z).Lease == ([32]byte{})) && ((*z).TxnIdx == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// TxTailRoundLeaseMaxSize returns a maximum valid message size for this message type
func TxTailRoundLeaseMaxSize() (s int) {
s = 1 + 2 + basics.AddressMaxSize() + 2
// Calculating size of array: z.Lease
diff --git a/ledger/store/trackerdb/msgp_gen_test.go b/ledger/store/trackerdb/msgp_gen_test.go
index be8a232c32..f6965c5778 100644
--- a/ledger/store/trackerdb/msgp_gen_test.go
+++ b/ledger/store/trackerdb/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package trackerdb
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package trackerdb
+
import (
"testing"
diff --git a/ledger/store/trackerdb/params.go b/ledger/store/trackerdb/params.go
index af8c2ed8cb..14bc4add4e 100644
--- a/ledger/store/trackerdb/params.go
+++ b/ledger/store/trackerdb/params.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/pebbledbdriver/pebbledriver.go b/ledger/store/trackerdb/pebbledbdriver/pebbledriver.go
index 2e273d3a24..341457e024 100644
--- a/ledger/store/trackerdb/pebbledbdriver/pebbledriver.go
+++ b/ledger/store/trackerdb/pebbledbdriver/pebbledriver.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/pebbledbdriver/pebbledriver_arm.go b/ledger/store/trackerdb/pebbledbdriver/pebbledriver_arm.go
index 69cdf26f04..3ad23e9e1b 100644
--- a/ledger/store/trackerdb/pebbledbdriver/pebbledriver_arm.go
+++ b/ledger/store/trackerdb/pebbledbdriver/pebbledriver_arm.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/pebbledbdriver/testing.go b/ledger/store/trackerdb/pebbledbdriver/testing.go
index e3f29ed297..57483aa1b7 100644
--- a/ledger/store/trackerdb/pebbledbdriver/testing.go
+++ b/ledger/store/trackerdb/pebbledbdriver/testing.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/accountsV2.go b/ledger/store/trackerdb/sqlitedriver/accountsV2.go
index 967832fb49..d8eae963ae 100644
--- a/ledger/store/trackerdb/sqlitedriver/accountsV2.go
+++ b/ledger/store/trackerdb/sqlitedriver/accountsV2.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/accountsV2_test.go b/ledger/store/trackerdb/sqlitedriver/accountsV2_test.go
index d2fbc6c20e..d3c6dad6e6 100644
--- a/ledger/store/trackerdb/sqlitedriver/accountsV2_test.go
+++ b/ledger/store/trackerdb/sqlitedriver/accountsV2_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/catchpoint.go b/ledger/store/trackerdb/sqlitedriver/catchpoint.go
index c3a6c466b2..f3d8242af7 100644
--- a/ledger/store/trackerdb/sqlitedriver/catchpoint.go
+++ b/ledger/store/trackerdb/sqlitedriver/catchpoint.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/catchpointPendingHashesIter.go b/ledger/store/trackerdb/sqlitedriver/catchpointPendingHashesIter.go
index 0692ad2a55..049bfc9fc1 100644
--- a/ledger/store/trackerdb/sqlitedriver/catchpointPendingHashesIter.go
+++ b/ledger/store/trackerdb/sqlitedriver/catchpointPendingHashesIter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/catchpoint_test.go b/ledger/store/trackerdb/sqlitedriver/catchpoint_test.go
index 4acc5d4410..aa5c54137c 100644
--- a/ledger/store/trackerdb/sqlitedriver/catchpoint_test.go
+++ b/ledger/store/trackerdb/sqlitedriver/catchpoint_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/encodedAccountsIter.go b/ledger/store/trackerdb/sqlitedriver/encodedAccountsIter.go
index 895efad6ed..79861c74d6 100644
--- a/ledger/store/trackerdb/sqlitedriver/encodedAccountsIter.go
+++ b/ledger/store/trackerdb/sqlitedriver/encodedAccountsIter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/kvsIter.go b/ledger/store/trackerdb/sqlitedriver/kvsIter.go
index 0bdd63e2c3..8ab2477b20 100644
--- a/ledger/store/trackerdb/sqlitedriver/kvsIter.go
+++ b/ledger/store/trackerdb/sqlitedriver/kvsIter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/merkle_committer.go b/ledger/store/trackerdb/sqlitedriver/merkle_committer.go
index 67c6e94ac2..8719863579 100644
--- a/ledger/store/trackerdb/sqlitedriver/merkle_committer.go
+++ b/ledger/store/trackerdb/sqlitedriver/merkle_committer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/orderedAccountsIter.go b/ledger/store/trackerdb/sqlitedriver/orderedAccountsIter.go
index 404548af66..9b40e03032 100644
--- a/ledger/store/trackerdb/sqlitedriver/orderedAccountsIter.go
+++ b/ledger/store/trackerdb/sqlitedriver/orderedAccountsIter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/schema.go b/ledger/store/trackerdb/sqlitedriver/schema.go
index 6993c0f72b..be2276ff6f 100644
--- a/ledger/store/trackerdb/sqlitedriver/schema.go
+++ b/ledger/store/trackerdb/sqlitedriver/schema.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/schema_test.go b/ledger/store/trackerdb/sqlitedriver/schema_test.go
index b2a8cf3aca..683d0932f6 100644
--- a/ledger/store/trackerdb/sqlitedriver/schema_test.go
+++ b/ledger/store/trackerdb/sqlitedriver/schema_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/spVerificationAccessor.go b/ledger/store/trackerdb/sqlitedriver/spVerificationAccessor.go
index a5b44a5832..09954a786a 100644
--- a/ledger/store/trackerdb/sqlitedriver/spVerificationAccessor.go
+++ b/ledger/store/trackerdb/sqlitedriver/spVerificationAccessor.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/sql.go b/ledger/store/trackerdb/sqlitedriver/sql.go
index f69363536b..f88adb7611 100644
--- a/ledger/store/trackerdb/sqlitedriver/sql.go
+++ b/ledger/store/trackerdb/sqlitedriver/sql.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/sql_test.go b/ledger/store/trackerdb/sqlitedriver/sql_test.go
index 7b48f1a352..ac00b397d9 100644
--- a/ledger/store/trackerdb/sqlitedriver/sql_test.go
+++ b/ledger/store/trackerdb/sqlitedriver/sql_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/sqlitedriver.go b/ledger/store/trackerdb/sqlitedriver/sqlitedriver.go
index a0fec44233..5f8e2c040a 100644
--- a/ledger/store/trackerdb/sqlitedriver/sqlitedriver.go
+++ b/ledger/store/trackerdb/sqlitedriver/sqlitedriver.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/testing.go b/ledger/store/trackerdb/sqlitedriver/testing.go
index f3f096166b..0f7bab6307 100644
--- a/ledger/store/trackerdb/sqlitedriver/testing.go
+++ b/ledger/store/trackerdb/sqlitedriver/testing.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/sqlitedriver/trackerdbV2.go b/ledger/store/trackerdb/sqlitedriver/trackerdbV2.go
index c59873d7f9..101b7c41c3 100644
--- a/ledger/store/trackerdb/sqlitedriver/trackerdbV2.go
+++ b/ledger/store/trackerdb/sqlitedriver/trackerdbV2.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/store.go b/ledger/store/trackerdb/store.go
index 5ee09894f6..0609d82f83 100644
--- a/ledger/store/trackerdb/store.go
+++ b/ledger/store/trackerdb/store.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testdb/testdb.go b/ledger/store/trackerdb/testdb/testdb.go
index 48e93d63d3..21ab15c873 100644
--- a/ledger/store/trackerdb/testdb/testdb.go
+++ b/ledger/store/trackerdb/testdb/testdb.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testinterface.go b/ledger/store/trackerdb/testinterface.go
index ce90faabb7..b09255d677 100644
--- a/ledger/store/trackerdb/testinterface.go
+++ b/ledger/store/trackerdb/testinterface.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testsuite/accounts_ext_kv_test.go b/ledger/store/trackerdb/testsuite/accounts_ext_kv_test.go
index f6d6852b26..f2b5c79fd2 100644
--- a/ledger/store/trackerdb/testsuite/accounts_ext_kv_test.go
+++ b/ledger/store/trackerdb/testsuite/accounts_ext_kv_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testsuite/accounts_kv_test.go b/ledger/store/trackerdb/testsuite/accounts_kv_test.go
index 9759517c5a..99c7d00e95 100644
--- a/ledger/store/trackerdb/testsuite/accounts_kv_test.go
+++ b/ledger/store/trackerdb/testsuite/accounts_kv_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testsuite/dbsemantics_test.go b/ledger/store/trackerdb/testsuite/dbsemantics_test.go
index d38f2ddf34..72ea207462 100644
--- a/ledger/store/trackerdb/testsuite/dbsemantics_test.go
+++ b/ledger/store/trackerdb/testsuite/dbsemantics_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testsuite/dual_test.go b/ledger/store/trackerdb/testsuite/dual_test.go
index 2ded73fe81..1b3e5cf6c0 100644
--- a/ledger/store/trackerdb/testsuite/dual_test.go
+++ b/ledger/store/trackerdb/testsuite/dual_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testsuite/migration_test.go b/ledger/store/trackerdb/testsuite/migration_test.go
index 3bcd2525c6..aa3060765d 100644
--- a/ledger/store/trackerdb/testsuite/migration_test.go
+++ b/ledger/store/trackerdb/testsuite/migration_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testsuite/mockdb_test.go b/ledger/store/trackerdb/testsuite/mockdb_test.go
index 2aebd87e58..28fdf056ff 100644
--- a/ledger/store/trackerdb/testsuite/mockdb_test.go
+++ b/ledger/store/trackerdb/testsuite/mockdb_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testsuite/onlineaccounts_kv_test.go b/ledger/store/trackerdb/testsuite/onlineaccounts_kv_test.go
index 9c0be20a60..fb65f49b93 100644
--- a/ledger/store/trackerdb/testsuite/onlineaccounts_kv_test.go
+++ b/ledger/store/trackerdb/testsuite/onlineaccounts_kv_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testsuite/pebbledb_test.go b/ledger/store/trackerdb/testsuite/pebbledb_test.go
index 39f04f7e94..fd3d42864c 100644
--- a/ledger/store/trackerdb/testsuite/pebbledb_test.go
+++ b/ledger/store/trackerdb/testsuite/pebbledb_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testsuite/sqlitedb_test.go b/ledger/store/trackerdb/testsuite/sqlitedb_test.go
index c0cf86e8d0..94a6b93634 100644
--- a/ledger/store/trackerdb/testsuite/sqlitedb_test.go
+++ b/ledger/store/trackerdb/testsuite/sqlitedb_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testsuite/stateproofs_kv_test.go b/ledger/store/trackerdb/testsuite/stateproofs_kv_test.go
index e474f5a8c4..a211257826 100644
--- a/ledger/store/trackerdb/testsuite/stateproofs_kv_test.go
+++ b/ledger/store/trackerdb/testsuite/stateproofs_kv_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/testsuite/utils_test.go b/ledger/store/trackerdb/testsuite/utils_test.go
index 77b55db9fd..658c852231 100644
--- a/ledger/store/trackerdb/testsuite/utils_test.go
+++ b/ledger/store/trackerdb/testsuite/utils_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/utils.go b/ledger/store/trackerdb/utils.go
index ee4c1f2276..076eec7d67 100644
--- a/ledger/store/trackerdb/utils.go
+++ b/ledger/store/trackerdb/utils.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/store/trackerdb/version.go b/ledger/store/trackerdb/version.go
index e82df68a1d..3221f4b267 100644
--- a/ledger/store/trackerdb/version.go
+++ b/ledger/store/trackerdb/version.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/testing/accountsTotals.go b/ledger/testing/accountsTotals.go
index d9e2239087..3de72a7d40 100644
--- a/ledger/testing/accountsTotals.go
+++ b/ledger/testing/accountsTotals.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/testing/consensusRange.go b/ledger/testing/consensusRange.go
index c6d3265cbc..13b5f2f61b 100644
--- a/ledger/testing/consensusRange.go
+++ b/ledger/testing/consensusRange.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/testing/consensusRange_test.go b/ledger/testing/consensusRange_test.go
index fd30e47c5d..1b50e4b1ef 100644
--- a/ledger/testing/consensusRange_test.go
+++ b/ledger/testing/consensusRange_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/testing/initState.go b/ledger/testing/initState.go
index d4a0217f0a..774b811499 100644
--- a/ledger/testing/initState.go
+++ b/ledger/testing/initState.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/testing/randomAccounts.go b/ledger/testing/randomAccounts.go
index 0b0dffbd8c..ee5a5a6f66 100644
--- a/ledger/testing/randomAccounts.go
+++ b/ledger/testing/randomAccounts.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -193,6 +193,13 @@ func RandomAppParams() basics.AppParams {
ap.ClearStateProgram = nil
}
+ // The can only be a sponsor if there's extra storage
+ if ap.ExtraProgramPages > 0 && !ap.StateSchemas.GlobalStateSchema.Empty() {
+ if crypto.RandUint63()%2 == 0 {
+ crypto.RandBytes(ap.SizeSponsor[:])
+ }
+ }
+
for i := uint64(0); i < ap.StateSchemas.GlobalStateSchema.NumUint; i++ {
var keyName string
if crypto.RandUint64()%5 != 0 {
diff --git a/ledger/testing/randomAccounts_test.go b/ledger/testing/randomAccounts_test.go
index bb5d68df91..cadd9aa1cb 100644
--- a/ledger/testing/randomAccounts_test.go
+++ b/ledger/testing/randomAccounts_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -39,7 +39,7 @@ func TestAccounts(t *testing.T) {
return true
}
stackTop := stack[len(stack)-1]
- if path[len(path)-1].FieldName == "_struct" && stackTop == reflect.TypeOf(struct{}{}) {
+ if path[len(path)-1].FieldName == "_struct" && stackTop == reflect.TypeFor[struct{}]() {
// Ignore the informational _struct field
return true
}
diff --git a/ledger/testing/testGenesis.go b/ledger/testing/testGenesis.go
index 353f68b5bd..7f4d09ba2b 100644
--- a/ledger/testing/testGenesis.go
+++ b/ledger/testing/testGenesis.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/testing/withAndWithoutCache.go b/ledger/testing/withAndWithoutCache.go
index 7de37463c6..87cd617627 100644
--- a/ledger/testing/withAndWithoutCache.go
+++ b/ledger/testing/withAndWithoutCache.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/tracker.go b/ledger/tracker.go
index faa4359fc8..3b95df3240 100644
--- a/ledger/tracker.go
+++ b/ledger/tracker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/tracker_test.go b/ledger/tracker_test.go
index 06563b6e88..074b6c4006 100644
--- a/ledger/tracker_test.go
+++ b/ledger/tracker_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/trackerdb.go b/ledger/trackerdb.go
index 46e6dcaf9d..3fe36cb2c1 100644
--- a/ledger/trackerdb.go
+++ b/ledger/trackerdb.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/txnbench_test.go b/ledger/txnbench_test.go
index 7cee882d9c..99d854998a 100644
--- a/ledger/txnbench_test.go
+++ b/ledger/txnbench_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -24,7 +24,6 @@ import (
"github.com/algorand/go-algorand/config"
"github.com/algorand/go-algorand/data/basics"
- "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"
@@ -237,7 +236,7 @@ func BenchmarkTxnTypes(b *testing.B) {
signed := t.SignedTxn()
for n := 0; n < b.N; n++ {
signed.Txn.Note = []byte(strconv.Itoa(n))
- err := eval.Transaction(signed, transactions.ApplyData{})
+ err := eval.TransactionGroup(signed.WithAD())
if errors.Is(err, ledgercore.ErrNoSpace) {
endBlock(b, l, eval)
eval = nextBlock(b, l)
diff --git a/ledger/txtail.go b/ledger/txtail.go
index 51fed0cb39..84d7ed1b94 100644
--- a/ledger/txtail.go
+++ b/ledger/txtail.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/txtail_test.go b/ledger/txtail_test.go
index a49c052338..6e6b26f428 100644
--- a/ledger/txtail_test.go
+++ b/ledger/txtail_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/voters.go b/ledger/voters.go
index a4794edd4d..d7e8b3aee5 100644
--- a/ledger/voters.go
+++ b/ledger/voters.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/ledger/voters_test.go b/ledger/voters_test.go
index 7b2179a775..56a7f61fc8 100644
--- a/ledger/voters_test.go
+++ b/ledger/voters_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/accounts.go b/libgoal/accounts.go
index 4c90682379..5ee2238c6c 100644
--- a/libgoal/accounts.go
+++ b/libgoal/accounts.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/error.go b/libgoal/error.go
index 7921deb093..51022ba589 100644
--- a/libgoal/error.go
+++ b/libgoal/error.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/libgoal.go b/libgoal/libgoal.go
index c3fe8d4d42..876c0778ff 100644
--- a/libgoal/libgoal.go
+++ b/libgoal/libgoal.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -135,7 +135,7 @@ func MakeClientFromConfig(config ClientConfig, clientType ClientType) (c Client,
return
}
-// Init takes data directory path or an empty string if $ALGORAND_DATA is defined and initializes Client
+// init takes data directory path or an empty string if $ALGORAND_DATA is defined and initializes Client
func (c *Client) init(config ClientConfig, clientType ClientType) error {
// check and assign dataDir
dataDir, err := getDataDir(config.AlgodDataDir)
diff --git a/libgoal/libgoal_test.go b/libgoal/libgoal_test.go
index eb4fb4f766..9a008d9bf2 100644
--- a/libgoal/libgoal_test.go
+++ b/libgoal/libgoal_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/lockedFile.go b/libgoal/lockedFile.go
index d15ec0a5e4..69488f7a73 100644
--- a/libgoal/lockedFile.go
+++ b/libgoal/lockedFile.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/lockedFileLinux.go b/libgoal/lockedFileLinux.go
index dee4507d50..285baccb9e 100644
--- a/libgoal/lockedFileLinux.go
+++ b/libgoal/lockedFileLinux.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//go:build linux
-// +build linux
package libgoal
diff --git a/libgoal/lockedFileUnix.go b/libgoal/lockedFileUnix.go
index cf37214769..c66b9e14b5 100644
--- a/libgoal/lockedFileUnix.go
+++ b/libgoal/lockedFileUnix.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -18,7 +18,6 @@
// in https://github.com/golang/sys/blob/master/unix/syscall_unix.go
//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd || solaris
-// +build aix darwin dragonfly freebsd netbsd openbsd solaris
package libgoal
diff --git a/libgoal/lockedFileWindows.go b/libgoal/lockedFileWindows.go
index 42000513c5..516f411026 100644
--- a/libgoal/lockedFileWindows.go
+++ b/libgoal/lockedFileWindows.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//go:build windows
-// +build windows
package libgoal
diff --git a/libgoal/participation.go b/libgoal/participation.go
index 48a08be64d..2aaec78570 100644
--- a/libgoal/participation.go
+++ b/libgoal/participation.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/participation/participation.go b/libgoal/participation/participation.go
index 2f93b5f9fa..770af0dedd 100644
--- a/libgoal/participation/participation.go
+++ b/libgoal/participation/participation.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/participation/participation_test.go b/libgoal/participation/participation_test.go
index 66f44224e7..e5f8187dc8 100644
--- a/libgoal/participation/participation_test.go
+++ b/libgoal/participation/participation_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/system.go b/libgoal/system.go
index 0f3a2d0bf4..c3a25a6560 100644
--- a/libgoal/system.go
+++ b/libgoal/system.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/teal.go b/libgoal/teal.go
index a87c4519fe..f4b59ca794 100644
--- a/libgoal/teal.go
+++ b/libgoal/teal.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/transactions.go b/libgoal/transactions.go
index 38fafabd9c..eac5d9b07f 100644
--- a/libgoal/transactions.go
+++ b/libgoal/transactions.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/unencryptedWallet.go b/libgoal/unencryptedWallet.go
index 0f9db7fbac..b8b24e502b 100644
--- a/libgoal/unencryptedWallet.go
+++ b/libgoal/unencryptedWallet.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/walletHandles.go b/libgoal/walletHandles.go
index 425d32b92e..8a7d7ccc20 100644
--- a/libgoal/walletHandles.go
+++ b/libgoal/walletHandles.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/libgoal/wallets.go b/libgoal/wallets.go
index 394f22a9ab..6dc0bdc9ff 100644
--- a/libgoal/wallets.go
+++ b/libgoal/wallets.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/collector.go b/logging/collector.go
index 8ab8094090..553206fd74 100644
--- a/logging/collector.go
+++ b/logging/collector.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/cyclicWriter.go b/logging/cyclicWriter.go
index f2f75c7831..45f40718a5 100644
--- a/logging/cyclicWriter.go
+++ b/logging/cyclicWriter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/cyclicWriter_test.go b/logging/cyclicWriter_test.go
index 398d830b57..7c16e730b7 100644
--- a/logging/cyclicWriter_test.go
+++ b/logging/cyclicWriter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/logBuffer.go b/logging/logBuffer.go
index 0c00523c09..41f083cd3e 100644
--- a/logging/logBuffer.go
+++ b/logging/logBuffer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/logBuffer_test.go b/logging/logBuffer_test.go
index f9cc57c192..cb448d40ba 100644
--- a/logging/logBuffer_test.go
+++ b/logging/logBuffer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/log_test.go b/logging/log_test.go
index c0d4ede2ad..4df219f26e 100644
--- a/logging/log_test.go
+++ b/logging/log_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/logspec/agreement.go b/logging/logspec/agreement.go
index bf320daee4..c385472ec5 100644
--- a/logging/logspec/agreement.go
+++ b/logging/logspec/agreement.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -24,7 +24,7 @@ import (
// AgreementType is an enum identifying a specific type of AgreementEvent
// TODO Maybe this should be called AgreementEventType, since these are not actually types of agreements
//
-//go:generate stringer -type=AgreementType
+//go:generate go tool -modfile=../../tool.mod stringer -type=AgreementType
type AgreementType int
const (
diff --git a/logging/logspec/agreementtype_string.go b/logging/logspec/agreementtype_string.go
index 7f9cb45679..bbccd1c653 100644
--- a/logging/logspec/agreementtype_string.go
+++ b/logging/logspec/agreementtype_string.go
@@ -42,8 +42,9 @@ const _AgreementType_name = "RoundConcludedPeriodConcludedStepTimeoutRoundStartR
var _AgreementType_index = [...]uint16{0, 14, 29, 40, 50, 66, 78, 94, 108, 124, 141, 158, 172, 188, 204, 217, 228, 242, 252, 265, 277, 289, 304, 318, 332, 340, 349, 366}
func (i AgreementType) String() string {
- if i < 0 || i >= AgreementType(len(_AgreementType_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_AgreementType_index)-1 {
return "AgreementType(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _AgreementType_name[_AgreementType_index[i]:_AgreementType_index[i+1]]
+ return _AgreementType_name[_AgreementType_index[idx]:_AgreementType_index[idx+1]]
}
diff --git a/logging/logspec/component_string.go b/logging/logspec/component_string.go
index 91490b95d9..5383758b91 100644
--- a/logging/logspec/component_string.go
+++ b/logging/logspec/component_string.go
@@ -21,8 +21,9 @@ const _Component_name = "AgreementCatchupNetworkLedgerFrontendnumComponents"
var _Component_index = [...]uint8{0, 9, 16, 23, 29, 37, 50}
func (i Component) String() string {
- if i < 0 || i >= Component(len(_Component_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_Component_index)-1 {
return "Component(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _Component_name[_Component_index[i]:_Component_index[i+1]]
+ return _Component_name[_Component_index[idx]:_Component_index[idx+1]]
}
diff --git a/logging/logspec/ledger.go b/logging/logspec/ledger.go
index 2d06cf2315..052559887b 100644
--- a/logging/logspec/ledger.go
+++ b/logging/logspec/ledger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -24,7 +24,7 @@ import (
// LedgerType is an enum identifying a specific type of LedgerEvent
// TODO Maybe this should be called LedgerEventType, since these are not actually types of ledgers
//
-//go:generate stringer -type=LedgerType
+//go:generate go tool -modfile=../../tool.mod stringer -type=LedgerType
type LedgerType int
const (
diff --git a/logging/logspec/ledgertype_string.go b/logging/logspec/ledgertype_string.go
index 81e62e2d8b..e003033762 100644
--- a/logging/logspec/ledgertype_string.go
+++ b/logging/logspec/ledgertype_string.go
@@ -17,8 +17,9 @@ const _LedgerType_name = "WroteBlocknumLedgerTypes"
var _LedgerType_index = [...]uint8{0, 10, 24}
func (i LedgerType) String() string {
- if i < 0 || i >= LedgerType(len(_LedgerType_index)-1) {
+ idx := int(i) - 0
+ if i < 0 || idx >= len(_LedgerType_index)-1 {
return "LedgerType(" + strconv.FormatInt(int64(i), 10) + ")"
}
- return _LedgerType_name[_LedgerType_index[i]:_LedgerType_index[i+1]]
+ return _LedgerType_name[_LedgerType_index[idx]:_LedgerType_index[idx+1]]
}
diff --git a/logging/logspec/root.go b/logging/logspec/root.go
index 77852b97cb..feb607d7dd 100644
--- a/logging/logspec/root.go
+++ b/logging/logspec/root.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -26,7 +26,7 @@ import (
// TODO Maybe this should be called ComponentEventType (and change Event to ComponentEvent),
// since these are not actually types of components
//
-//go:generate stringer -type=Component
+//go:generate go tool -modfile=../../tool.mod stringer -type=Component
type Component int
const (
diff --git a/logging/telemetry.go b/logging/telemetry.go
index 8e69ec02a4..d9929a739d 100644
--- a/logging/telemetry.go
+++ b/logging/telemetry.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryCommon.go b/logging/telemetryCommon.go
index ac187f7857..a7d087d1aa 100644
--- a/logging/telemetryCommon.go
+++ b/logging/telemetryCommon.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryConfig.go b/logging/telemetryConfig.go
index 9c69c77d88..f523a653df 100644
--- a/logging/telemetryConfig.go
+++ b/logging/telemetryConfig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryConfig_test.go b/logging/telemetryConfig_test.go
index 379b4b7f20..b99415e5ae 100644
--- a/logging/telemetryConfig_test.go
+++ b/logging/telemetryConfig_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryFilteredHook.go b/logging/telemetryFilteredHook.go
index 0d956ef08e..9f8eb795fe 100644
--- a/logging/telemetryFilteredHook.go
+++ b/logging/telemetryFilteredHook.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -33,7 +33,7 @@ type telemetryFilteredHook struct {
levels []logrus.Level
}
-// newFilteredTelemetryHook creates a hook filter for ensuring telemetry events are
+// newTelemetryFilteredHook creates a hook filter for ensuring telemetry events are
// always included by the wrapped log hook.
func newTelemetryFilteredHook(cfg TelemetryConfig, hook logrus.Hook, reportLogLevel logrus.Level, history *logBuffer, sessionGUID string, factory hookFactory, levels []logrus.Level) (logrus.Hook, error) {
filteredHook := &telemetryFilteredHook{
diff --git a/logging/telemetry_test.go b/logging/telemetry_test.go
index 6975038eaf..d26af18a46 100644
--- a/logging/telemetry_test.go
+++ b/logging/telemetry_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryhook.go b/logging/telemetryhook.go
index 86253879ec..e70f289f2b 100644
--- a/logging/telemetryhook.go
+++ b/logging/telemetryhook.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -257,7 +257,7 @@ func createElasticHookContext(ctx context.Context, cfg TelemetryConfig) (hook lo
return hook, err
}
-// createTelemetryHook creates the Telemetry log hook, or returns nil if remote logging is not enabled
+// createTelemetryHookContext creates the Telemetry log hook, or returns nil if remote logging is not enabled
func createTelemetryHookContext(ctx context.Context, cfg TelemetryConfig, history *logBuffer, hookFactory hookFactory) (hook logrus.Hook, err error) {
if !cfg.Enable {
return nil, fmt.Errorf("createTelemetryHook called when telemetry not enabled")
diff --git a/logging/telemetryhook_test.go b/logging/telemetryhook_test.go
index 417118696a..085bcaa21d 100644
--- a/logging/telemetryhook_test.go
+++ b/logging/telemetryhook_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryspec/category.go b/logging/telemetryspec/category.go
index 7b5a9bfb3d..10b2b49610 100644
--- a/logging/telemetryspec/category.go
+++ b/logging/telemetryspec/category.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryspec/event.go b/logging/telemetryspec/event.go
index a976987ecd..8cd583a192 100644
--- a/logging/telemetryspec/event.go
+++ b/logging/telemetryspec/event.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryspec/eventTiming.go b/logging/telemetryspec/eventTiming.go
index b3b4017a68..c387b4eab7 100644
--- a/logging/telemetryspec/eventTiming.go
+++ b/logging/telemetryspec/eventTiming.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryspec/metric.go b/logging/telemetryspec/metric.go
index 941e0c7b33..3222557e28 100644
--- a/logging/telemetryspec/metric.go
+++ b/logging/telemetryspec/metric.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/telemetryspec/metric_test.go b/logging/telemetryspec/metric_test.go
index af5a08eba7..be3bfdeb7d 100644
--- a/logging/telemetryspec/metric_test.go
+++ b/logging/telemetryspec/metric_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/testingLogger.go b/logging/testingLogger.go
index 0246b8cdcb..63aaf33a62 100644
--- a/logging/testingLogger.go
+++ b/logging/testingLogger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/logging/usage.go b/logging/usage.go
index 26115f73e3..8110e1c003 100644
--- a/logging/usage.go
+++ b/logging/usage.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/network.go b/netdeploy/network.go
index b49c9a2797..c23f68762f 100644
--- a/netdeploy/network.go
+++ b/netdeploy/network.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/networkTemplate.go b/netdeploy/networkTemplate.go
index 85f63997ed..51661778c9 100644
--- a/netdeploy/networkTemplate.go
+++ b/netdeploy/networkTemplate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/networkTemplates_test.go b/netdeploy/networkTemplates_test.go
index 13aff8d842..05149f4b30 100644
--- a/netdeploy/networkTemplates_test.go
+++ b/netdeploy/networkTemplates_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/network_test.go b/netdeploy/network_test.go
index 82f53fb78a..e2bb0db7d1 100644
--- a/netdeploy/network_test.go
+++ b/netdeploy/network_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/bootstrappedNetwork.go b/netdeploy/remote/bootstrappedNetwork.go
index aee34226b6..9c898fbb02 100644
--- a/netdeploy/remote/bootstrappedNetwork.go
+++ b/netdeploy/remote/bootstrappedNetwork.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/bootstrappedNetwork_test.go b/netdeploy/remote/bootstrappedNetwork_test.go
index 86b44051cc..b0761c4895 100644
--- a/netdeploy/remote/bootstrappedNetwork_test.go
+++ b/netdeploy/remote/bootstrappedNetwork_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/buildConfig.go b/netdeploy/remote/buildConfig.go
index ae00decf8c..c1eb5c6953 100644
--- a/netdeploy/remote/buildConfig.go
+++ b/netdeploy/remote/buildConfig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/deployedNetwork.go b/netdeploy/remote/deployedNetwork.go
index 14ada96393..09576a5a92 100644
--- a/netdeploy/remote/deployedNetwork.go
+++ b/netdeploy/remote/deployedNetwork.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/deployedNetwork_test.go b/netdeploy/remote/deployedNetwork_test.go
index fc9aabb333..4d89cf958f 100644
--- a/netdeploy/remote/deployedNetwork_test.go
+++ b/netdeploy/remote/deployedNetwork_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/hostConfig.go b/netdeploy/remote/hostConfig.go
index c261ca7c35..d288a3c827 100644
--- a/netdeploy/remote/hostConfig.go
+++ b/netdeploy/remote/hostConfig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/hostTemplate.go b/netdeploy/remote/hostTemplate.go
index 7971e12639..c536c90a82 100644
--- a/netdeploy/remote/hostTemplate.go
+++ b/netdeploy/remote/hostTemplate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/nodeConfig.go b/netdeploy/remote/nodeConfig.go
index abe257b1e4..16cbbd9730 100644
--- a/netdeploy/remote/nodeConfig.go
+++ b/netdeploy/remote/nodeConfig.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/nodeWalletData.go b/netdeploy/remote/nodeWalletData.go
index 0a54160582..e72185f167 100644
--- a/netdeploy/remote/nodeWalletData.go
+++ b/netdeploy/remote/nodeWalletData.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/nodecfg/nodeConfigurator.go b/netdeploy/remote/nodecfg/nodeConfigurator.go
index ab26d091ff..1327f1cca8 100644
--- a/netdeploy/remote/nodecfg/nodeConfigurator.go
+++ b/netdeploy/remote/nodecfg/nodeConfigurator.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/nodecfg/nodeDir.go b/netdeploy/remote/nodecfg/nodeDir.go
index f22f8b73f9..7800150d4c 100644
--- a/netdeploy/remote/nodecfg/nodeDir.go
+++ b/netdeploy/remote/nodecfg/nodeDir.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/netdeploy/remote/topology.go b/netdeploy/remote/topology.go
index 91feaac9e8..f9455d8c52 100644
--- a/netdeploy/remote/topology.go
+++ b/netdeploy/remote/topology.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/addr.go b/network/addr.go
index 402f1e4c76..a372dd7642 100644
--- a/network/addr.go
+++ b/network/addr.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/addr/addr.go b/network/addr/addr.go
index 0c90b1118d..53db9e30b8 100644
--- a/network/addr/addr.go
+++ b/network/addr/addr.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/addr/addr_test.go b/network/addr/addr_test.go
index d19889654a..9bf6a2ce9f 100644
--- a/network/addr/addr_test.go
+++ b/network/addr/addr_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/connPerfMon.go b/network/connPerfMon.go
index 1399e17097..58fe11df5c 100644
--- a/network/connPerfMon.go
+++ b/network/connPerfMon.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -46,7 +46,6 @@ const (
pmAccumulationIdlingTime = 2 * time.Second
pmMaxMessageWaitTime = 15 * time.Second
pmUndeliveredMessagePenaltyTime = 5 * time.Second
- pmDesiredMessegeDelayThreshold = 50 * time.Millisecond
pmMessageBucketDuration = time.Second
)
@@ -59,7 +58,7 @@ type pmMessage struct {
// pmPeerStatistics is the per-peer resulting datastructure of the performance analysis.
type pmPeerStatistics struct {
peer Peer // the peer interface
- peerDelay int64 // the peer avarage relative message delay
+ peerDelay int64 // the peer average relative message delay
peerFirstMessage float32 // what percentage of the messages were delivered by this peer before any other peer
}
@@ -197,7 +196,7 @@ func (pm *connectionPerformanceMonitor) Notify(msg *IncomingMessage) {
}
}
-// notifyPresync waits until pmPresyncTime has passed and monitor the last arrivial time
+// notifyPresync waits until pmPresyncTime has passed and monitors the last arrival time
// of messages from each of the peers.
func (pm *connectionPerformanceMonitor) notifyPresync(msg *IncomingMessage) {
pm.peerLastMsgTime[msg.Sender] = msg.Received
@@ -221,7 +220,7 @@ func (pm *connectionPerformanceMonitor) notifyPresync(msg *IncomingMessage) {
return
}
if len(noMsgPeers) > 0 {
- // we have one or more peers that did not send a single message thoughtout the presync time.
+ // we have one or more peers that did not send a single message throughout the presync time.
// ( but less than half ). since we cannot rely on these to send us messages in the future,
// we'll disconnect from these peers.
pm.advanceStage(pmStageStopped, msg.Received)
diff --git a/network/connPerfMon_test.go b/network/connPerfMon_test.go
index 9aae9ac029..8428da7dec 100644
--- a/network/connPerfMon_test.go
+++ b/network/connPerfMon_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -17,7 +17,10 @@
package network
import (
+ "encoding/binary"
"fmt"
+ "math/rand"
+ "sort"
"testing"
"time"
@@ -240,3 +243,182 @@ func TestNetworkAdvanceMonitor(t *testing.T) {
m.updateLastAdvance()
require.True(t, m.lastAdvancedWithin(500*time.Millisecond))
}
+
+// shuffleNormal reorders elements by assigning each element a priority based on
+// normal distribution centered at its original index, then sorting by priority.
+// The stddevFactor controls how much elements can move from their original position:
+// - smaller values (e.g., 0.1) keep elements closer to original positions
+// - larger values (e.g., 1.0) allow more mixing
+// - very large values approach uniform distribution behavior
+func shuffleNormal[T any](slice []T, stddevFactor float64) {
+ n := len(slice)
+ if n <= 1 {
+ return
+ }
+
+ // Each element gets a priority = originalIndex + normalRandom * stddev
+ // where stddev = stddevFactor * n
+ stddev := stddevFactor * float64(n)
+
+ type indexedItem struct {
+ original int
+ priority float64
+ item T
+ }
+
+ items := make([]indexedItem, n)
+ for i := range slice {
+ items[i] = indexedItem{
+ original: i,
+ priority: float64(i) + rand.NormFloat64()*stddev,
+ item: slice[i],
+ }
+ }
+
+ sort.Slice(items, func(i, j int) bool {
+ return items[i].priority < items[j].priority
+ })
+
+ for i := range slice {
+ slice[i] = items[i].item
+ }
+}
+
+func shuffleUniform[T any](slice []T) {
+ rand.Shuffle(len(slice), func(i, j int) {
+ slice[i], slice[j] = slice[j], slice[i]
+ })
+}
+
+func TestConnMonitor_Simulate(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ t.Skip("Use locally for conn perf logic adjustment as needed")
+
+ const (
+ numNoDupPeers = 2 // peers that provide only unique msgs
+ numDupPeers = 3 // peers that provide duplicate msgs
+ numDupPlusPeers = 3 // peers that provide "smart" duplicate msgs (like txn with changed note field)
+ dupRatio = 2 // each duplicate peer sends this many duplicates per message
+ smartDupRatio = 3 // each "smart" duplicate peer sends this many duplicates per message (including the original)
+ )
+ const numMsgsPerTick = 1*numNoDupPeers + (numDupPeers * dupRatio) + (numDupPlusPeers * smartDupRatio)
+
+ msgs := make([]IncomingMessage, numMsgsPerTick)
+ data := make([][]byte, numMsgsPerTick)
+ for i := range numMsgsPerTick {
+ data[i] = make([]byte, 10) // each msg data, 8 bytes for uint64 + 2 bytes for randomness
+ }
+
+ senders := make([]*wsPeer, numNoDupPeers+numDupPeers+numDupPlusPeers)
+ for i := range numNoDupPeers {
+ senders[i] = &wsPeer{wsPeerCore: wsPeerCore{rootURL: fmt.Sprintf("noDupPeer%d", i+1)}}
+ }
+ for i := range numDupPeers {
+ senders[numNoDupPeers+i] = &wsPeer{wsPeerCore: wsPeerCore{rootURL: fmt.Sprintf("dupPeer%d", i+1)}}
+ }
+ for i := range numDupPlusPeers {
+ senders[numNoDupPeers+numDupPeers+i] = &wsPeer{wsPeerCore: wsPeerCore{rootURL: fmt.Sprintf("dupPlusPeer%d", i+1)}}
+ }
+
+ nextTickMsgs := func(tick uint64, shuffleFn func([]IncomingMessage)) []IncomingMessage {
+ for i := range data {
+ binary.LittleEndian.PutUint64(data[i], tick)
+ }
+
+ // noDup peers
+ for i := range numNoDupPeers {
+ msgs[i] = IncomingMessage{
+ Tag: protocol.TxnTag,
+ Data: data[i],
+ Sender: senders[i],
+ }
+ }
+
+ // dup peers
+ for i := range numDupPeers {
+ for j := 0; j < dupRatio; j++ {
+ msgs[numNoDupPeers+i*dupRatio+j] = IncomingMessage{
+ Tag: protocol.TxnTag,
+ Data: data[numNoDupPeers+i],
+ Sender: senders[numNoDupPeers+i],
+ }
+ }
+ }
+
+ // "smart" dup peers
+ for i := range numDupPlusPeers {
+ for j := 0; j < smartDupRatio; j++ {
+ // change last byte to make data different
+ idx := numNoDupPeers + numDupPeers*dupRatio + i*smartDupRatio + j
+ data[idx][9] = byte(j)
+
+ msgs[idx] = IncomingMessage{
+ Tag: protocol.TxnTag,
+ Data: data[idx],
+ Sender: senders[numNoDupPeers+numDupPeers+i],
+ }
+ }
+ }
+
+ // for i := range msgs {
+ // t.Logf("tick %d: msg from %s data=%x\n", tick, msgs[i].Sender.(*wsPeer).rootURL, msgs[i].Data)
+ // }
+
+ // shuffle to simulate different receiving orders
+ shuffleFn(msgs)
+
+ now := time.Now().UnixNano()
+ for i := range msgs {
+ msgs[i].Received = now + int64(i*10)
+ }
+ return msgs
+ }
+
+ tests := []struct {
+ name string
+ shuffleFn func([]IncomingMessage)
+ }{
+ {
+ name: "normalShuffle",
+ shuffleFn: func(msgs []IncomingMessage) { shuffleNormal(msgs, 0.5) },
+ },
+ {
+ name: "uniformShuffle",
+ shuffleFn: shuffleUniform[IncomingMessage],
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+
+ mon := makeConnectionPerformanceMonitor([]Tag{protocol.TxnTag})
+ peers := make([]Peer, len(senders))
+ for i := range senders {
+ peers[i] = senders[i]
+ }
+ mon.Reset(peers)
+
+ i := uint64(0)
+ prevStage := -1
+ for mon.stage != pmStageStopped {
+ if int(mon.stage) != prevStage {
+ t.Logf("Monitor advanced to stage %d at tick %d\n", mon.stage, i)
+ prevStage = int(mon.stage)
+ }
+ msgs := nextTickMsgs(i, test.shuffleFn)
+ for _, msg := range msgs {
+ mon.Notify(&msg)
+ }
+ i++
+ }
+
+ // at the very end get stats
+ stats := mon.GetPeersStatistics()
+ t.Logf("%s: %d messages over %d ticks\n", test.name, mon.msgCount, i)
+ for _, ps := range stats.peerStatistics {
+ t.Logf("%s: delay=%d firstMessagePercentage=%.2f\n", ps.peer.(*wsPeer).rootURL, ps.peerDelay, ps.peerFirstMessage)
+ }
+ })
+ }
+}
diff --git a/network/gossipNode.go b/network/gossipNode.go
index 9594ee5e11..17840c905e 100644
--- a/network/gossipNode.go
+++ b/network/gossipNode.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -153,6 +153,11 @@ type IncomingMessage struct {
// Received is time.Time.UnixNano()
Received int64
+ // Outgoing indicates whether this was received on an outgoing (trusted) connection.
+ // Added to let knowing transaction handler's rate limiters more details about the peer.
+ // Set only for ws net peers since p2p network does not really have trusted outgoing connections.
+ Outgoing bool
+
// processing is a channel that is used by messageHandlerThread
// to indicate that it has started processing this message. It
// is used to ensure fairness across peers in terms of processing
diff --git a/network/hybridNetwork.go b/network/hybridNetwork.go
index 45c49d840c..be5cc19e6d 100644
--- a/network/hybridNetwork.go
+++ b/network/hybridNetwork.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/hybridNetwork_test.go b/network/hybridNetwork_test.go
index c4e5540d59..d15ca20066 100644
--- a/network/hybridNetwork_test.go
+++ b/network/hybridNetwork_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/limitcaller/dialer.go b/network/limitcaller/dialer.go
index 90049081ea..16a89a6376 100644
--- a/network/limitcaller/dialer.go
+++ b/network/limitcaller/dialer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/limitcaller/rateLimitingTransport.go b/network/limitcaller/rateLimitingTransport.go
index 8aacd05fcb..87fa2f9698 100644
--- a/network/limitcaller/rateLimitingTransport.go
+++ b/network/limitcaller/rateLimitingTransport.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/limitcaller/rateLimitingTransport_test.go b/network/limitcaller/rateLimitingTransport_test.go
index 0e92357945..6e7e007f20 100644
--- a/network/limitcaller/rateLimitingTransport_test.go
+++ b/network/limitcaller/rateLimitingTransport_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/limited_reader_slurper.go b/network/limited_reader_slurper.go
index 56ed0df2ae..4ea97c39c7 100644
--- a/network/limited_reader_slurper.go
+++ b/network/limited_reader_slurper.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/limited_reader_slurper_test.go b/network/limited_reader_slurper_test.go
index c8c05ebd13..7e02dbb323 100644
--- a/network/limited_reader_slurper_test.go
+++ b/network/limited_reader_slurper_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/limitlistener/helper_stub_test.go b/network/limitlistener/helper_stub_test.go
index a1430427ca..f2d0e32e8f 100644
--- a/network/limitlistener/helper_stub_test.go
+++ b/network/limitlistener/helper_stub_test.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows
-// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
package limitlistener_test
diff --git a/network/limitlistener/helper_unix_test.go b/network/limitlistener/helper_unix_test.go
index 9cae789122..7c941479cf 100644
--- a/network/limitlistener/helper_unix_test.go
+++ b/network/limitlistener/helper_unix_test.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
-// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package limitlistener_test
diff --git a/network/mesh.go b/network/mesh.go
index d01c144f9b..c755f72e20 100644
--- a/network/mesh.go
+++ b/network/mesh.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/mesh_test.go b/network/mesh_test.go
index dae83940e3..b2f8a76d7c 100644
--- a/network/mesh_test.go
+++ b/network/mesh_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/messageFilter.go b/network/messageFilter.go
index 1b11d22d80..c54f46b4fc 100644
--- a/network/messageFilter.go
+++ b/network/messageFilter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -43,7 +43,7 @@ func makeMessageFilter(bucketsCount, maxBucketSize int) *messageFilter {
return mf
}
-// CheckMessage checks if the given tag/msg already in the collection, and return true if it was there before the call.
+// CheckIncomingMessage checks if the given tag/msg already in the collection, and return true if it was there before the call.
// Prepends our own random secret to the message to make it hard to abuse hash collisions.
func (f *messageFilter) CheckIncomingMessage(tag protocol.Tag, msg []byte, add bool, promote bool) bool {
hasher := crypto.NewHash()
diff --git a/network/messageFilter_test.go b/network/messageFilter_test.go
index 5dd5dc1200..f1cce60afc 100644
--- a/network/messageFilter_test.go
+++ b/network/messageFilter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/messagetracer/graphtrace.go b/network/messagetracer/graphtrace.go
index 6b57a70562..d7aedc1e6c 100644
--- a/network/messagetracer/graphtrace.go
+++ b/network/messagetracer/graphtrace.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//
//go:build msgtrace
-// +build msgtrace
package messagetracer
diff --git a/network/messagetracer/interface.go b/network/messagetracer/interface.go
index 858289155d..c0463a0e4b 100644
--- a/network/messagetracer/interface.go
+++ b/network/messagetracer/interface.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/metrics.go b/network/metrics.go
index 5400c927a3..5ef235b93e 100644
--- a/network/metrics.go
+++ b/network/metrics.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/metrics_test.go b/network/metrics_test.go
index e15f7c1b1d..379ad2a6be 100644
--- a/network/metrics_test.go
+++ b/network/metrics_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -27,7 +27,7 @@ import (
"github.com/algorand/go-algorand/test/partitiontest"
)
-// TestPubsubTracer_TagList makes sure pubsubMetricsTracer traces pubsub messages
+// TestMetrics_PubsubTracer_TagList makes sure pubsubMetricsTracer traces pubsub messages
// by counting switch cases in SendRPC and ValidateMessage
func TestMetrics_PubsubTracer_TagList(t *testing.T) {
t.Parallel()
diff --git a/network/msgCompressor.go b/network/msgCompressor.go
index 6b51476726..0aa79538d9 100644
--- a/network/msgCompressor.go
+++ b/network/msgCompressor.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/msgCompressor_test.go b/network/msgCompressor_test.go
index 333c0b0baa..76717b4914 100644
--- a/network/msgCompressor_test.go
+++ b/network/msgCompressor_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/msgOfInterest.go b/network/msgOfInterest.go
index fd07e60c0d..3890f4aa01 100644
--- a/network/msgOfInterest.go
+++ b/network/msgOfInterest.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/msgOfInterest_test.go b/network/msgOfInterest_test.go
index c596781d64..c12877e66c 100644
--- a/network/msgOfInterest_test.go
+++ b/network/msgOfInterest_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/msgp_gen.go b/network/msgp_gen.go
index 3d94f7f478..57cb238120 100644
--- a/network/msgp_gen.go
+++ b/network/msgp_gen.go
@@ -1,7 +1,7 @@
-package network
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package network
+
import (
"sort"
@@ -166,7 +166,7 @@ func (z disconnectReason) MsgIsZero() bool {
return z == ""
}
-// MaxSize returns a maximum valid message size for this message type
+// DisconnectReasonMaxSize returns a maximum valid message size for this message type
func DisconnectReasonMaxSize() (s int) {
panic("Unable to determine max size: String type string(z) is unbounded")
}
@@ -351,7 +351,7 @@ func (z *identityChallenge) MsgIsZero() bool {
return ((*z).Key.MsgIsZero()) && ((*z).Challenge == (identityChallengeValue{})) && (len((*z).PublicAddress) == 0)
}
-// MaxSize returns a maximum valid message size for this message type
+// IdentityChallengeMaxSize returns a maximum valid message size for this message type
func IdentityChallengeMaxSize() (s int) {
s = 1 + 3 + crypto.PublicKeyMaxSize() + 2
// Calculating size of array: z.Challenge
@@ -520,7 +520,7 @@ func (z *identityChallengeResponse) MsgIsZero() bool {
return ((*z).Key.MsgIsZero()) && ((*z).Challenge == (identityChallengeValue{})) && ((*z).ResponseChallenge == (identityChallengeValue{}))
}
-// MaxSize returns a maximum valid message size for this message type
+// IdentityChallengeResponseMaxSize returns a maximum valid message size for this message type
func IdentityChallengeResponseMaxSize() (s int) {
s = 1 + 3 + crypto.PublicKeyMaxSize() + 2
// Calculating size of array: z.Challenge
@@ -668,7 +668,7 @@ func (z *identityChallengeResponseSigned) MsgIsZero() bool {
return ((*z).Msg.MsgIsZero()) && ((*z).Signature.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// IdentityChallengeResponseSignedMaxSize returns a maximum valid message size for this message type
func IdentityChallengeResponseSignedMaxSize() (s int) {
s = 1 + 4 + IdentityChallengeResponseMaxSize() + 4 + crypto.SignatureMaxSize()
return
@@ -811,7 +811,7 @@ func (z *identityChallengeSigned) MsgIsZero() bool {
return ((*z).Msg.MsgIsZero()) && ((*z).Signature.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// IdentityChallengeSignedMaxSize returns a maximum valid message size for this message type
func IdentityChallengeSignedMaxSize() (s int) {
s = 1 + 3 + IdentityChallengeMaxSize() + 4 + crypto.SignatureMaxSize()
return
@@ -864,7 +864,7 @@ func (z *identityChallengeValue) MsgIsZero() bool {
return (*z) == (identityChallengeValue{})
}
-// MaxSize returns a maximum valid message size for this message type
+// IdentityChallengeValueMaxSize returns a maximum valid message size for this message type
func IdentityChallengeValueMaxSize() (s int) {
// Calculating size of array: z
s = msgp.ArrayHeaderSize + ((32) * (msgp.ByteSize))
@@ -985,7 +985,7 @@ func (z *identityVerificationMessage) MsgIsZero() bool {
return ((*z).ResponseChallenge == (identityChallengeValue{}))
}
-// MaxSize returns a maximum valid message size for this message type
+// IdentityVerificationMessageMaxSize returns a maximum valid message size for this message type
func IdentityVerificationMessageMaxSize() (s int) {
s = 1 + 3
// Calculating size of array: z.ResponseChallenge
@@ -1243,7 +1243,7 @@ func (z *identityVerificationMessageSigned) MsgIsZero() bool {
return ((*z).Msg.ResponseChallenge == (identityChallengeValue{})) && ((*z).Signature.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// IdentityVerificationMessageSignedMaxSize returns a maximum valid message size for this message type
func IdentityVerificationMessageSignedMaxSize() (s int) {
s = 1 + 4 + 1 + 3
// Calculating size of array: z.Msg.ResponseChallenge
@@ -1383,7 +1383,7 @@ func (z peerMetaHeaders) MsgIsZero() bool {
return len(z) == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// PeerMetaHeadersMaxSize returns a maximum valid message size for this message type
func PeerMetaHeadersMaxSize() (s int) {
s += msgp.MapHeaderSize
// Adding size of map keys for z
@@ -1472,7 +1472,7 @@ func (z peerMetaValues) MsgIsZero() bool {
return len(z) == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// PeerMetaValuesMaxSize returns a maximum valid message size for this message type
func PeerMetaValuesMaxSize() (s int) {
// Calculating size of slice: z
s += msgp.ArrayHeaderSize
diff --git a/network/msgp_gen_test.go b/network/msgp_gen_test.go
index 0144dea16e..3415eb7fbc 100644
--- a/network/msgp_gen_test.go
+++ b/network/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package network
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package network
+
import (
"testing"
diff --git a/network/multiplexer.go b/network/multiplexer.go
index abe5d209f4..b6ed68a8e4 100644
--- a/network/multiplexer.go
+++ b/network/multiplexer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/multiplexer_test.go b/network/multiplexer_test.go
index 54e0a0e029..2eb08eaa56 100644
--- a/network/multiplexer_test.go
+++ b/network/multiplexer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/netidentity.go b/network/netidentity.go
index dc19f9d774..317f7f0017 100644
--- a/network/netidentity.go
+++ b/network/netidentity.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/netidentity_test.go b/network/netidentity_test.go
index 03c345fe79..396defde0d 100644
--- a/network/netidentity_test.go
+++ b/network/netidentity_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/netprio.go b/network/netprio.go
index 6a6af66fa0..82da8d19d3 100644
--- a/network/netprio.go
+++ b/network/netprio.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/netprio_test.go b/network/netprio_test.go
index 0c323232a0..4036e74470 100644
--- a/network/netprio_test.go
+++ b/network/netprio_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/capabilities.go b/network/p2p/capabilities.go
index fafa4ee6b1..85ba6f9ede 100644
--- a/network/p2p/capabilities.go
+++ b/network/p2p/capabilities.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/capabilities_test.go b/network/p2p/capabilities_test.go
index c084ac1a24..cace6e4206 100644
--- a/network/p2p/capabilities_test.go
+++ b/network/p2p/capabilities_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -43,6 +43,7 @@ func setupDHTHosts(t *testing.T, numHosts int) []*dht.IpfsDHT {
var bootstrapPeers []peer.AddrInfo
var dhts []*dht.IpfsDHT
cfg := config.GetDefaultLocal()
+ cfg.NetAddress = "localhost:0" // enable DHT server mode
for i := 0; i < numHosts; i++ {
tmpdir := t.TempDir()
pk, err := GetPrivKey(cfg, tmpdir)
@@ -94,6 +95,7 @@ func setupCapDiscovery(t *testing.T, numHosts int, numBootstrapPeers int) []*Cap
var bootstrapPeers []peer.AddrInfo
var capsDisc []*CapabilitiesDiscovery
cfg := config.GetDefaultLocal()
+ cfg.NetAddress = "localhost:0" // enable DHT server mode
for i := 0; i < numHosts; i++ {
tmpdir := t.TempDir()
pk, err := GetPrivKey(cfg, tmpdir)
diff --git a/network/p2p/dht/dht.go b/network/p2p/dht/dht.go
index e53fa8f216..12fbb398ec 100644
--- a/network/p2p/dht/dht.go
+++ b/network/p2p/dht/dht.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -46,11 +46,31 @@ func dhtProtocolPrefix(networkID algoproto.NetworkID) protocol.ID {
return protocol.ID(fmt.Sprintf("/algorand/kad/%s", networkID))
}
+// dhtMode returns the appropriate DHT mode based on config.
+// If DHTMode is explicitly set, use that. Otherwise:
+// - Nodes with listen addresses (NetAddress or P2PHybridNetAddress) default to ModeServer to be discoverable
+// - Other nodes default to ModeClient
+func dhtMode(cfg config.Local) dht.ModeOpt {
+ switch cfg.DHTMode {
+ case "server":
+ return dht.ModeServer
+ case "client":
+ return dht.ModeClient
+ case "":
+ // Default behavior: nodes with listen addresses should be discoverable
+ if cfg.IsListenServer() {
+ return dht.ModeServer
+ }
+ return dht.ModeClient
+ default:
+ return dht.ModeClient
+ }
+}
+
// MakeDHT creates the dht.IpfsDHT object
func MakeDHT(ctx context.Context, h host.Host, networkID algoproto.NetworkID, cfg config.Local, bootstrapFunc func() []peer.AddrInfo) (*dht.IpfsDHT, error) {
dhtCfg := []dht.Option{
- // Automatically determine server or client mode
- dht.Mode(dht.ModeAutoServer),
+ dht.Mode(dhtMode(cfg)),
// We don't need the value store right now
dht.DisableValues(),
dht.ProtocolPrefix(dhtProtocolPrefix(networkID)),
diff --git a/network/p2p/dht/dht_test.go b/network/p2p/dht/dht_test.go
index 77f3db72da..55253c5c63 100644
--- a/network/p2p/dht/dht_test.go
+++ b/network/p2p/dht/dht_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -47,6 +47,69 @@ func TestDHTBasic(t *testing.T) {
require.NoError(t, err)
}
+func TestMakeDHTWithModes(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ modes := []string{"", "server", "client"}
+ for _, mode := range modes {
+ t.Run("mode_"+mode, func(t *testing.T) {
+ h, err := libp2p.New()
+ require.NoError(t, err)
+ defer h.Close()
+
+ cfg := config.GetDefaultLocal()
+ cfg.DHTMode = mode
+
+ dht, err := MakeDHT(
+ context.Background(),
+ h,
+ "devtestnet",
+ cfg,
+ func() []peer.AddrInfo { return nil })
+ require.NoError(t, err)
+ require.NotNil(t, dht)
+ err = dht.Close()
+ require.NoError(t, err)
+ })
+ }
+}
+
+func TestDHTModeDefaults(t *testing.T) {
+ partitiontest.PartitionTest(t)
+
+ t.Run("node with NetAddress defaults to server mode", func(t *testing.T) {
+ cfg := config.GetDefaultLocal()
+ cfg.NetAddress = ":4160"
+ cfg.DHTMode = ""
+
+ h, err := libp2p.New()
+ require.NoError(t, err)
+ defer h.Close()
+
+ dht, err := MakeDHT(context.Background(), h, "devtestnet", cfg, func() []peer.AddrInfo { return nil })
+ require.NoError(t, err)
+ require.NotNil(t, dht)
+ err = dht.Close()
+ require.NoError(t, err)
+ })
+
+ t.Run("node without NetAddress defaults to client mode", func(t *testing.T) {
+ cfg := config.GetDefaultLocal()
+ cfg.NetAddress = ""
+ cfg.DHTMode = ""
+
+ h, err := libp2p.New()
+ require.NoError(t, err)
+ defer h.Close()
+
+ dht, err := MakeDHT(context.Background(), h, "devtestnet", cfg, func() []peer.AddrInfo { return nil })
+ require.NoError(t, err)
+ require.NotNil(t, dht)
+ err = dht.Close()
+ require.NoError(t, err)
+ })
+}
+
func TestDHTBasicAlgodev(t *testing.T) {
partitiontest.PartitionTest(t)
diff --git a/network/p2p/dnsaddr/resolve.go b/network/p2p/dnsaddr/resolve.go
index 1dcee65488..44f2fbac85 100644
--- a/network/p2p/dnsaddr/resolve.go
+++ b/network/p2p/dnsaddr/resolve.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/dnsaddr/resolveController.go b/network/p2p/dnsaddr/resolveController.go
index 78d992f676..eb826ac41b 100644
--- a/network/p2p/dnsaddr/resolveController.go
+++ b/network/p2p/dnsaddr/resolveController.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/dnsaddr/resolveController_test.go b/network/p2p/dnsaddr/resolveController_test.go
index dac680a7fc..47efa09add 100644
--- a/network/p2p/dnsaddr/resolveController_test.go
+++ b/network/p2p/dnsaddr/resolveController_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/dnsaddr/resolve_test.go b/network/p2p/dnsaddr/resolve_test.go
index 0e259240ae..38fbca0077 100644
--- a/network/p2p/dnsaddr/resolve_test.go
+++ b/network/p2p/dnsaddr/resolve_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/http.go b/network/p2p/http.go
index bb053cdd92..ae3468aa23 100644
--- a/network/p2p/http.go
+++ b/network/p2p/http.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/logger.go b/network/p2p/logger.go
index eef4f0322e..474576bda8 100644
--- a/network/p2p/logger.go
+++ b/network/p2p/logger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/p2p.go b/network/p2p/p2p.go
index 9186074f01..44677ecb14 100644
--- a/network/p2p/p2p.go
+++ b/network/p2p/p2p.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/p2p_test.go b/network/p2p/p2p_test.go
index 86e8e299de..5973b00ea6 100644
--- a/network/p2p/p2p_test.go
+++ b/network/p2p/p2p_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/peerID.go b/network/p2p/peerID.go
index 1fdde6074b..291de66425 100644
--- a/network/p2p/peerID.go
+++ b/network/p2p/peerID.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/peerID_test.go b/network/p2p/peerID_test.go
index 10f9e364d6..a00ba20126 100644
--- a/network/p2p/peerID_test.go
+++ b/network/p2p/peerID_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/peerstore/peerstore.go b/network/p2p/peerstore/peerstore.go
index 83ee62c09e..3d37334d5d 100644
--- a/network/p2p/peerstore/peerstore.go
+++ b/network/p2p/peerstore/peerstore.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -240,14 +240,19 @@ func (ps *PeerStore) ReplacePeerList(addressesThey []*peer.AddrInfo, networkName
}
for _, info := range addressesThey {
+ if len(info.Addrs) == 0 {
+ // skip entries without addresses
+ continue
+ }
data, _ := ps.Get(info.ID, psmdkAddressData)
if data != nil {
// we already have this
- // update the networkName and role
+ // update the networkName and role, and refresh the address TTL
ad := data.(addressData)
ad.networkNames[networkName] = true
ad.roles.Add(role)
_ = ps.Put(info.ID, psmdkAddressData, ad)
+ ps.AddAddrs(info.ID, info.Addrs, libp2p.AddressTTL)
// do not remove this entry
delete(removeItems, info.ID)
@@ -273,6 +278,10 @@ func (ps *PeerStore) AddPersistentPeers(addrInfo []*peer.AddrInfo, networkName s
defer ps.lock.Unlock()
for _, info := range addrInfo {
+ if len(info.Addrs) == 0 {
+ // skip entries without addresses
+ continue
+ }
data, _ := ps.Get(info.ID, psmdkAddressData)
if data != nil {
// we already have this.
@@ -280,6 +289,8 @@ func (ps *PeerStore) AddPersistentPeers(addrInfo []*peer.AddrInfo, networkName s
ad := data.(addressData)
ad.roles.AddPersistent(role)
_ = ps.Put(info.ID, psmdkAddressData, ad)
+ // refresh the address TTL
+ ps.AddAddrs(info.ID, info.Addrs, libp2p.PermanentAddrTTL)
} else {
// we don't have this item. add it.
ps.AddAddrs(info.ID, info.Addrs, libp2p.PermanentAddrTTL)
diff --git a/network/p2p/peerstore/peerstore_test.go b/network/p2p/peerstore/peerstore_test.go
index fcff51d0c6..af2e6dc227 100644
--- a/network/p2p/peerstore/peerstore_test.go
+++ b/network/p2p/peerstore/peerstore_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -610,3 +610,57 @@ func TestReplacePeerList(t *testing.T) {
require.Contains(t, res, info)
}
}
+
+// TestReplacePeerListRefreshesAddresses simulates addresses expiring
+// by calling ReplacePeerList + UpdateAddrs(newTTL=0) + ReplacePeerList again
+func TestReplacePeerListRefreshesAddresses(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ relaysSet := []string{"relay1:4160", "relay2:4160", "relay3:4160"}
+ infoRelaySet := make([]*peer.AddrInfo, 0)
+ for _, addr := range relaysSet {
+ info, err := peerInfoFromDomainPort(addr)
+ require.NoError(t, err)
+ infoRelaySet = append(infoRelaySet, info)
+ }
+
+ ph, err := MakePhonebook(1, time.Millisecond)
+ require.NoError(t, err)
+
+ ph.ReplacePeerList(infoRelaySet, "default", phonebook.RelayRole)
+
+ for _, info := range infoRelaySet {
+ addrs := ph.Addrs(info.ID)
+ require.NotEmpty(t, addrs)
+ }
+
+ // Simulate addr book GC run by setting zero TTL
+ for _, info := range infoRelaySet {
+ ph.UpdateAddrs(info.ID, libp2p.AddressTTL, 0)
+ }
+
+ // Verify metadata still exists but addresses are now empty
+ for _, info := range infoRelaySet {
+ addrs := ph.Addrs(info.ID)
+ require.Empty(t, addrs)
+ data, err := ph.Get(info.ID, psmdkAddressData)
+ require.NoError(t, err)
+ require.NotNil(t, data)
+ }
+
+ // Re-add the peer list, which should refresh the addresses
+ ph.ReplacePeerList(infoRelaySet, "default", phonebook.RelayRole)
+
+ // Verify addresses are restored
+ for _, info := range infoRelaySet {
+ addrs := ph.Addrs(info.ID)
+ require.NotEmpty(t, addrs)
+ }
+
+ result := ph.GetAddresses(len(relaysSet), phonebook.RelayRole)
+ require.Equal(t, len(relaysSet), len(result))
+ for _, info := range result {
+ require.NotEmpty(t, info.Addrs)
+ }
+}
diff --git a/network/p2p/peerstore/utils.go b/network/p2p/peerstore/utils.go
index 5e0b7627b6..0bdf9a2362 100644
--- a/network/p2p/peerstore/utils.go
+++ b/network/p2p/peerstore/utils.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/peerstore/utils_test.go b/network/p2p/peerstore/utils_test.go
index 8c1975e16e..f524f607dc 100644
--- a/network/p2p/peerstore/utils_test.go
+++ b/network/p2p/peerstore/utils_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/pubsub.go b/network/p2p/pubsub.go
index 2e5906aeb3..8ff628a37b 100644
--- a/network/p2p/pubsub.go
+++ b/network/p2p/pubsub.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/pubsub_test.go b/network/p2p/pubsub_test.go
index 70cb957148..b7cfab9716 100644
--- a/network/p2p/pubsub_test.go
+++ b/network/p2p/pubsub_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/streams.go b/network/p2p/streams.go
index f880a4f833..7f9cf0260f 100644
--- a/network/p2p/streams.go
+++ b/network/p2p/streams.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/streams_test.go b/network/p2p/streams_test.go
index 93e26aecbf..6e71755d4f 100644
--- a/network/p2p/streams_test.go
+++ b/network/p2p/streams_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2p/testing/httpNode.go b/network/p2p/testing/httpNode.go
index 10ccb6e7b6..b1e8555ce5 100644
--- a/network/p2p/testing/httpNode.go
+++ b/network/p2p/testing/httpNode.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2pMetainfo.go b/network/p2pMetainfo.go
index 02a931d259..0646e817f6 100644
--- a/network/p2pMetainfo.go
+++ b/network/p2pMetainfo.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2pMetainfo_test.go b/network/p2pMetainfo_test.go
index 08e8ada943..2d65ee2362 100644
--- a/network/p2pMetainfo_test.go
+++ b/network/p2pMetainfo_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/p2pNetwork.go b/network/p2pNetwork.go
index 959d960ec7..452b843369 100644
--- a/network/p2pNetwork.go
+++ b/network/p2pNetwork.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -241,7 +241,7 @@ func NewP2PNetwork(log logging.Logger, cfg config.Local, datadir string, phonebo
return nil, err
}
- relayMessages := cfg.IsGossipServer() || cfg.ForceRelayMessages
+ relayMessages := cfg.IsListenServer() || cfg.ForceRelayMessages
net := &P2PNetwork{
log: log,
config: cfg,
@@ -393,7 +393,7 @@ func (n *P2PNetwork) setup() error {
return fmt.Errorf("failed to create mesh: %w", err)
}
- n.connPerfMonitor = makeConnectionPerformanceMonitor([]Tag{protocol.AgreementVoteTag, protocol.TxnTag})
+ n.connPerfMonitor = makeConnectionPerformanceMonitor([]Tag{protocol.AgreementVoteTag})
n.outgoingConnsCloser = makeOutgoingConnsCloser(n.log, n, n.connPerfMonitor, cliqueResolveInterval)
return nil
@@ -471,8 +471,8 @@ func (n *P2PNetwork) Start() error {
n.meshUpdateRequests <- meshRequest{}
n.mesher.start()
- if n.capabilitiesDiscovery != nil {
- n.capabilitiesDiscovery.AdvertiseCapabilities(n.nodeInfo.Capabilities()...)
+ if caps := n.nodeInfo.Capabilities(); len(caps) > 0 && n.capabilitiesDiscovery != nil {
+ n.capabilitiesDiscovery.AdvertiseCapabilities(caps...)
}
return nil
@@ -898,7 +898,7 @@ func (n *P2PNetwork) VoteCompressionEnabled() bool {
return n.config.EnableVoteCompression
}
-// wsStreamHandler is a callback that the p2p package calls when a new peer connects and establishes a
+// wsStreamHandlerV1 is a callback that the p2p package calls when a new peer connects and establishes a
// stream for the websocket protocol.
// TODO: remove after consensus v41 takes effect.
func (n *P2PNetwork) wsStreamHandlerV1(ctx context.Context, p2pPeer peer.ID, stream network.Stream, incoming bool) {
diff --git a/network/p2pNetwork_test.go b/network/p2pNetwork_test.go
index 9c44f1f74c..2e5f1617a0 100644
--- a/network/p2pNetwork_test.go
+++ b/network/p2pNetwork_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -22,9 +22,7 @@ import (
"fmt"
"io"
"net/http"
- "os"
"slices"
- "strings"
"sync"
"sync/atomic"
"testing"
@@ -195,7 +193,7 @@ func TestP2PSubmitTXNoGossip(t *testing.T) {
// run netC in NPN mode (no relay => no gossip sup => no TX receiving)
cfg.ForceFetchTransactions = false
- // Have to unset NetAddress to get IsGossipServer to return false
+ // Have to unset NetAddress to get IsListenServer to return false
cfg.NetAddress = ""
netC, err := NewP2PNetwork(log, cfg, "", phoneBookAddresses, genesisInfo, &nopeNodeInfo{}, nil, nil)
require.NoError(t, err)
@@ -717,7 +715,7 @@ func TestP2PNetworkDHTCapabilities(t *testing.T) {
}
}
-// TestMultiaddrConversionToFrom ensures Multiaddr can be serialized back to an address without losing information
+// TestP2PMultiaddrConversionToFrom ensures Multiaddr can be serialized back to an address without losing information
func TestP2PMultiaddrConversionToFrom(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()
@@ -864,9 +862,10 @@ func TestP2PHTTPHandlerAllInterfaces(t *testing.T) {
func TestP2PRelay(t *testing.T) {
partitiontest.PartitionTest(t)
- if strings.ToUpper(os.Getenv("CIRCLECI")) == "TRUE" {
- t.Skip("Flaky on CIRCLECI")
- }
+ // Speed up heartbeat to reduce test flakiness from mesh establishment timing
+ oldHeartbeatInterval := pubsub.GossipSubHeartbeatInterval
+ pubsub.GossipSubHeartbeatInterval = 200 * time.Millisecond
+ defer func() { pubsub.GossipSubHeartbeatInterval = oldHeartbeatInterval }()
cfg := config.GetDefaultLocal()
cfg.DNSBootstrapID = "" // disable DNS lookups since the test uses phonebook addresses
@@ -994,6 +993,11 @@ func TestP2PRelay(t *testing.T) {
netA.hasPeer(netB.service.ID()) && netA.hasPeer(netC.service.ID())
}, 2*time.Second, 50*time.Millisecond)
+ // Wait for gossipsub heartbeat to establish mesh links.
+ // ListPeersForTopic returns subscribed peers but mesh links are established
+ // asynchronously via HEARTBEAT.
+ time.Sleep(pubsub.GossipSubHeartbeatInterval + 100*time.Millisecond)
+
const expectedMsgs = 10
counter.Store(0)
var msgsSink logMessages
@@ -1070,7 +1074,7 @@ func TestP2PWantTXGossip(t *testing.T) {
log: logging.TestingLog(t),
ctx: ctx,
nodeInfo: &nopeNodeInfo{},
- connPerfMonitor: makeConnectionPerformanceMonitor([]Tag{protocol.AgreementVoteTag, protocol.TxnTag}),
+ connPerfMonitor: makeConnectionPerformanceMonitor([]Tag{protocol.AgreementVoteTag}),
}
net.outgoingConnsCloser = makeOutgoingConnsCloser(logging.TestingLog(t), net, net.connPerfMonitor, cliqueResolveInterval)
@@ -1594,15 +1598,12 @@ func TestP2PMetainfoV1vsV22(t *testing.T) {
require.NoError(t, err)
defer netB.Stop()
+ // Wait for wsPeer objects to be established on both sides
require.Eventually(t, func() bool {
- return len(netA.service.Conns()) > 0 && len(netB.service.Conns()) > 0
+ return len(netA.GetPeers(PeersConnectedIn)) > 0 && len(netB.GetPeers(PeersConnectedOut)) > 0
}, 2*time.Second, 50*time.Millisecond)
- var peers []Peer
- require.Eventually(t, func() bool {
- peers = netA.GetPeers(PeersConnectedIn)
- return len(peers) > 0
- }, 2*time.Second, 50*time.Millisecond)
+ peers := netA.GetPeers(PeersConnectedIn)
require.Len(t, peers, 1)
peer := peers[0].(*wsPeer)
require.False(t, peer.features&pfCompressedProposal != 0)
@@ -1686,9 +1687,9 @@ func TestP2PVoteCompression(t *testing.T) {
counterDone := matcher.done
netB.RegisterHandlers([]TaggedMessageHandler{{Tag: protocol.AgreementVoteTag, MessageHandler: matcher}})
- // Wait for peers to connect
+ // Wait for wsPeer objects to be established on both sides
require.Eventually(t, func() bool {
- return len(netA.service.Conns()) > 0 && len(netB.service.Conns()) > 0
+ return len(netA.GetPeers(PeersConnectedIn)) > 0 && len(netB.GetPeers(PeersConnectedOut)) > 0
}, 2*time.Second, 50*time.Millisecond)
for _, msg := range messages {
diff --git a/network/p2pPeer.go b/network/p2pPeer.go
index 52fdb3432e..fae62f5379 100644
--- a/network/p2pPeer.go
+++ b/network/p2pPeer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/peersheap.go b/network/peersheap.go
index 15d856d132..5698e88699 100644
--- a/network/peersheap.go
+++ b/network/peersheap.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/phonebook/phonebook.go b/network/phonebook/phonebook.go
index 58d3774cc1..5130195ab2 100644
--- a/network/phonebook/phonebook.go
+++ b/network/phonebook/phonebook.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -190,7 +190,7 @@ func (e *phonebookImpl) deletePhonebookEntry(entryName, networkName string) {
}
}
-// PopEarliestTime removes the earliest time from recentConnectionTimes in
+// popNElements removes the earliest time from recentConnectionTimes in
// addressData for addr
// It is expected to be later than ConnectionsRateLimitingWindow
func (e *phonebookImpl) popNElements(n int, addr string) {
@@ -199,7 +199,7 @@ func (e *phonebookImpl) popNElements(n int, addr string) {
e.data[addr] = entry
}
-// AppendTime adds the current time to recentConnectionTimes in
+// appendTime adds the current time to recentConnectionTimes in
// addressData of addr
func (e *phonebookImpl) appendTime(addr string, t time.Time) {
entry := e.data[addr]
diff --git a/network/phonebook/phonebook_test.go b/network/phonebook/phonebook_test.go
index b07b8f2f7d..ed2da2dbaf 100644
--- a/network/phonebook/phonebook_test.go
+++ b/network/phonebook/phonebook_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/requestLogger.go b/network/requestLogger.go
index a87caddf60..471522c332 100644
--- a/network/requestLogger.go
+++ b/network/requestLogger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/requestLogger_test.go b/network/requestLogger_test.go
index 35e569c166..7353432d4d 100644
--- a/network/requestLogger_test.go
+++ b/network/requestLogger_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/requestTracker.go b/network/requestTracker.go
index 3d54cc5048..82a5cccf25 100644
--- a/network/requestTracker.go
+++ b/network/requestTracker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/requestTracker_test.go b/network/requestTracker_test.go
index dcc5067667..586e1ee22e 100644
--- a/network/requestTracker_test.go
+++ b/network/requestTracker_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/topics.go b/network/topics.go
index 6459df550e..a3911cf30a 100644
--- a/network/topics.go
+++ b/network/topics.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/topics_test.go b/network/topics_test.go
index cab7cfaf4b..0c830bc0a5 100644
--- a/network/topics_test.go
+++ b/network/topics_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/vpack/dynamic_vpack.go b/network/vpack/dynamic_vpack.go
index ea324cd2ae..e5e8b3755f 100644
--- a/network/vpack/dynamic_vpack.go
+++ b/network/vpack/dynamic_vpack.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/vpack/dynamic_vpack_test.go b/network/vpack/dynamic_vpack_test.go
index af8ce5f747..612c9dc404 100644
--- a/network/vpack/dynamic_vpack_test.go
+++ b/network/vpack/dynamic_vpack_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/vpack/lru_table.go b/network/vpack/lru_table.go
index 6153d39c48..993d2026a3 100644
--- a/network/vpack/lru_table.go
+++ b/network/vpack/lru_table.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/vpack/lru_table_test.go b/network/vpack/lru_table_test.go
index 8abf267a3b..3e5d0a9c53 100644
--- a/network/vpack/lru_table_test.go
+++ b/network/vpack/lru_table_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/vpack/msgp.go b/network/vpack/msgp.go
index b515d1fa3c..c06cad8eb2 100644
--- a/network/vpack/msgp.go
+++ b/network/vpack/msgp.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/vpack/parse.go b/network/vpack/parse.go
index 17598ee76f..8451cbd056 100644
--- a/network/vpack/parse.go
+++ b/network/vpack/parse.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/vpack/parse_test.go b/network/vpack/parse_test.go
index 0ad6230c8a..f69c577953 100644
--- a/network/vpack/parse_test.go
+++ b/network/vpack/parse_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/vpack/proposal_window.go b/network/vpack/proposal_window.go
index b4004c4c24..0fa2bd1a85 100644
--- a/network/vpack/proposal_window.go
+++ b/network/vpack/proposal_window.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/vpack/proposal_window_test.go b/network/vpack/proposal_window_test.go
index 1ec9a9dab5..0161107240 100644
--- a/network/vpack/proposal_window_test.go
+++ b/network/vpack/proposal_window_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/vpack/rapid_test.go b/network/vpack/rapid_test.go
index eae07011e2..fc58c57528 100644
--- a/network/vpack/rapid_test.go
+++ b/network/vpack/rapid_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/vpack/vpack.go b/network/vpack/vpack.go
index 18b552ed91..4d20275b97 100644
--- a/network/vpack/vpack.go
+++ b/network/vpack/vpack.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -338,9 +338,18 @@ func (d *StatelessDecoder) DecompressVote(dst, src []byte) ([]byte, error) {
return d.dst, nil
}
+// stripMsgpFieldMarker removes the msgpack fixstr marker byte from a field string
+// for cleaner error messages. msgpack field strings like "\xa3per" become "per".
+func stripMsgpFieldMarker(fieldStr string) string {
+ if len(fieldStr) > 1 && (fieldStr[0]&0xe0) == 0xa0 {
+ return fieldStr[1:]
+ }
+ return fieldStr
+}
+
func (d *StatelessDecoder) bin64(fieldStr string) error {
if d.pos+64 > len(d.src) {
- return fmt.Errorf("not enough data to read value for field %s", fieldStr)
+ return fmt.Errorf("not enough data to read value for field %s", stripMsgpFieldMarker(fieldStr))
}
d.dst = append(d.dst, fieldStr...)
d.dst = append(d.dst, msgpBin8Len64...)
@@ -351,7 +360,7 @@ func (d *StatelessDecoder) bin64(fieldStr string) error {
func (d *StatelessDecoder) bin32(fieldStr string) error {
if d.pos+32 > len(d.src) {
- return fmt.Errorf("not enough data to read value for field %s", fieldStr)
+ return fmt.Errorf("not enough data to read value for field %s", stripMsgpFieldMarker(fieldStr))
}
d.dst = append(d.dst, fieldStr...)
d.dst = append(d.dst, msgpBin8Len32...)
@@ -362,7 +371,7 @@ func (d *StatelessDecoder) bin32(fieldStr string) error {
func (d *StatelessDecoder) bin80(fieldStr string) error {
if d.pos+80 > len(d.src) {
- return fmt.Errorf("not enough data to read value for field %s, d.pos=%d, len(src)=%d", fieldStr, d.pos, len(d.src))
+ return fmt.Errorf("not enough data to read value for field %s, d.pos=%d, len(src)=%d", stripMsgpFieldMarker(fieldStr), d.pos, len(d.src))
}
d.dst = append(d.dst, fieldStr...)
d.dst = append(d.dst, msgpBin8Len80...)
@@ -373,16 +382,16 @@ func (d *StatelessDecoder) bin80(fieldStr string) error {
func (d *StatelessDecoder) varuint(fieldName string) error {
if d.pos+1 > len(d.src) {
- return fmt.Errorf("not enough data to read varuint marker for field %s", fieldName)
+ return fmt.Errorf("not enough data to read varuint marker for field %s", stripMsgpFieldMarker(fieldName))
}
marker := d.src[d.pos] // read msgpack varuint marker
moreBytes, err := msgpVaruintRemaining(marker)
if err != nil {
- return fmt.Errorf("invalid varuint marker %d for field %s: %w", marker, fieldName, err)
+ return fmt.Errorf("invalid varuint marker %d for field %s: %w", marker, stripMsgpFieldMarker(fieldName), err)
}
if d.pos+1+moreBytes > len(d.src) {
- return fmt.Errorf("not enough data for varuint (need %d bytes) for field %s", moreBytes, fieldName)
+ return fmt.Errorf("not enough data for varuint (need %d bytes) for field %s", moreBytes, stripMsgpFieldMarker(fieldName))
}
d.dst = append(d.dst, fieldName...)
d.dst = append(d.dst, marker)
diff --git a/network/vpack/vpack_test.go b/network/vpack/vpack_test.go
index 9062a61da8..3b6bc5643c 100644
--- a/network/vpack/vpack_test.go
+++ b/network/vpack/vpack_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -18,7 +18,6 @@ package vpack
import (
"encoding/json"
- "fmt"
"reflect"
"slices"
"testing"
@@ -123,45 +122,45 @@ func TestStatelessDecoderErrors(t *testing.T) {
cases := []tc{
// ---------- cred ----------
- {"pf-bin80", fmt.Sprintf("field %s", msgpFixstrPf),
+ {"pf-bin80", "field pf",
func() []byte { return slices.Concat(h(0), z(79)) }},
// ---------- r.per ----------
- {"per-varuint-marker", fmt.Sprintf("field %s", msgpFixstrPer),
+ {"per-varuint-marker", "field per",
func() []byte { return slices.Concat(h(bitPer), pf) }},
// ---------- r.prop.* ----------
- {"dig-bin32", fmt.Sprintf("field %s", msgpFixstrDig),
+ {"dig-bin32", "field dig",
func() []byte { return slices.Concat(h(bitDig), pf, z(10)) }},
- {"encdig-bin32", fmt.Sprintf("field %s", msgpFixstrEncdig),
+ {"encdig-bin32", "field encdig",
func() []byte { return slices.Concat(h(bitDig|bitEncDig), pf, z32, z(10)) }},
- {"oper-varuint-marker", fmt.Sprintf("field %s", msgpFixstrOper),
+ {"oper-varuint-marker", "field oper",
func() []byte { return slices.Concat(h(bitOper), pf) }},
- {"oprop-bin32", fmt.Sprintf("field %s", msgpFixstrOprop),
+ {"oprop-bin32", "field oprop",
func() []byte { return slices.Concat(h(bitOprop), pf, z(5)) }},
// ---------- r.rnd ----------
- {"rnd-varuint-marker", fmt.Sprintf("field %s", msgpFixstrRnd),
+ {"rnd-varuint-marker", "field rnd",
func() []byte { return slices.Concat(h(0), pf) }},
- {"rnd-varuint-trunc", fmt.Sprintf("not enough data for varuint (need 4 bytes) for field %s", msgpFixstrRnd),
+ {"rnd-varuint-trunc", "not enough data for varuint (need 4 bytes) for field rnd",
func() []byte { return slices.Concat(h(0), pf, []byte{msgpUint32, 0x00}) }},
// ---------- r.snd / r.step ----------
- {"snd-bin32", fmt.Sprintf("field %s", msgpFixstrSnd),
+ {"snd-bin32", "field snd",
func() []byte { return slices.Concat(h(0), pf, fix1) }},
- {"step-varuint-marker", fmt.Sprintf("field %s", msgpFixstrStep),
+ {"step-varuint-marker", "field step",
func() []byte { return slices.Concat(h(bitStep), pf, fix1, z32) }},
// ---------- sig.* ----------
- {"p-bin32", fmt.Sprintf("field %s", msgpFixstrP),
+ {"p-bin32", "field p",
func() []byte { return slices.Concat(h(0), pf, fix1, z32) }},
- {"p1s-bin64", fmt.Sprintf("field %s", msgpFixstrP1s),
+ {"p1s-bin64", "field p1s",
func() []byte { return slices.Concat(h(0), pf, fix1, z32, z32, z(12)) }},
- {"p2-bin32", fmt.Sprintf("field %s", msgpFixstrP2),
+ {"p2-bin32", "field p2",
func() []byte { return slices.Concat(h(0), pf, fix1, z32, z32, z64) }},
- {"p2s-bin64", fmt.Sprintf("field %s", msgpFixstrP2s),
+ {"p2s-bin64", "field p2s",
func() []byte { return slices.Concat(h(0), pf, fix1, z32, z32, z64, z32, z(3)) }},
- {"s-bin64", fmt.Sprintf("field %s", msgpFixstrS),
+ {"s-bin64", "field s",
func() []byte { return slices.Concat(h(0), pf, fix1, z32, z32, z64, z32, z64) }},
// ---------- trailing data ----------
diff --git a/network/websocketProxy_test.go b/network/websocketProxy_test.go
index 753430a965..a08c18db1e 100644
--- a/network/websocketProxy_test.go
+++ b/network/websocketProxy_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/network/wsNetwork.go b/network/wsNetwork.go
index e92aa8a9d3..765bdd93dd 100644
--- a/network/wsNetwork.go
+++ b/network/wsNetwork.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -440,7 +440,7 @@ func (wn *WebsocketNetwork) Disconnect(node DisconnectablePeer) {
wn.disconnect(node, disconnectBadData)
}
-// Disconnect from a peer, probably due to protocol errors.
+// disconnect from a peer, probably due to protocol errors.
func (wn *WebsocketNetwork) disconnect(badnode Peer, reason disconnectReason) {
if badnode == nil {
return
@@ -580,7 +580,7 @@ func (wn *WebsocketNetwork) setup() error {
wn.server.IdleTimeout = httpServerIdleTimeout
wn.server.MaxHeaderBytes = httpServerMaxHeaderBytes
wn.ctx, wn.ctxCancel = context.WithCancel(context.Background())
- wn.relayMessages = wn.config.IsGossipServer() || wn.config.ForceRelayMessages
+ wn.relayMessages = wn.config.IsListenServer() || wn.config.ForceRelayMessages
if wn.relayMessages || wn.config.ForceFetchTransactions {
wn.wantTXGossip.Store(wantTXGossipYes)
}
@@ -641,7 +641,7 @@ func (wn *WebsocketNetwork) setup() error {
if wn.config.EnableIncomingMessageFilter {
wn.incomingMsgFilter = makeMessageFilter(wn.config.IncomingMessageFilterBucketCount, wn.config.IncomingMessageFilterBucketSize)
}
- wn.connPerfMonitor = makeConnectionPerformanceMonitor([]Tag{protocol.AgreementVoteTag, protocol.TxnTag})
+ wn.connPerfMonitor = makeConnectionPerformanceMonitor([]Tag{protocol.AgreementVoteTag})
wn.outgoingConnsCloser = makeOutgoingConnsCloser(wn.log, wn, wn.connPerfMonitor, cliqueResolveInterval)
// set our supported versions
@@ -1081,7 +1081,7 @@ func (wn *WebsocketNetwork) checkIncomingConnectionVariables(response http.Respo
return http.StatusOK
}
-// ServerHTTP handles the gossip network functions over websockets
+// ServeHTTP handles the gossip network functions over websockets
func (wn *WebsocketNetwork) ServeHTTP(response http.ResponseWriter, request *http.Request) {
if !wn.config.EnableGossipService {
response.WriteHeader(http.StatusNotFound)
@@ -1986,7 +1986,8 @@ func (wn *WebsocketNetwork) tryConnectReleaseAddr(addr, gossipAddr string) {
func (wn *WebsocketNetwork) numOutgoingPending() int {
wn.tryConnectLock.Lock()
defer wn.tryConnectLock.Unlock()
- return len(wn.tryConnectAddrs)
+ // tryConnectAddrs always populates two entries per pending connection: addr and gossipAddr
+ return len(wn.tryConnectAddrs) / 2
}
// GetHTTPClient returns a http.Client with a suitable for the network Transport
diff --git a/network/wsNetwork_test.go b/network/wsNetwork_test.go
index 28c73b133d..8603fbf4ff 100644
--- a/network/wsNetwork_test.go
+++ b/network/wsNetwork_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -4896,3 +4896,68 @@ func TestMaybeSendMessagesOfInterestLegacyPeer(t *testing.T) {
}
})
}
+
+// TestNumOutgoingPending tests that numOutgoingPending returns the correct count
+// of pending connections, accounting for the fact that tryConnectAddrs always
+// stores two entries per pending connection (addr and gossipAddr).
+func TestNumOutgoingPending(t *testing.T) {
+ partitiontest.PartitionTest(t)
+ t.Parallel()
+
+ netA := makeTestWebsocketNode(t)
+ netA.Start()
+ defer netA.Stop()
+
+ assertEvenEntries := func() {
+ netA.tryConnectLock.Lock()
+ mapLen := len(netA.tryConnectAddrs)
+ netA.tryConnectLock.Unlock()
+ require.Equal(t, 0, mapLen%2, "tryConnectAddrs should always have even number of entries, got %d", mapLen)
+ }
+
+ require.Equal(t, 0, netA.numOutgoingPending())
+ assertEvenEntries()
+
+ gossipAddr1, ok := netA.tryConnectReserveAddr("127.0.0.1:4161")
+ require.True(t, ok)
+ require.NotEmpty(t, gossipAddr1)
+ require.Equal(t, 1, netA.numOutgoingPending())
+ assertEvenEntries()
+
+ netA.tryConnectLock.Lock()
+ require.Equal(t, 2, len(netA.tryConnectAddrs))
+ netA.tryConnectLock.Unlock()
+
+ gossipAddr2, ok := netA.tryConnectReserveAddr("127.0.0.1:4162")
+ require.True(t, ok)
+ require.NotEmpty(t, gossipAddr2)
+ require.Equal(t, 2, netA.numOutgoingPending())
+ assertEvenEntries()
+
+ netA.tryConnectLock.Lock()
+ require.Equal(t, 4, len(netA.tryConnectAddrs))
+ netA.tryConnectLock.Unlock()
+
+ // Trying to reserve the same address should fail
+ _, ok = netA.tryConnectReserveAddr("127.0.0.1:4161")
+ require.False(t, ok)
+ require.Equal(t, 2, netA.numOutgoingPending(), "count should not change after failed reserve")
+ assertEvenEntries()
+
+ // Release addresses
+ netA.tryConnectReleaseAddr("127.0.0.1:4161", gossipAddr1)
+ require.Equal(t, 1, netA.numOutgoingPending())
+ assertEvenEntries()
+
+ netA.tryConnectLock.Lock()
+ require.Equal(t, 2, len(netA.tryConnectAddrs))
+ netA.tryConnectLock.Unlock()
+
+ netA.tryConnectReleaseAddr("127.0.0.1:4162", gossipAddr2)
+ require.Equal(t, 0, netA.numOutgoingPending())
+ assertEvenEntries()
+
+ netA.tryConnectLock.Lock()
+ require.Equal(t, 0, len(netA.tryConnectAddrs), "map should be empty after all releases")
+ netA.tryConnectLock.Unlock()
+}
diff --git a/network/wsPeer.go b/network/wsPeer.go
index a40814f2ac..5e3bc197d3 100644
--- a/network/wsPeer.go
+++ b/network/wsPeer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -570,7 +570,10 @@ func (wp *wsPeer) readLoop() {
msg.Data = slurper.Bytes()
msg.Net = wp.net
wp.lastPacketTime.Store(msg.Received)
+
if wp.peerType == peerTypeWs {
+ msg.Outgoing = wp.outgoing
+
networkReceivedBytesTotal.AddUint64(uint64(len(msg.Data)+2), nil)
networkMessageReceivedTotal.AddUint64(1, nil)
networkReceivedBytesByTag.Add(string(tag[:]), uint64(len(msg.Data)+2))
diff --git a/network/wsPeer_test.go b/network/wsPeer_test.go
index 3fc21e9d09..d3e3cd3fdb 100644
--- a/network/wsPeer_test.go
+++ b/network/wsPeer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/assemble_test.go b/node/assemble_test.go
index 07a7f65389..cea320eef3 100644
--- a/node/assemble_test.go
+++ b/node/assemble_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/error.go b/node/error.go
index b9ee13b214..259bbb6701 100644
--- a/node/error.go
+++ b/node/error.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/follower_node.go b/node/follower_node.go
index bffce44558..36f926d383 100644
--- a/node/follower_node.go
+++ b/node/follower_node.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -128,7 +128,7 @@ func MakeFollower(log logging.Logger, rootDir string, cfg config.Local, phoneboo
node.ledger.RegisterBlockListeners([]ledgercore.BlockListener{node})
- if cfg.IsGossipServer() {
+ if cfg.IsListenServer() {
rpcs.MakeHealthService(node.net)
}
diff --git a/node/follower_node_test.go b/node/follower_node_test.go
index bd18dc3595..7dc0792c18 100644
--- a/node/follower_node_test.go
+++ b/node/follower_node_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/impls.go b/node/impls.go
index 54b8b63ed2..15ad936381 100644
--- a/node/impls.go
+++ b/node/impls.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/msgp_gen.go b/node/msgp_gen.go
index 9d79065fe8..5cada2558b 100644
--- a/node/msgp_gen.go
+++ b/node/msgp_gen.go
@@ -1,7 +1,7 @@
-package node
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package node
+
import (
"github.com/algorand/msgp/msgp"
@@ -165,7 +165,7 @@ func (z *netPrioResponse) MsgIsZero() bool {
return ((*z).Nonce == "")
}
-// MaxSize returns a maximum valid message size for this message type
+// NetPrioResponseMaxSize returns a maximum valid message size for this message type
func NetPrioResponseMaxSize() (s int) {
s = 1 + 6 + msgp.StringPrefixSize + netPrioChallengeSizeBase64Encoded
return
@@ -507,7 +507,7 @@ func (z *netPrioResponseSigned) MsgIsZero() bool {
return ((*z).Response.Nonce == "") && ((*z).Round.MsgIsZero()) && ((*z).Sender.MsgIsZero()) && ((*z).Sig.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// NetPrioResponseSignedMaxSize returns a maximum valid message size for this message type
func NetPrioResponseSignedMaxSize() (s int) {
s = 1 + 9 + 1 + 6 + msgp.StringPrefixSize + netPrioChallengeSizeBase64Encoded + 6 + basics.RoundMaxSize() + 7 + basics.AddressMaxSize() + 4 + crypto.OneTimeSignatureMaxSize()
return
diff --git a/node/msgp_gen_test.go b/node/msgp_gen_test.go
index 46590cb228..55e3696f00 100644
--- a/node/msgp_gen_test.go
+++ b/node/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package node
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package node
+
import (
"testing"
diff --git a/node/netprio.go b/node/netprio.go
index 65193673a9..fc158cecea 100644
--- a/node/netprio.go
+++ b/node/netprio.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/netprio_test.go b/node/netprio_test.go
index e91bed4e45..1073c88f75 100644
--- a/node/netprio_test.go
+++ b/node/netprio_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/node/node.go b/node/node.go
index be0491ec8a..23aae5cd06 100644
--- a/node/node.go
+++ b/node/node.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -293,7 +293,7 @@ recreateNetwork:
}
// The health service registers itself with the network
- if cfg.IsGossipServer() {
+ if cfg.IsListenServer() {
rpcs.MakeHealthService(node.net)
}
@@ -437,13 +437,13 @@ func (node *AlgorandFullNode) Start() error {
// Capabilities returns the node's capabilities for advertising to other nodes.
func (node *AlgorandFullNode) Capabilities() []p2p.Capability {
var caps []p2p.Capability
- if node.config.Archival && node.config.IsGossipServer() {
+ if node.config.Archival && node.config.IsListenServer() {
caps = append(caps, p2p.Archival)
}
- if node.config.StoresCatchpoints() && node.config.IsGossipServer() {
+ if node.config.StoresCatchpoints() && node.config.IsListenServer() {
caps = append(caps, p2p.Catchpoints)
}
- if node.config.EnableGossipService && node.config.IsGossipServer() {
+ if node.config.EnableGossipService && node.config.IsListenServer() {
caps = append(caps, p2p.Gossip)
}
return caps
diff --git a/node/node_test.go b/node/node_test.go
index 42c1dbf9f4..7026b363e4 100644
--- a/node/node_test.go
+++ b/node/node_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -1031,11 +1031,18 @@ func TestNodeHybridTopology(t *testing.T) {
// ensure discovery of archival node by tracking its ledger
select {
case <-nodes[0].ledger.Wait(targetRound):
- e0, err := nodes[0].ledger.Block(targetRound)
+ b0, err := nodes[0].ledger.Block(targetRound)
require.NoError(t, err)
- e1, err := nodes[1].ledger.Block(targetRound)
- require.NoError(t, err)
- require.Equal(t, e1.Hash(), e0.Hash())
+
+ var err1 error
+ var b1 bookkeeping.Block
+ require.Eventually(t, func() bool {
+ // it is possible N0 commits blocks faster than R, so wait a bit
+ b1, err1 = nodes[1].ledger.Block(targetRound)
+ return err1 == nil
+ }, 3*time.Second, 50*time.Millisecond)
+
+ require.Equal(t, b1.Hash(), b0.Hash())
case <-time.After(3 * time.Minute): // set it to 1.5x of the dht.periodicBootstrapInterval to give DHT code to rebuild routing table one more time
require.Fail(t, fmt.Sprintf("no block notification for wallet: %v.", wallets[0]))
}
diff --git a/nodecontrol/LaggedStdIo.go b/nodecontrol/LaggedStdIo.go
index f26bafe78d..7dc5fb7df8 100644
--- a/nodecontrol/LaggedStdIo.go
+++ b/nodecontrol/LaggedStdIo.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/nodecontrol/NodeController.go b/nodecontrol/NodeController.go
index 30179a3d39..957c9dc39d 100644
--- a/nodecontrol/NodeController.go
+++ b/nodecontrol/NodeController.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/nodecontrol/algodControl.go b/nodecontrol/algodControl.go
index bb17e5598e..e5f3ef06bf 100644
--- a/nodecontrol/algodControl.go
+++ b/nodecontrol/algodControl.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/nodecontrol/algodControl_test.go b/nodecontrol/algodControl_test.go
index 05f6c11326..1cd5849830 100644
--- a/nodecontrol/algodControl_test.go
+++ b/nodecontrol/algodControl_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/nodecontrol/kmdControl.go b/nodecontrol/kmdControl.go
index ea896ebea7..2acdd78e80 100644
--- a/nodecontrol/kmdControl.go
+++ b/nodecontrol/kmdControl.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/nodecontrol/kmdControl_common.go b/nodecontrol/kmdControl_common.go
index 86973b9704..978b80f978 100644
--- a/nodecontrol/kmdControl_common.go
+++ b/nodecontrol/kmdControl_common.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//go:build !windows
-// +build !windows
package nodecontrol
diff --git a/nodecontrol/kmdControl_windows.go b/nodecontrol/kmdControl_windows.go
index 92baa0da55..da64a65c6c 100644
--- a/nodecontrol/kmdControl_windows.go
+++ b/nodecontrol/kmdControl_windows.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/nodecontrol/nodeControlErrors.go b/nodecontrol/nodeControlErrors.go
index c281a20818..e8c3c56bbb 100644
--- a/nodecontrol/nodeControlErrors.go
+++ b/nodecontrol/nodeControlErrors.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/codec.go b/protocol/codec.go
index f85d67b9bc..61f71540c0 100644
--- a/protocol/codec.go
+++ b/protocol/codec.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/codec_test.go b/protocol/codec_test.go
index 1971a79f9d..91a83932ab 100644
--- a/protocol/codec_test.go
+++ b/protocol/codec_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/codec_tester.go b/protocol/codec_tester.go
index 08ff7ee686..27654bb120 100644
--- a/protocol/codec_tester.go
+++ b/protocol/codec_tester.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/consensus.go b/protocol/consensus.go
index 981eb37288..1c9d4a456b 100644
--- a/protocol/consensus.go
+++ b/protocol/consensus.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -47,7 +47,7 @@ const DEPRECATEDConsensusV3 = ConsensusVersion("v3")
// closes out an account.
const DEPRECATEDConsensusV4 = ConsensusVersion("v4")
-// DEPRECATEDConsensusV5 sets MinTxnFee to 1000 and fixes a blance lookback bug
+// DEPRECATEDConsensusV5 sets MinTxnFee to 1000 and fixes a balance lookback bug
const DEPRECATEDConsensusV5 = ConsensusVersion("v5")
// DEPRECATEDConsensusV6 adds support for explicit ephemeral-key parameters
diff --git a/protocol/encodebench_test.go b/protocol/encodebench_test.go
index 086bb22201..8169f024c5 100644
--- a/protocol/encodebench_test.go
+++ b/protocol/encodebench_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/hash.go b/protocol/hash.go
index 2ac6842f81..d5f069f34a 100644
--- a/protocol/hash.go
+++ b/protocol/hash.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/hash_test.go b/protocol/hash_test.go
index 6a5d9915b3..459a0160e9 100644
--- a/protocol/hash_test.go
+++ b/protocol/hash_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/msgp_gen.go b/protocol/msgp_gen.go
index a6288eac0b..56ec47bd7a 100644
--- a/protocol/msgp_gen.go
+++ b/protocol/msgp_gen.go
@@ -1,7 +1,7 @@
-package protocol
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package protocol
+
import (
"github.com/algorand/msgp/msgp"
@@ -144,7 +144,7 @@ func (z ConsensusVersion) MsgIsZero() bool {
return z == ""
}
-// MaxSize returns a maximum valid message size for this message type
+// ConsensusVersionMaxSize returns a maximum valid message size for this message type
func ConsensusVersionMaxSize() (s int) {
s = msgp.StringPrefixSize + bounds.MaxConsensusVersionLen
return
@@ -204,7 +204,7 @@ func (z Error) MsgIsZero() bool {
return z == ""
}
-// MaxSize returns a maximum valid message size for this message type
+// ErrorMaxSize returns a maximum valid message size for this message type
func ErrorMaxSize() (s int) {
panic("Unable to determine max size: String type string(z) is unbounded")
}
@@ -263,7 +263,7 @@ func (z HashID) MsgIsZero() bool {
return z == ""
}
-// MaxSize returns a maximum valid message size for this message type
+// HashIDMaxSize returns a maximum valid message size for this message type
func HashIDMaxSize() (s int) {
panic("Unable to determine max size: String type string(z) is unbounded")
}
@@ -322,7 +322,7 @@ func (z NetworkID) MsgIsZero() bool {
return z == ""
}
-// MaxSize returns a maximum valid message size for this message type
+// NetworkIDMaxSize returns a maximum valid message size for this message type
func NetworkIDMaxSize() (s int) {
panic("Unable to determine max size: String type string(z) is unbounded")
}
@@ -381,7 +381,7 @@ func (z StateProofType) MsgIsZero() bool {
return z == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// StateProofTypeMaxSize returns a maximum valid message size for this message type
func StateProofTypeMaxSize() (s int) {
s = msgp.Uint64Size
return
@@ -441,7 +441,7 @@ func (z Tag) MsgIsZero() bool {
return z == ""
}
-// MaxSize returns a maximum valid message size for this message type
+// TagMaxSize returns a maximum valid message size for this message type
func TagMaxSize() (s int) {
panic("Unable to determine max size: String type string(z) is unbounded")
}
@@ -510,7 +510,7 @@ func (z TxType) MsgIsZero() bool {
return z == ""
}
-// MaxSize returns a maximum valid message size for this message type
+// TxTypeMaxSize returns a maximum valid message size for this message type
func TxTypeMaxSize() (s int) {
s = msgp.StringPrefixSize + txTypeMaxLen
return
diff --git a/protocol/msgp_gen_test.go b/protocol/msgp_gen_test.go
index e9cbe36b16..72b6f3fb9e 100644
--- a/protocol/msgp_gen_test.go
+++ b/protocol/msgp_gen_test.go
@@ -1,6 +1,5 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package protocol
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+
+package protocol
diff --git a/protocol/networks.go b/protocol/networks.go
index cc473645b1..f78c894c2f 100644
--- a/protocol/networks.go
+++ b/protocol/networks.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/stateproof.go b/protocol/stateproof.go
index 2f41980eff..2c24d80f2c 100644
--- a/protocol/stateproof.go
+++ b/protocol/stateproof.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/tags.go b/protocol/tags.go
index 61ae80a7c4..c33c49b581 100644
--- a/protocol/tags.go
+++ b/protocol/tags.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/tags_test.go b/protocol/tags_test.go
index 66cff0d762..e1a42bb85a 100644
--- a/protocol/tags_test.go
+++ b/protocol/tags_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/test/allocbound_slice.go b/protocol/test/allocbound_slice.go
index d9e462a273..40d28e7baf 100644
--- a/protocol/test/allocbound_slice.go
+++ b/protocol/test/allocbound_slice.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/test/msgp_gen.go b/protocol/test/msgp_gen.go
index b7500acdd9..c15f5a82c2 100644
--- a/protocol/test/msgp_gen.go
+++ b/protocol/test/msgp_gen.go
@@ -1,7 +1,7 @@
-package test
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package test
+
import (
"github.com/algorand/msgp/msgp"
)
@@ -96,7 +96,7 @@ func (z testSlice) MsgIsZero() bool {
return len(z) == 0
}
-// MaxSize returns a maximum valid message size for this message type
+// TestSliceMaxSize returns a maximum valid message size for this message type
func TestSliceMaxSize() (s int) {
// Calculating size of slice: z
s += msgp.ArrayHeaderSize + ((16) * (msgp.Uint64Size))
diff --git a/protocol/test/msgp_gen_test.go b/protocol/test/msgp_gen_test.go
index 7ee90531d1..3e34169266 100644
--- a/protocol/test/msgp_gen_test.go
+++ b/protocol/test/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package test
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package test
+
import (
"testing"
diff --git a/protocol/transcode/core.go b/protocol/transcode/core.go
index 993131f932..15f24a635d 100644
--- a/protocol/transcode/core.go
+++ b/protocol/transcode/core.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/transcode/core_test.go b/protocol/transcode/core_test.go
index 72ceee9c6f..cf979eea09 100644
--- a/protocol/transcode/core_test.go
+++ b/protocol/transcode/core_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/protocol/txntype.go b/protocol/txntype.go
index 6a60438ab3..66487ad5f8 100644
--- a/protocol/txntype.go
+++ b/protocol/txntype.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -50,6 +50,9 @@ const (
// HeartbeatTx demonstrates the account is alive
HeartbeatTx TxType = "hb"
+ // Remember to add to TxnTypeNames and txnTypeLongNames in logic/fields.go when
+ // adding a new transaction type!
+
// UnknownTx signals an error
UnknownTx TxType = "unknown"
)
diff --git a/rpcs/blockService.go b/rpcs/blockService.go
index 03a4c4ebb7..97f0a43af7 100644
--- a/rpcs/blockService.go
+++ b/rpcs/blockService.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/blockService_test.go b/rpcs/blockService_test.go
index 494b4772ae..22a3dc3f00 100644
--- a/rpcs/blockService_test.go
+++ b/rpcs/blockService_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/healthService.go b/rpcs/healthService.go
index 1668c6f9b2..0f0e95715d 100644
--- a/rpcs/healthService.go
+++ b/rpcs/healthService.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/healthService_test.go b/rpcs/healthService_test.go
index 8954c29deb..3b5284c5dd 100644
--- a/rpcs/healthService_test.go
+++ b/rpcs/healthService_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/httpTxSync.go b/rpcs/httpTxSync.go
index 1aa2584754..4d87fe84f8 100644
--- a/rpcs/httpTxSync.go
+++ b/rpcs/httpTxSync.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/ledgerService.go b/rpcs/ledgerService.go
index 3265ba3781..ec921f9b2f 100644
--- a/rpcs/ledgerService.go
+++ b/rpcs/ledgerService.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/ledgerService_test.go b/rpcs/ledgerService_test.go
index dcb1e045fa..116e51d0ab 100644
--- a/rpcs/ledgerService_test.go
+++ b/rpcs/ledgerService_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/msgp_gen.go b/rpcs/msgp_gen.go
index 4e091781cd..848d0a22fb 100644
--- a/rpcs/msgp_gen.go
+++ b/rpcs/msgp_gen.go
@@ -1,7 +1,7 @@
-package rpcs
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package rpcs
+
import (
"github.com/algorand/msgp/msgp"
@@ -140,7 +140,7 @@ func (z *EncodedBlockCert) MsgIsZero() bool {
return ((*z).Block.MsgIsZero()) && ((*z).Certificate.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// EncodedBlockCertMaxSize returns a maximum valid message size for this message type
func EncodedBlockCertMaxSize() (s int) {
s = 1 + 6 + bookkeeping.BlockMaxSize() + 5 + agreement.CertificateMaxSize()
return
diff --git a/rpcs/msgp_gen_test.go b/rpcs/msgp_gen_test.go
index d88b73039b..5d2ec6fc7a 100644
--- a/rpcs/msgp_gen_test.go
+++ b/rpcs/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package rpcs
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package rpcs
+
import (
"testing"
diff --git a/rpcs/registrar.go b/rpcs/registrar.go
index d9a4cddcdd..8cf99502e6 100644
--- a/rpcs/registrar.go
+++ b/rpcs/registrar.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/txService.go b/rpcs/txService.go
index 38977910d1..b299c90da4 100644
--- a/rpcs/txService.go
+++ b/rpcs/txService.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/txService_test.go b/rpcs/txService_test.go
index dde7cfc4ab..62ab5d1827 100644
--- a/rpcs/txService_test.go
+++ b/rpcs/txService_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/txSyncer.go b/rpcs/txSyncer.go
index 02fdcab3d4..4a6dcf77ff 100644
--- a/rpcs/txSyncer.go
+++ b/rpcs/txSyncer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/rpcs/txSyncer_test.go b/rpcs/txSyncer_test.go
index ac3be12335..15870eb349 100644
--- a/rpcs/txSyncer_test.go
+++ b/rpcs/txSyncer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/scripts/build_deb.sh b/scripts/build_deb.sh
index 3c5b1e2198..5ba0918af4 100755
--- a/scripts/build_deb.sh
+++ b/scripts/build_deb.sh
@@ -52,7 +52,7 @@ mkdir -p "${PKG_ROOT}/usr/bin"
if [ "${VARIATION}" = "" ]; then
# NOTE: keep in sync with installer/rpm/algorand.spec
- bin_files=("algocfg" "algod" "algoh" "algokey" "carpenter" "catchupsrv" "ddconfig.sh" "diagcfg" "goal" "kmd" "msgpacktool" "node_exporter" "tealcut" "tealdbg")
+ bin_files=("algocfg" "algod" "algoh" "algokey" "diagcfg" "goal" "kmd" "node_exporter")
fi
for bin in "${bin_files[@]}"; do
diff --git a/scripts/build_package.sh b/scripts/build_package.sh
index d9b3c9b18a..6b527aac95 100755
--- a/scripts/build_package.sh
+++ b/scripts/build_package.sh
@@ -77,7 +77,7 @@ DEFAULT_RELEASE_NETWORK=$(./scripts/compute_branch_release_network.sh "${DEFAULT
mkdir ${PKG_ROOT}/bin
# If you modify this list, also update this list in ./cmd/updater/update.sh backup_binaries()
-bin_files=("algocfg" "algotmpl" "algod" "algoh" "algokey" "carpenter" "catchupsrv" "ddconfig.sh" "diagcfg" "find-nodes.sh" "goal" "kmd" "msgpacktool" "node_exporter" "tealcut" "tealdbg" "update.sh" "updater" "COPYING")
+bin_files=("algocfg" "algotmpl" "algod" "algoh" "algokey" "diagcfg" "find-nodes.sh" "goal" "kmd" "node_exporter" "update.sh" "updater" "COPYING")
for bin in "${bin_files[@]}"; do
cp ${GOBIN}/${bin} ${PKG_ROOT}/bin
if [ $? -ne 0 ]; then exit 1; fi
@@ -120,7 +120,7 @@ TOOLS_ROOT=${PKG_ROOT}/tools
echo "Staging tools package files"
-bin_files=("algons" "coroner" "dispenser" "netgoal" "nodecfg" "pingpong" "cc_service" "cc_agent" "cc_client" "loadgenerator" "COPYING" "dsign" "catchpointdump" "block-generator")
+bin_files=("algons" "carpenter" "coroner" "dispenser" "msgpacktool" "netgoal" "nodecfg" "pingpong" "loadgenerator" "COPYING" "dsign" "catchpointdump" "block-generator" "tealdbg")
mkdir -p ${TOOLS_ROOT}
for bin in "${bin_files[@]}"; do
cp ${GOBIN}/${bin} ${TOOLS_ROOT}
@@ -140,4 +140,4 @@ cp "scripts/sysctl.sh" ${TOOLS_ROOT}
if [ $? -ne 0 ]; then exit 1; fi
cp "scripts/sysctl-all.sh" ${TOOLS_ROOT}
-if [ $? -ne 0 ]; then exit 1; fi
\ No newline at end of file
+if [ $? -ne 0 ]; then exit 1; fi
diff --git a/scripts/buildtools/install_buildtools.sh b/scripts/buildtools/install_buildtools.sh
deleted file mode 100755
index d4f5b0c848..0000000000
--- a/scripts/buildtools/install_buildtools.sh
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/env bash
-# shellcheck disable=2181
-
-set -exo pipefail
-
-BUILDTOOLS_INSTALL=ALL
-
-function usage {
- echo "$0 is used to install go build tools."
- echo "By default all packages are installed."
- echo "usage: $0 [-o packagename]"
- echo " -o packagename when used only packagename is installed."
- echo " -c commandname if it is one command from a package provide this."
- echo " -h print this usage information."
-}
-
-while getopts ":o:c:h" opt; do
- case $opt in
- o)
- BUILDTOOLS_INSTALL="$OPTARG"
- ;;
- c)
- BUILDTOOLS_COMMAND="$OPTARG"
- ;;
- h)
- usage
- exit 0
- ;;
- \?)
- echo "Invalid option: -$OPTARG" >&2
- usage
- exit 1
- ;;
- :)
- echo "Option -$OPTARG requires an argument." >&2
- usage
- exit 1
- ;;
- esac
-done
-shift $((OPTIND -1))
-
-if [ "$#" -ne 0 ]; then
- echo "Unexpected positional arguments passed to script: $@"
- exit 1
-fi
-
-
-SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
-pushd .
-cd ${SCRIPTPATH}
-(cd ../..; ${SCRIPTPATH}/../check_golang_version.sh dev)
-
-function get_go_version {
- cd "${SCRIPTPATH}"
- VERSION=$( grep "$1" 2>/dev/null < ./versions | awk -F " " '{print $2}')
- echo "$VERSION"
- return
-}
-
-function install_go_module {
- local OUTPUT
- local MODULE
- if [[ "$2" != "" ]]; then
- MODULE=$2
- else
- MODULE=$1
- fi
-
- # Check for version
- VERSION=$(get_go_version "$1")
-
- if [ -z "$VERSION" ]; then
- echo "Unable to install requested package '$1' (${MODULE}): no version listed in ${SCRIPTPATH}/versions"
- exit 1
- else
- OUTPUT=$(go install "${MODULE}@${VERSION}" 2>&1)
- fi
- if [ $? != 0 ]; then
- echo "error: executing \"go install ${MODULE}\" failed : ${OUTPUT}"
- exit 1
- fi
-}
-
-if [[ "${BUILDTOOLS_INSTALL}" != "ALL" ]]; then
- install_go_module "${BUILDTOOLS_INSTALL}" "${BUILDTOOLS_COMMAND}"
- exit 0
-fi
-
-install_go_module golang.org/x/tools golang.org/x/tools/cmd/stringer
-install_go_module github.com/algorand/go-swagger github.com/algorand/go-swagger/cmd/swagger
-install_go_module github.com/algorand/msgp
-install_go_module gotest.tools/gotestsum
-install_go_module github.com/golangci/golangci-lint/v2/cmd/golangci-lint
diff --git a/scripts/buildtools/versions b/scripts/buildtools/versions
deleted file mode 100644
index d22acec8cc..0000000000
--- a/scripts/buildtools/versions
+++ /dev/null
@@ -1,6 +0,0 @@
-golang.org/x/lint v0.0.0-20241112194109-818c5a804067
-golang.org/x/tools v0.27.0
-github.com/algorand/msgp v1.1.61
-github.com/algorand/go-swagger v0.0.0-20251018003531-2ea7c750dcac
-gotest.tools/gotestsum v1.13.0
-github.com/golangci/golangci-lint/v2/cmd/golangci-lint v2.6.0
diff --git a/scripts/check_deps.sh b/scripts/check_deps.sh
deleted file mode 100755
index 229e4edf4a..0000000000
--- a/scripts/check_deps.sh
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/env bash
-
-# check_deps.sh - Quickly(!) checks the enlistment for any missing dependencies and attempts to resolve them.
-# Reports if any dependencies are still missing after attempts to resolve.
-#
-# Syntax: check_deps.sh
-#
-# Outputs: status messages
-#
-# ExitCode: 0 = All dependencies resolved / present
-#
-# Usage: Use before building to ensure dependencies are present (should be nop except after dependencies change)
-#
-# Examples: scripts/check_deps.sh
-
-GREEN_FG=$(tput setaf 2 2>/dev/null)
-RED_FG=$(tput setaf 1 2>/dev/null)
-TEAL_FG=$(tput setaf 6 2>/dev/null)
-YELLOW_FG=$(tput setaf 3 2>/dev/null)
-END_FG_COLOR=$(tput sgr0 2>/dev/null)
-
-UNAME=$(uname)
-if [[ "${UNAME}" == *"MINGW"* ]]; then
- GOPATH=$HOME/go
-else
- GOPATH=$(go env GOPATH)
-fi
-export GOPATH
-GO_BIN="$(echo "$GOPATH" | cut -d: -f1)/bin"
-MISSING=0
-
-missing_dep() {
- echo "$YELLOW_FG[WARNING]$END_FG_COLOR Missing dependency \`$TEAL_FG${1}$END_FG_COLOR\`."
- MISSING=1
-}
-
-GO_DEPS=(
- "msgp"
- "golangci-lint"
- "swagger"
-)
-
-check_go_binary_version() {
- binary_name=$1
- expected_version=$(grep "$binary_name" scripts/buildtools/versions | awk '{print $2}')
- actual_version=$(go version -m "$GO_BIN/$binary_name" | awk 'NR==3 {print $3}')
-
- if [ "$expected_version" != "$actual_version" ]; then
- echo "$YELLOW_FG[WARNING]$END_FG_COLOR $binary_name version mismatch, expected $expected_version, but got $actual_version"
- echo "Use 'install_buildtools.sh' to fix."
- fi
-}
-
-check_deps() {
- for dep in ${GO_DEPS[*]}
- do
- if [ ! -f "$GO_BIN/$dep" ]
- then
- # Parameter expansion is faster than invoking another process.
- # https://www.linuxjournal.com/content/bash-parameter-expansion
- missing_dep "${dep##*/}"
- fi
-
- # go 1.17 on arm64 macs has an issue checking binaries with "go version", skip version check
- if [[ "$(uname)" != "Darwin" ]] || [[ "$(uname -m)" != "arm64" ]] || ! [[ "$(go version | awk '{print $3}')" < "go1.17" ]]
- then
- check_go_binary_version "$dep"
- fi
- done
-
- # Don't print `shellcheck`s location.
- if ! which shellcheck > /dev/null
- then
- missing_dep shellcheck
- fi
-}
-
-check_deps
-
-if [ $MISSING -eq 0 ]
-then
- echo "$GREEN_FG[$0]$END_FG_COLOR Required dependencies installed."
-else
- echo -e "$RED_FG[$0]$END_FG_COLOR Required dependencies missing. Run \`${TEAL_FG}./scripts/configure_dev.sh$END_FG_COLOR\` and/or \`${TEAL_FG}./scripts/buildtools/install_buildtools.sh$END_FG_COLOR\` to install."
- exit 1
-fi
-
diff --git a/scripts/ddconfig.sh b/scripts/ddconfig.sh
deleted file mode 100755
index 6a8bcf029d..0000000000
--- a/scripts/ddconfig.sh
+++ /dev/null
@@ -1,162 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-
-SCRIPTPATH="$(cd "$(dirname "$0")" ; pwd -P )" >/dev/null
-
-function ShowSyntaxAndExit() {
- echo "ddconfig - enable or disable DataDog for use with an Algorand host"
- echo "Syntax: ddconfig enable -d -p -n -k "
- echo "Syntax: ddconfig disable"
- echo "Do not run as root / sudo - you will be prompted to elevate if necessary"
- exit 2
-}
-
-function DisableAndExit() {
- sudo systemctl stop datadog-agent
- sudo systemctl disable datadog-agent
- exit 0
-}
-
-function PrintEndpointAddress() {
- if [[ -f "$1/algocfg" ]]; then
- echo $($1/algocfg get -p EndpointAddress -d "$2")
- else
- echo $(cat $2/config.json|grep EndpointAddress|cut -f 4 -d\")
- fi
-}
-
-function SetEndpointAddress() {
- if [[ -f "$1/algocfg" ]]; then
- $($1/algocfg set -p EndpointAddress -d "$2" -v "$3")
- else
- $(sed -i -e 's/.*EndpointAddress.*/ "EndpointAddress": "'"$3"'","/' "$2/config.json")
- fi
-}
-
-DATADIR=
-PORT=
-HOSTNAME=
-APIKEY=
-
-# ddconfig enable -p 8880 -n r-aa.mainnet -k -d ~/algorand/node
-
-CMD="$1"
-
-if [[ "${CMD}" = "disable" ]]; then
- DisableAndExit
-fi
-
-if [[ "${CMD}" != "enable" ]]; then
- ShowSyntaxAndExit
-fi
-
-shift
-
-while [[ "$1" != "" ]]; do
- case "$1" in
- -d)
- shift
- DATADIR=$1
- pushd ${DATADIR} >/dev/null
- DATADIR=$(pwd -P)
- popd >/dev/null
- ;;
- -p)
- shift
- PORT=$1
- PORT=$(echo $1 | grep -o "[0-9]*")
- if [[ -z "${PORT}" ]]; then
- echo "Port value does not appear to be valid. Specify just the port (eg -p 8000)"
- exit 1
- fi
- ;;
- -n)
- shift
- HOSTNAME=$1
- ;;
- -k)
- shift
- APIKEY=$1
- ;;
- -h)
- ShowSyntaxAndExit
- ;;
- *)
- echo "Unknown option:" "$1"
- ;;
- esac
- shift
-done
-
-if [[ -z "${DATADIR}" || -z "${HOSTNAME}" || -z "${APIKEY}" ]]; then
- ShowSyntaxAndExit
-fi
-
-ENDPOINT="$(PrintEndpointAddress $SCRIPTPATH $DATADIR)"
-ADDRESS=$(echo ${ENDPOINT} | grep -o "[0-9\.]*:" | tr -d ":")
-
-if [[ -z "${PORT}" ]]; then
- PORT=$(echo ${ENDPOINT} | grep -o ":[0-9]*" | tr -d ":")
- if [[ -z "${PORT}" || "${PORT}" = "0" ]]; then
- echo "Port not specified and not already configured - please specify a port to use with `-p`"
- exit 1
- fi
-fi
-
-# Validate the APIKEY - should be 32 alphanum (lowercase) chars
-if [[ "${#APIKEY}" != "32" ]]; then
- echo "API Key specified should be 32 characters long"
- exit 1
-fi
-FILTEREDKEY=$(echo ${APIKEY} | grep -o "[0-9a-f]*")
-if [[ "${APIKEY}" != "${FILTEREDKEY}" ]]; then
- echo "API Key specified should contain only lowercase characters or numbers"
- exit 1
-fi
-
-# At this point we should have valid PORT, HOSTNAME, APIKEY, and DATADIR
-# Apply the algod changes and restart it
-# Install DataDog agent, configure it, and restart it
-
-${SCRIPTPATH}/diagcfg metric disable -d "${DATADIR}"
-
-SetEndpointAddress $SCRIPTPATH $DATADIR "${ADDRESS}:${PORT}"
-
-${SCRIPTPATH}/goal node stop -d ${DATADIR}
-pkill node_exporter || true
-
-if [[ ! -f "${DATADIR}/algod.token" ]]; then
- ${SCRIPTPATH}/goal node generatetoken -d "${DATADIR}"
-fi
-
-ALGOD_TOKEN=$(cat "${DATADIR}/algod.token")
-${SCRIPTPATH}/goal node start -d "${DATADIR}"
-
-
-# Install DataDog Agent
-DD_API_KEY=${APIKEY} bash -c "$(curl -L https://raw.githubusercontent.com/DataDog/datadog-agent/master/cmd/agent/install_script.sh)"
-
-# Remove existing "hostname:" line if any, then append the new one
-sudo sed /[[:space:]#]hostname:/d /etc/datadog-agent/datadog.yaml | sudo sed /^hostname:/d > ~/datadog.yaml.tmp
-sudo echo "hostname: $HOSTNAME" >> ~/datadog.yaml.tmp
-sudo mv ~/datadog.yaml.tmp /etc/datadog-agent/datadog.yaml
-
-sudo mkdir -p /etc/datadog-agent/conf.d/prometheus.d
-
-cat <~/conf.yaml.tmp
-init_config:
-Â
-instances:
-Â Â - prometheus_url: http://localhost:${PORT}/metrics
-Â Â Â Â extra_headers:
-Â Â Â Â Â Â X-Algo-API-Token: ${ALGOD_TOKEN}
-Â Â Â Â namespace: algod
-Â Â Â Â metrics:
-Â Â Â Â Â Â - algod*
-EOF
-
-sudo mv ~/conf.yaml.tmp /etc/datadog-agent/conf.d/prometheus.d/conf.yaml
-
-# Restart datadog agent to pick up hostname and prometheus settings
-sudo systemctl restart datadog-agent
diff --git a/scripts/export_sdk_types.py b/scripts/export_sdk_types.py
index b74e9b9410..3dfec70532 100755
--- a/scripts/export_sdk_types.py
+++ b/scripts/export_sdk_types.py
@@ -174,10 +174,20 @@ def export_thing(pattern, name, src, dst):
export_type("ConsensusProtocols", src, dst)
export_var("Consensus", src, dst)
export_func("initConsensusProtocols", src, dst)
+ export_func("(cp ConsensusProtocols) DeepCopy", src, dst)
+ export_func("(cp ConsensusProtocols) Merge", src, dst)
export_type("Global", src, dst)
export_var("Protocol", src, dst)
# do _not_ export init(), since go-algorand sets bounds, SDK does not
+ # Custom Consensus Functions
+ src = "config/config.go"
+ dst = "protocol/config/config.go"
+ export_func("SaveConfigurableConsensus", src, dst)
+ export_func("PreloadConfigurableConsensusProtocols", src, dst)
+ export_func("LoadConfigurableConsensusProtocols", src, dst)
+ # do not export SetConfigurableConsensusProtocols(), since go-algorand sets bounds, SDK does not
+
# Common transaction types
export_type("Header", "data/transactions/transaction.go", "transaction")
export_type("Transaction", "data/transactions/transaction.go", "transaction")
diff --git a/scripts/release/build/deb/build_deb.sh b/scripts/release/build/deb/build_deb.sh
index 275c37cd2d..dbcf8a9df7 100755
--- a/scripts/release/build/deb/build_deb.sh
+++ b/scripts/release/build/deb/build_deb.sh
@@ -28,12 +28,12 @@ mkdir -p "$PKG_ROOT/usr/bin"
# NOTE: keep in sync with `./installer/rpm/algorand.spec`.
if [[ "$PKG_NAME" =~ devtools ]]; then
- BIN_FILES=("carpenter" "catchupsrv" "msgpacktool" "tealcut" "tealdbg")
+ BIN_FILES=("carpenter" "msgpacktool" "tealdbg")
UNATTENDED_UPGRADES_FILE="53algorand-devtools-upgrades"
OUTPUT_DEB="$OUTDIR/algorand-devtools_${CHANNEL}_${OS_TYPE}-${ARCH}_${VER}.deb"
REQUIRED_ALGORAND_PKG=$("./scripts/compute_package_name.sh" "$CHANNEL")
else
- BIN_FILES=("algocfg" "algod" "algoh" "algokey" "ddconfig.sh" "diagcfg" "goal" "kmd" "node_exporter")
+ BIN_FILES=("algocfg" "algod" "algoh" "algokey" "diagcfg" "goal" "kmd" "node_exporter")
OUTPUT_DEB="$OUTDIR/algorand_${CHANNEL}_${OS_TYPE}-${ARCH}_${VER}.deb"
UNATTENDED_UPGRADES_FILE="51algorand-upgrades"
fi
diff --git a/scripts/release/mule/package/deb/package.sh b/scripts/release/mule/package/deb/package.sh
index 8a8612a3af..c46be04f37 100755
--- a/scripts/release/mule/package/deb/package.sh
+++ b/scripts/release/mule/package/deb/package.sh
@@ -30,22 +30,24 @@ find tmp/node_pkgs -name "*${CHANNEL}*linux*${VERSION}*.tar.gz" | cut -d '/' -f3
ARCH=$(echo "${OS_ARCH}" | cut -d '/' -f2)
PKG_DIR="./tmp/node_pkgs/$OS_TYPE/$ARCH"
mkdir -p "$PKG_DIR/bin"
- ALGO_BIN="${PKG_DIR}/$CHANNEL/$OS_TYPE-$ARCH/bin"
-
+ ALGO_BIN_TOOLS_SRC="${PKG_DIR}/$CHANNEL/$OS_TYPE-$ARCH/bin"
+
# NOTE: keep in sync with `./installer/rpm/algorand.spec`.
if [[ "$ALGORAND_PACKAGE_NAME" =~ devtools ]]; then
- BIN_FILES=("carpenter" "catchupsrv" "msgpacktool" "tealcut" "tealdbg")
+ BIN_FILES=("carpenter" "msgpacktool" "tealdbg")
UNATTENDED_UPGRADES_FILE="53algorand-devtools-upgrades"
OUTPUT_DEB="$PKG_DIR/algorand-devtools_${CHANNEL}_${OS_TYPE}-${ARCH}_${VERSION}.deb"
REQUIRED_ALGORAND_PKG=$("./scripts/compute_package_name.sh" "$CHANNEL")
+ # tools are in tools/ subdirectory instead of bin/
+ ALGO_BIN_TOOLS_SRC="${PKG_DIR}/$CHANNEL/$OS_TYPE-$ARCH/tools"
else
- BIN_FILES=("algocfg" "algod" "algoh" "algokey" "ddconfig.sh" "diagcfg" "goal" "kmd" "node_exporter")
+ BIN_FILES=("algocfg" "algod" "algoh" "algokey" "diagcfg" "goal" "kmd" "node_exporter")
UNATTENDED_UPGRADES_FILE="51algorand-upgrades"
OUTPUT_DEB="$PKG_DIR/algorand_${CHANNEL}_${OS_TYPE}-${ARCH}_${VERSION}.deb"
fi
for binary in "${BIN_FILES[@]}"; do
- cp "${ALGO_BIN}/$binary" "$PKG_ROOT/usr/bin"
+ cp "${ALGO_BIN_TOOLS_SRC}/$binary" "$PKG_ROOT/usr/bin"
chmod 755 "$PKG_ROOT/usr/bin/$binary"
done
@@ -53,7 +55,7 @@ find tmp/node_pkgs -name "*${CHANNEL}*linux*${VERSION}*.tar.gz" | cut -d '/' -f3
mkdir -p "$PKG_ROOT/usr/lib/algorand"
lib_files=("updater" "find-nodes.sh")
for lib in "${lib_files[@]}"; do
- cp "$ALGO_BIN/$lib" "$PKG_ROOT/usr/lib/algorand"
+ cp "$ALGO_BIN_TOOLS_SRC/$lib" "$PKG_ROOT/usr/lib/algorand"
chmod g-w "$PKG_ROOT/usr/lib/algorand/$lib"
done
@@ -144,7 +146,7 @@ EOF
go version:
EOF
- /usr/local/go/bin/go version >> "$STATUSFILE"
+ go version >> "$STATUSFILE"
############################################################
@@ -152,7 +154,7 @@ EOF
go env:
EOF
- /usr/local/go/bin/go env >> "$STATUSFILE"
+ go env >> "$STATUSFILE"
############################################################
diff --git a/scripts/release/mule/package/rpm/package.sh b/scripts/release/mule/package/rpm/package.sh
index 7d63872f5c..daa4a72e66 100755
--- a/scripts/release/mule/package/rpm/package.sh
+++ b/scripts/release/mule/package/rpm/package.sh
@@ -21,6 +21,7 @@ find tmp/node_pkgs -name "*${CHANNEL}*linux*${VERSION}*.tar.gz" | cut -d '/' -f3
ARCH_TYPE=$(echo "${OS_ARCH}" | cut -d '/' -f2)
ARCH_UNAME=$(./scripts/release/common/cpu_name.sh ${ARCH_TYPE})
ALGO_BIN="$REPO_DIR/tmp/node_pkgs/$OS_TYPE/$ARCH_TYPE/$CHANNEL/$OS_TYPE-$ARCH_TYPE/bin"
+ ALGO_TOOLS="$REPO_DIR/tmp/node_pkgs/$OS_TYPE/$ARCH_TYPE/$CHANNEL/$OS_TYPE-$ARCH_TYPE/tools"
# A make target in Makefile.mule may pass the name as an argument.
ALGORAND_PACKAGE_NAME=$(./scripts/compute_package_name.sh "$CHANNEL" "$PACKAGE_NAME")
@@ -32,6 +33,7 @@ find tmp/node_pkgs -name "*${CHANNEL}*linux*${VERSION}*.tar.gz" | cut -d '/' -f3
export DEFAULT_RELEASE_NETWORK
export REPO_DIR
export ALGO_BIN
+ export ALGO_TOOLS
RPMTMP=$(mktemp -d 2>/dev/null || mktemp -d -t "rpmtmp")
trap 'rm -rf $RPMTMP' 0
diff --git a/scripts/release/mule/test/tests/post/verify_package_binaries.sh b/scripts/release/mule/test/tests/post/verify_package_binaries.sh
index 1a61dba1e7..969a66748c 100755
--- a/scripts/release/mule/test/tests/post/verify_package_binaries.sh
+++ b/scripts/release/mule/test/tests/post/verify_package_binaries.sh
@@ -24,7 +24,6 @@ ALGORAND_BINS=(
/usr/bin/algod
/usr/bin/algoh
/usr/bin/algokey
- /usr/bin/ddconfig.sh
/usr/bin/diagcfg
/usr/bin/goal
/usr/bin/kmd
@@ -40,9 +39,7 @@ done
DEVTOOLS_BINS=(
/usr/bin/carpenter
- /usr/bin/catchupsrv
/usr/bin/msgpacktool
- /usr/bin/tealcut
/usr/bin/tealdbg
)
diff --git a/scripts/travis/codegen_verification.sh b/scripts/travis/codegen_verification.sh
index 393f8e6965..ab8c9be1b7 100755
--- a/scripts/travis/codegen_verification.sh
+++ b/scripts/travis/codegen_verification.sh
@@ -20,8 +20,6 @@ touch gen/generate.go
make build
-"${SCRIPTPATH}"/../buildtools/install_buildtools.sh
-
make gen SHORT_PART_PERIOD=1
echo "Running check_license..."
diff --git a/scripts/travis/test.sh b/scripts/travis/test.sh
index 486316dad2..919ae3588a 100755
--- a/scripts/travis/test.sh
+++ b/scripts/travis/test.sh
@@ -15,9 +15,6 @@ if [ -z "${SKIP_GO_INSTALLATION}" ]; then
eval "$(~/gimme "${GOLANG_VERSION}")"
fi
-# If this command fails the Makefile will select 'go test' instead.
-"${SCRIPTPATH}/../buildtools/install_buildtools.sh" -o "gotest.tools/gotestsum" || true
-
if [ "${OS}-${ARCH}" = "linux-arm" ] || [ "${OS}-${ARCH}" = "windows-amd64" ]; then
# for arm, no tests need to be invoked.
# for now, disable tests on windows.
diff --git a/scripts/travis/upload_coverage.sh b/scripts/travis/upload_coverage.sh
index 8ab3b56ea6..bdeee7e938 100755
--- a/scripts/travis/upload_coverage.sh
+++ b/scripts/travis/upload_coverage.sh
@@ -3,7 +3,7 @@
set -eo pipefail
if [[ -z "$CODECOV_TOKEN" ]]; then
- /usr/bin/env bash scripts/travis/codecov
+ /usr/bin/env bash scripts/travis/codecov "$@"
else
- /usr/bin/env bash scripts/travis/codecov -t $CODECOV_TOKEN
+ /usr/bin/env bash scripts/travis/codecov -t $CODECOV_TOKEN "$@"
fi
diff --git a/shared/algoh/config.go b/shared/algoh/config.go
index d079510ca5..eb4e1a4335 100644
--- a/shared/algoh/config.go
+++ b/shared/algoh/config.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/shared/pingpong/accounts.go b/shared/pingpong/accounts.go
index 6ea255ff26..39ca5ead00 100644
--- a/shared/pingpong/accounts.go
+++ b/shared/pingpong/accounts.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/shared/pingpong/accounts_test.go b/shared/pingpong/accounts_test.go
index 511d478506..c35c032aec 100644
--- a/shared/pingpong/accounts_test.go
+++ b/shared/pingpong/accounts_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/shared/pingpong/config.go b/shared/pingpong/config.go
index ee0f6760d1..f496a09af8 100644
--- a/shared/pingpong/config.go
+++ b/shared/pingpong/config.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/shared/pingpong/pingpong.go b/shared/pingpong/pingpong.go
index 4bf6ba44af..fe58826006 100644
--- a/shared/pingpong/pingpong.go
+++ b/shared/pingpong/pingpong.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/stateproof/abstractions.go b/stateproof/abstractions.go
index 24bec5de07..6e3ae32bd7 100644
--- a/stateproof/abstractions.go
+++ b/stateproof/abstractions.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/stateproof/builder.go b/stateproof/builder.go
index ac77e0c81a..406f8fb5d7 100644
--- a/stateproof/builder.go
+++ b/stateproof/builder.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/stateproof/db.go b/stateproof/db.go
index 8b997643a6..3f2ddbd5e6 100644
--- a/stateproof/db.go
+++ b/stateproof/db.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/stateproof/db_test.go b/stateproof/db_test.go
index fde79d242d..028045d6a9 100644
--- a/stateproof/db_test.go
+++ b/stateproof/db_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/stateproof/msgp_gen.go b/stateproof/msgp_gen.go
index f7a04efecd..ec0afd18eb 100644
--- a/stateproof/msgp_gen.go
+++ b/stateproof/msgp_gen.go
@@ -1,7 +1,7 @@
-package stateproof
-
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package stateproof
+
import (
"sort"
@@ -196,7 +196,7 @@ func (z *sigFromAddr) MsgIsZero() bool {
return ((*z).SignerAddress.MsgIsZero()) && ((*z).Round.MsgIsZero()) && ((*z).Sig.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// SigFromAddrMaxSize returns a maximum valid message size for this message type
func SigFromAddrMaxSize() (s int) {
s = 1 + 2 + basics.AddressMaxSize() + 2 + basics.RoundMaxSize() + 2 + merklesignature.SignatureMaxSize()
return
@@ -496,7 +496,7 @@ func (z *spProver) MsgIsZero() bool {
return ((*z).Prover == nil) && (len((*z).AddrToPos) == 0) && ((*z).VotersHdr.MsgIsZero()) && ((*z).Message.MsgIsZero())
}
-// MaxSize returns a maximum valid message size for this message type
+// SpProverMaxSize returns a maximum valid message size for this message type
func SpProverMaxSize() (s int) {
s = 1 + 4
s += stateproof.ProverMaxSize()
diff --git a/stateproof/msgp_gen_test.go b/stateproof/msgp_gen_test.go
index 0a2c025304..f651ef97bb 100644
--- a/stateproof/msgp_gen_test.go
+++ b/stateproof/msgp_gen_test.go
@@ -1,10 +1,9 @@
//go:build !skip_msgp_testing
-// +build !skip_msgp_testing
-
-package stateproof
// Code generated by github.com/algorand/msgp DO NOT EDIT.
+package stateproof
+
import (
"testing"
diff --git a/stateproof/recovery.go b/stateproof/recovery.go
index 31afd00a10..4da2269b38 100644
--- a/stateproof/recovery.go
+++ b/stateproof/recovery.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/stateproof/signer.go b/stateproof/signer.go
index b939061647..4d19cbb6e6 100644
--- a/stateproof/signer.go
+++ b/stateproof/signer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/stateproof/stateproofMessageGenerator.go b/stateproof/stateproofMessageGenerator.go
index 6f5357f734..6d0be8dad7 100644
--- a/stateproof/stateproofMessageGenerator.go
+++ b/stateproof/stateproofMessageGenerator.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/stateproof/stateproofMessageGenerator_test.go b/stateproof/stateproofMessageGenerator_test.go
index b5e46b137f..5e545c1f3b 100644
--- a/stateproof/stateproofMessageGenerator_test.go
+++ b/stateproof/stateproofMessageGenerator_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/stateproof/verify/stateproof.go b/stateproof/verify/stateproof.go
index b01cd5c95b..0cac131017 100644
--- a/stateproof/verify/stateproof.go
+++ b/stateproof/verify/stateproof.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/stateproof/verify/stateproof_test.go b/stateproof/verify/stateproof_test.go
index 8654531b3e..07e3d9d79c 100644
--- a/stateproof/verify/stateproof_test.go
+++ b/stateproof/verify/stateproof_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/stateproof/worker.go b/stateproof/worker.go
index 2422d1e7f3..fa84c49ad3 100644
--- a/stateproof/worker.go
+++ b/stateproof/worker.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/stateproof/worker_test.go b/stateproof/worker_test.go
index 1690e09379..de1de63c91 100644
--- a/stateproof/worker_test.go
+++ b/stateproof/worker_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/commandandcontrol/README.md b/test/commandandcontrol/README.md
deleted file mode 100644
index cf2fde31f7..0000000000
--- a/test/commandandcontrol/README.md
+++ /dev/null
@@ -1,137 +0,0 @@
-# Command and Control Center
-
-Command and Control Service and distributed Agents are designed to help test the Algorand blockchain network. Through a central service node, agents deployed to Algorand host nodes can be controlled and monitored by clients.
-The initial version support launching the ping pong utility on target hosts and nodes.
-
-```
- CC Agent -> Ping Pong
- /
- CC Client -> CC Service
- \
- CC Agent -> Ping Pong
-```
-
-## Starting the CC Service
-The following command can be used to start the CC Service. Run this from the machine that will host the CC Service.
-```Shell
-cc_service
- -addr :
-```
-
-One or more data dirs can be specified.
-
-## Starting the CC Agent
-The following `cc_agent` command will start the CC Agent. Run this from each of the machines that host the Algod Instances. Specify the data dir for each of the Algod Instances to be controlled.
-```Shell
-cc_agent
- -service-addr :
- -hostname
- -bindir
- -tempdir
- -d
- -d ...
-```
-
-The flag -bindir specifies where the algod binaries are located.
-
-## Using the Client to Control the Agents
-The following cc_agent command will send an action to the CC Service which will then dispatch it to each of the agents.
-```Shell
-cc_client
- -target :
- -component (pingpong)
- -action (start|stop)
- -options
-```
-
-## Example Scripts for running CC Service, Agent, and Client
-The following `example/cc_example.sh` script will launch local instance of the CC Service and CC Agent.
-
-#### cc_example.sh
-```Shell
-#!/usr/bin/env bash
-set -v
-set -x
-
-CC_SERVICE_HOST="localhost:8080"
-BIN_DIR=${GOPATH}/bin/
-TEMP_DIR=${TMPDIR}
-SLEEP_TIME=5
-
-# Start the cc_service
-cc_service \
- -addr ${CC_SERVICE_HOST} &
-
-sleep ${SLEEP_TIME}
-
-# Start the cc_agent for 2 local algod instances
-cc_agent \
- -service-addr ${CC_SERVICE_HOST} \
- -hostname Host1 \
- -bindir ${BIN_DIR} \
- -tempdir ${TEMP_DIR} \
- -d /tmp/test3/root/Node \
- -d /tmp/test3/root/Primary/ &
-```
-
-#### cc_example_client.sh
-Then use the `example/cc_example_client.sh` to start pingpong on the agent, wait 30 seconds, then change pingpong params, wait 30 seconds, then stop pingpong.
-
-```Shell
-#!/usr/bin/env bash
-set -v
-set -x
-
-CC_SERVICE_HOST=localhost:8080
-SLEEP_TIME=10
-
-# Start ping pong running on all known host and instances with configuration from pingpong1.json
-cc_client \
- -service-addr ${CC_SERVICE_HOST} \
- -target *:* \
- -component pingpong \
- -action start \
- -options ./pingpong1.json
-
-# Sleep
-sleep ${SLEEP_TIME}
-
-# Restart ping pong running on all host Host1 and node Primary with configuration from pingpong2.json
-cc_client \
- -service-addr ${CC_SERVICE_HOST} \
- -target Host1:Primary \
- -component pingpong \
- -action start \
- -options ./pingpong2.json
-
-# Sleep
-sleep ${SLEEP_TIME}
-
-# Stop ping pong on all known instances and nodes
-cc_client \
- -service-addr ${CC_SERVICE_HOST} \
- -target *:* \
- -component pingpong \
- -action stop \
- -options ./pingpong1.json
-
-```
-#### pingpong1.json
-Example `pingpong1.json` input options to pingpong
-
-```Json
-{
- "SrcAccount": "",
- "DelayBetweenTxn": 100,
- "RandomizeFee": false,
- "RandomizeAmt": false,
- "RandomizeDst": false,
- "MaxFee": 5,
- "MaxAmt": 20,
- "NumPartAccounts": 10,
- "RunTime": 10000,
- "RestTime": 10000,
- "RefreshTime": 10000,
- "MinAccountFunds": 100000
-}
-```
diff --git a/test/commandandcontrol/cc_agent/component/agent.go b/test/commandandcontrol/cc_agent/component/agent.go
deleted file mode 100644
index 203cdcaca6..0000000000
--- a/test/commandandcontrol/cc_agent/component/agent.go
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright (C) 2019-2025 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 component
-
-import (
- "fmt"
- "strings"
- "time"
-
- "github.com/algorand/websocket"
-
- "github.com/algorand/go-algorand/logging"
- "github.com/algorand/go-algorand/test/commandandcontrol/lib"
-)
-
-// NewAgent factory method for Agent
-func NewAgent() (agent *Agent) {
- var a Agent
- a.componentMap = make(map[string]Component)
- return &a
-}
-
-// Agent represents an instance of the CC Agent
-type Agent struct {
- Host Host
- componentMap map[string]Component
- ServiceConnection *websocket.Conn
- BinDir string
- TempDir string
-}
-
-// Host represents the server hosting the CC Agent and Algod Nodes
-type Host struct {
- Name string
- NodeMap map[string]AlgodNode
-}
-
-// AlgodNode represents an Algod Node (aka Algod Instance)
-type AlgodNode struct {
- Name string
- Status string
- DataDir string
-}
-
-// Common interface that all CC Components must implement
-type componentInstanceInterface interface {
- Init() (err error)
- Process(command Command) (err error)
- Terminate() (err error)
-}
-
-// Component base structure inherited by all CC Components
-type Component struct {
- name string
- componentInstanceMap map[string]componentInstanceInterface
-}
-
-// Instance represents a Component Instance (component + algod node)
-type Instance struct {
- algodName string
- dataDir string
-}
-
-// Init component instance
-func (comp *Instance) Init() (err error) {
- return
-}
-
-// Process component instance command
-func (comp *Instance) Process(command Command) (err error) {
- return
-}
-
-// Terminate component instance
-func (comp *Instance) Terminate() (err error) {
- return
-}
-
-// Command is a command object for Components
-type Command struct {
- command string
- options string
- time int64
- status CommandStatus
-}
-
-var hostAgent = NewAgent()
-
-// GetHostAgent returns the Agent singleton for the host
-func GetHostAgent() (agent *Agent) {
- return hostAgent
-}
-
-// CommandStatus for tracking status of commands
-type CommandStatus int
-
-// START, COMPLETED, FAILED are command status values
-const (
- START CommandStatus = 0
- COMPLETED CommandStatus = 1
- FAILED CommandStatus = 2
-)
-
-// PINGPONG name literal
-const (
- PINGPONG = "pingpong"
- HOSTINFO = "hostinfo"
-)
-
-var log = logging.NewLogger()
-
-// String returns the string value for the command status
-func (status CommandStatus) String() string {
- names := [...]string{
- "START",
- "COMPLETED",
- "FAILED"}
- if status < START || status > FAILED {
- return "Unknown"
- }
- return names[status]
-}
-
-// ProcessRequest processes the command received via the CC Service
-func (agent *Agent) ProcessRequest(managementServiceRequest lib.CCServiceRequest) (err error) {
- log.Infof("received command for %s\n", managementServiceRequest.Component)
- err = agent.ServiceConnection.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("received request %+v ", managementServiceRequest)))
- if err != nil {
- log.Errorf("problem sending ack to client , %v", err)
- }
- switch managementServiceRequest.Component {
- case PINGPONG:
- agent.processPingPongComponentRequest(managementServiceRequest)
- case HOSTINFO:
- log.Warnf("not implemented\n")
- default:
- log.Errorf("usupported component type: %s", managementServiceRequest.Component)
- }
- return
-}
-
-// Return the node list for the target agent list
-func (agent *Agent) getTargetNodeList(targetAgentList []string) (nodeList []string) {
- // determine the list of targeted nodes
- for _, target := range targetAgentList {
- target := strings.TrimSpace(target)
- targetParts := strings.Split(target, ":")
- targetHost := targetParts[0]
- if targetHost == "*" || targetHost == agent.Host.Name {
- targetNode := targetParts[1]
- for _, node := range agent.Host.NodeMap {
- if targetNode == "*" || targetNode == node.Name {
- nodeList = append(nodeList, node.Name)
- }
- }
- }
- }
- return
-}
-
-// lookup the component by name
-func (agent *Agent) lookupComponentByName(componentName string) (component Component) {
- var ok bool
- if component, ok = agent.componentMap[componentName]; !ok {
- component = Component{
- name: componentName,
- componentInstanceMap: make(map[string]componentInstanceInterface),
- }
- agent.componentMap[componentName] = component
- }
- return
-}
-
-// create a new component command based on the service request
-func (agent *Agent) makeNewComponentCommand(managementServiceRequest lib.CCServiceRequest) (componentCommand Command) {
- // create a new command object from the request
- componentCommand = Command{
- command: managementServiceRequest.Command,
- options: managementServiceRequest.Parameters,
- time: time.Now().Unix(),
- status: START,
- }
- return
-}
-
-func (agent *Agent) processPingPongComponentRequest(managementServiceRequest lib.CCServiceRequest) {
-
- var ok bool
- var componentInstance componentInstanceInterface
-
- componentCommand := agent.makeNewComponentCommand(managementServiceRequest)
-
- // get the PingPong Component
- component := agent.lookupComponentByName(PINGPONG)
-
- // get the target list of matching nodes
- nodeList := agent.getTargetNodeList(managementServiceRequest.TargetAgentList)
-
- // send the command to each of the matching nodes
- for _, node := range nodeList {
- // dispatch command to targeted agent node instances
- if componentInstance, ok = component.componentInstanceMap[node]; !ok {
- componentInstance = &PingPongComponentInstance{ctx: nil, cancelFunc: nil, ci: Instance{algodName: node, dataDir: agent.Host.NodeMap[node].DataDir}}
- err := componentInstance.Init()
- if err != nil {
- log.Errorf("error processing ping pong component request %v", err)
- } else {
- component.componentInstanceMap[node] = componentInstance
- }
- }
- err := componentInstance.Process(componentCommand)
- if err != nil {
- log.Errorf("error processing ping pong component request %v", err)
- err = agent.ServiceConnection.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("error processing request %+v with err: %v", managementServiceRequest, err)))
- if err != nil {
- log.Errorf("error sending message to service %v", err)
- }
-
- } else {
- componentCommand.status = COMPLETED
- }
- }
-}
diff --git a/test/commandandcontrol/cc_agent/component/agent_test.go b/test/commandandcontrol/cc_agent/component/agent_test.go
deleted file mode 100644
index 1a17488f00..0000000000
--- a/test/commandandcontrol/cc_agent/component/agent_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2019-2025 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 component
-
-import (
- "testing"
-
- "github.com/algorand/go-algorand/test/partitiontest"
- "github.com/stretchr/testify/assert"
-)
-
-func TestCommandStatus(t *testing.T) {
- partitiontest.PartitionTest(t)
-
- var start = START
- var completed = COMPLETED
- var failed = FAILED
-
- assert.Equal(t, "START", start.String())
- assert.Equal(t, "COMPLETED", completed.String())
- assert.Equal(t, "FAILED", failed.String())
-}
diff --git a/test/commandandcontrol/cc_agent/component/pingPongComponent.go b/test/commandandcontrol/cc_agent/component/pingPongComponent.go
deleted file mode 100644
index 5c2278d35b..0000000000
--- a/test/commandandcontrol/cc_agent/component/pingPongComponent.go
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright (C) 2019-2025 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 component
-
-import (
- "context"
- "encoding/json"
- "fmt"
- "os"
- "time"
-
- "github.com/algorand/go-algorand/libgoal"
- "github.com/algorand/go-algorand/shared/pingpong"
-)
-
-// PingPongComponentInstance extends component instance
-// supports management of ping pong instances
-type PingPongComponentInstance struct {
- ci Instance
- ctx context.Context
- cancelFunc context.CancelFunc
-}
-
-func getPingPongConfig(command Command) (config pingpong.PpConfig, err error) {
- err = json.Unmarshal([]byte(command.options), &config)
- return
-}
-
-// Init the PingPong instance
-func (componentInstance *PingPongComponentInstance) Init() (err error) {
- return
-}
-
-// Process the ping pong instance
-func (componentInstance *PingPongComponentInstance) Process(command Command) (err error) {
-
- switch command.command {
- case "start":
- // terminate previous instance
- err = componentInstance.Terminate()
- if err != nil {
- log.Warnf("terminating component instance resulted in error: %v", err)
- }
-
- // unmarshal config sent by client
- var pingPongConfig pingpong.PpConfig
- pingPongConfig, err = getPingPongConfig(command)
- if err != nil {
- err = fmt.Errorf("error demarshalling ping pong options %s, err: %v", command.options, err)
- log.Errorf("%v", err)
- } else {
- log.Infof("starting Ping Pong with configuration %+v", pingPongConfig)
- err = componentInstance.startPingPong(&pingPongConfig)
- if err != nil {
- err = fmt.Errorf("starting ping pong instance resulted in error: %v", err)
- log.Errorf("%v", err)
- } else {
- log.Infof("ping pong process started")
- }
- }
- case "stop":
- log.Infof("terminating Ping Pong")
- err = componentInstance.Terminate()
- if err != nil {
- err = fmt.Errorf("terminating ping pong instance resulted in error: %v", err)
- log.Errorf("%v", err)
- } else {
- log.Infof("ping pong process terminated")
- }
- default:
- log.Warnf("unsupported pingpong action '%s'", command.command)
- }
- return
-}
-
-// Terminate the ping pong instance
-func (componentInstance *PingPongComponentInstance) Terminate() (err error) {
- if componentInstance.cancelFunc != nil {
- componentInstance.cancelFunc()
- componentInstance.cancelFunc = nil
- componentInstance.ctx = nil
- }
- return
-}
-
-func (componentInstance *PingPongComponentInstance) startPingPong(cfg *pingpong.PpConfig) (err error) {
- // Make a cache dir for wallet handle tokens
- cacheDir, err := os.MkdirTemp(GetHostAgent().TempDir, PINGPONG)
- if err != nil {
- log.Errorf("Cannot make temp dir: %v\n", err)
- return
- }
-
- ac, err := libgoal.MakeClientWithBinDir(GetHostAgent().BinDir, componentInstance.ci.dataDir, cacheDir, libgoal.FullClient)
- if err != nil {
- log.Errorf("failed to create lib goal client %v", err)
- return
- }
-
- // Prepare configuration
- if cfg == nil {
- cfg = &pingpong.DefaultConfig
- }
-
- log.Infof("Preparing to initialize PingPong with config: %+v\n", cfg)
-
- pps := pingpong.NewPingpong(*cfg)
-
- // Initialize accounts if necessary, this may take several attempts while previous transactions to settle
- for i := 0; i < 10; i++ {
- err = pps.PrepareAccounts(&ac)
- if err == nil {
- break
- } else {
- log.Warnf("problem[%d] preparing accounts for transfers: %v\n, retrying", i, err)
- time.Sleep(time.Second * 2)
- }
- }
- if err != nil {
- log.Errorf("Error preparing accounts for transfers: %v\n", err)
- return
- }
-
- log.Infof("Preparing to run PingPong with config: %+v\n", cfg)
-
- // prepare cancelable context
- componentInstance.ctx, componentInstance.cancelFunc = context.WithCancel(context.Background())
-
- // Kick off the real processing
- go pps.RunPingPong(componentInstance.ctx, &ac)
-
- return
-}
diff --git a/test/commandandcontrol/cc_agent/main.go b/test/commandandcontrol/cc_agent/main.go
deleted file mode 100644
index 4e66ec640a..0000000000
--- a/test/commandandcontrol/cc_agent/main.go
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright (C) 2019-2025 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 .
-
-// cc_agent starts agent process on algod host
-package main
-
-import (
- "flag"
- "fmt"
- "net/url"
- "os"
- "os/signal"
- "strings"
- "time"
-
- "github.com/algorand/websocket"
-
- "github.com/algorand/go-algorand/logging"
- "github.com/algorand/go-algorand/test/commandandcontrol/cc_agent/component"
- "github.com/algorand/go-algorand/test/commandandcontrol/lib"
-)
-
-type arrayFlags []string
-
-func (i *arrayFlags) String() string {
- return "my string representation"
-}
-
-func (i *arrayFlags) Set(value string) error {
- *i = append(*i, value)
- return nil
-}
-
-var log = logging.NewLogger()
-var addr = flag.String("service-addr", "localhost:8080", "http service address")
-var hostName = flag.String("hostname", "Host1", "host name")
-var binDir = flag.String("bindir", "", "host name")
-var tempDir = flag.String("tempdir", "", "host name")
-var dataDirs arrayFlags
-
-func init() {
- flag.Var(&dataDirs, "nodedir", "node data directory")
- flag.Var(&dataDirs, "d", "node data directory (shorthand)")
-}
-
-var serverChannel = make(chan []byte, 100)
-
-func checkFlags() (ok bool) {
- ok = true
- if len(dataDirs) == 0 {
- log.Errorf("Use the -nodedir or -d flag to specify one or more node data directories")
- ok = false
- }
- if len(*binDir) == 0 {
- log.Errorf("Use the -bindir flag to specify the location of the algod bin directory")
- ok = false
- }
- if len(*tempDir) == 0 {
- log.Errorf("Use the -tempdir flag to specify the location of the tmp directory directory")
- ok = false
- }
- return ok
-}
-
-func main() {
- flag.Parse()
- log.SetLevel(logging.Debug)
-
- if !checkFlags() {
- os.Exit(1)
- }
-
- component.GetHostAgent().BinDir = *binDir
- component.GetHostAgent().TempDir = *tempDir
-
- // build the algo node map based on the data dirs
- algoNodeMap := make(map[string]component.AlgodNode)
- for _, dataDir := range dataDirs {
- dataDirParts := strings.Split(dataDir, "/")
- nodeName := dataDirParts[len(dataDirParts)-1]
- if nodeName == "" {
- nodeName = dataDirParts[len(dataDirParts)-2]
- }
- algodNode := component.AlgodNode{
- Name: nodeName,
- Status: "OK",
- DataDir: dataDir,
- }
- algoNodeMap[nodeName] = algodNode
- }
-
- interrupt := make(chan os.Signal, 1)
- signal.Notify(interrupt, os.Interrupt)
-
- component.GetHostAgent().Host = component.Host{
- Name: *hostName,
- NodeMap: algoNodeMap,
- }
-
- hostConfigMessage := fmt.Sprintf("New Agent Host Config: %+v", component.GetHostAgent().Host)
- log.Infof("%s", hostConfigMessage)
-
- serverChannel <- []byte(hostConfigMessage)
-
- u := url.URL{Scheme: "ws", Host: *addr, Path: "/agent"}
- log.Infof("connecting to %s", u.String())
-
- serverWs, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
- if err != nil {
- log.Error("dial:", err)
- }
- serverWs.Unsafe = true
- defer func() {
- log.Infof("closing service websocket: %s", serverWs.LocalAddr())
- err := serverWs.Close()
- if err != nil {
- log.Errorf("error closing service websocket %v", err)
- }
- }()
-
- go forwardMessagesToServer(serverWs)
-
- component.GetHostAgent().ServiceConnection = serverWs
-
- done := make(chan struct{})
-
- // accept and process commands sent from CC Service
- go func() {
- defer close(done)
- for {
- var managementServiceRequest lib.CCServiceRequest
- err := serverWs.ReadJSON(&managementServiceRequest)
- if err != nil {
- log.Errorf("ReadJSON %v:", err)
- return
- }
- log.Infof("recv: %+v", managementServiceRequest)
- err = component.GetHostAgent().ProcessRequest(managementServiceRequest)
- if err != nil {
- log.Errorf("error processRequest: %v\n", err)
- return
- }
- serverChannel <- []byte(fmt.Sprintf("agent %s is processing request %+v", component.GetHostAgent().Host.Name, managementServiceRequest))
- }
- }()
-
- // Send heartbeat to CC Service
- ticker := time.NewTicker(time.Second * 60)
- defer ticker.Stop()
-
- for {
- select {
- case <-done:
- return
- case t := <-ticker.C:
- err := serverWs.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintf("heartbeat from agent %s with time %s", component.GetHostAgent().Host.Name, t.String())))
- if err != nil {
- log.Error("write:", err)
- return
- }
- case <-interrupt:
- log.Infof("interrupt")
- // Cleanly close the connection by sending a close message and then
- // waiting (with timeout) for the server to close the connection.
- err := serverWs.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
- if err != nil {
- log.Error("write close:", err)
- return
- }
- select {
- case <-done:
- case <-time.After(time.Second):
- }
- return
- }
- }
-}
-
-func forwardMessagesToServer(serverWs *websocket.Conn) {
- log.Infof("forwardMessagesToServer()\n")
- for {
- // Wait for the next message from the server channel
- msg := <-serverChannel
-
- err := serverWs.WriteMessage(websocket.TextMessage, msg)
- if err != nil {
- log.Errorf("error: %v", err)
- err = serverWs.Close()
- if err != nil {
- log.Errorf("error closing server websocket %v", err)
- }
- }
- }
-}
diff --git a/test/commandandcontrol/cc_client/main.go b/test/commandandcontrol/cc_client/main.go
deleted file mode 100644
index 731d51458d..0000000000
--- a/test/commandandcontrol/cc_client/main.go
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (C) 2019-2025 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 main
-
-import (
- "flag"
- "net/url"
- "os"
- "os/signal"
-
- "github.com/algorand/websocket"
-
- "github.com/algorand/go-algorand/logging"
- "github.com/algorand/go-algorand/test/commandandcontrol/lib"
-)
-
-type arrayFlags []string
-
-func (i *arrayFlags) String() string {
- return "my string representation"
-}
-
-func (i *arrayFlags) Set(value string) error {
- *i = append(*i, value)
- return nil
-}
-
-var log = logging.NewLogger()
-
-var targetHosts arrayFlags
-var addr = flag.String("service-addr", "localhost:8080", "CC service address")
-var componentName = flag.String("component", "pingpong", "name of component to control")
-var componentAction = flag.String("action", "start", "action to perform (start or stop)")
-var componentOptions = flag.String("options", "", "json configuration file for component action")
-var listen = flag.Bool("listen", false, "keep connection to server open and tail output")
-
-func main() {
- flag.Var(&targetHosts, "target", "target host:node, wildcards(*) are supported for host and node")
- flag.Parse()
- log.SetLevel(logging.Debug)
-
- if len(targetHosts) == 0 {
- log.Errorf("Use the --target flag to specify one or more target host:node pairs")
- os.Exit(1)
- }
-
- if *componentOptions == "" {
- log.Errorf("Use the --options flag to specify the command options")
- os.Exit(1)
- }
-
- options, err := os.ReadFile(*componentOptions)
- if err != nil {
- log.Errorf("failed to read options file %s", *componentOptions)
- }
- log.Infof("starting client with options %s", options)
-
- u := url.URL{Scheme: "ws", Host: *addr, Path: "/client"}
- log.Infof("connecting to cc service: %s", u.String())
-
- serverWs, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
- if err != nil {
- log.Fatal("dial:", err)
- }
- defer func() {
- log.Infof("closing service connection: %s", serverWs.RemoteAddr())
- err1 := serverWs.Close()
- if err1 != nil {
- log.Fatalf("error closing service websocket %v", err1)
- }
- }()
- serverWs.Unsafe = true
-
- c := make(chan os.Signal, 1)
- signal.Notify(c, os.Interrupt)
- go func() {
- for sig := range c {
- // sig is a ^C
- log.Errorf("received signal %+v", sig)
- closeServiceConnection(serverWs)
- os.Exit(1)
- }
- }()
-
- ccServiceRequest := lib.CCServiceRequest{
- Component: *componentName,
- Command: *componentAction,
- Parameters: string(options),
- TargetAgentList: targetHosts,
- }
-
- log.Infof("sending service request to %+v", ccServiceRequest)
- err = serverWs.WriteJSON(ccServiceRequest)
- if err != nil {
- log.Fatalf("sending service request resulted in error: %v", err)
- }
-
- for {
- messageType, response, err := serverWs.ReadMessage()
- if err != nil {
- log.Fatalf("reading service response returned error: %v", err)
- } else if messageType == websocket.TextMessage {
- log.Infof("Response: %s", response)
- } else {
- log.Infof("Response: %+v", response)
- }
- if !*listen {
- break
- }
- }
- closeServiceConnection(serverWs)
-}
-
-func closeServiceConnection(serverWs *websocket.Conn) {
- err := serverWs.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
- if err != nil {
- log.Error("write close:", err)
- return
- }
-}
diff --git a/test/commandandcontrol/cc_service/main.go b/test/commandandcontrol/cc_service/main.go
deleted file mode 100644
index e580eb78ef..0000000000
--- a/test/commandandcontrol/cc_service/main.go
+++ /dev/null
@@ -1,313 +0,0 @@
-// Copyright (C) 2019-2025 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 main
-
-import (
- "flag"
- "html/template"
- "net/http"
-
- "github.com/algorand/websocket"
-
- "github.com/algorand/go-algorand/logging"
- "github.com/algorand/go-algorand/test/commandandcontrol/lib"
-)
-
-var addr = flag.String("addr", "localhost:8080", "http service address")
-
-var upgrader = websocket.Upgrader{} // use default options
-
-var clients = make(map[*websocket.Conn]bool) // map of connected clients
-var clientBroadcast = make(chan []byte, 100) // client broadcast channel
-var agents = make(map[*websocket.Conn]bool) // map of connected agents
-var agentBroadcast = make(chan lib.CCServiceRequest, 100) // agent broadcast channel
-
-var log = logging.NewLogger()
-
-func main() {
- flag.Parse()
-
- http.HandleFunc("/client", handleClientConnections)
- http.HandleFunc("/agent", handleAgentConnections)
- http.HandleFunc("/", webHome)
- go broadcastToAgents()
- go broadcastToClients()
- log.Infof("cc service listening for connections: %s", *addr)
- err := http.ListenAndServe(*addr, nil)
- if err != nil {
- log.Errorf("starting http service resulted in error: %v", err)
- }
-}
-
-func handleClientConnections(w http.ResponseWriter, r *http.Request) {
- ws, err := upgrader.Upgrade(w, r, nil)
- if err != nil {
- log.Error("upgrade:", err)
- return
- }
- ws.Unsafe = true
-
- log.Infof("handleClientConnections() with client: %s", ws.RemoteAddr())
-
- clients[ws] = true
-
- go monitorClient(ws)
-}
-
-func handleAgentConnections(w http.ResponseWriter, r *http.Request) {
- // Upgrade initial GET request to a websocket
- ws, err := upgrader.Upgrade(w, r, nil)
- if err != nil {
- log.Error("problem initializing agent web socket", err)
- return
- }
- ws.Unsafe = true
- log.Infof("handleAgentConnections() new client: %v", ws.RemoteAddr())
- // Register our new client
- agents[ws] = true
- log.Infof("handleAgentConnections client count: %d", len(agents))
- go monitorAgent(ws)
-}
-
-func monitorAgent(ws *websocket.Conn) {
-
- defer func() {
- log.Infof("closing client: %s", ws.RemoteAddr())
- err := ws.Close()
- if err != nil {
- log.Errorf("error closing agent websocket %v", err)
- }
- }()
-
- for {
- var message []byte
- var messageType int
- messageType, message, err := ws.ReadMessage()
- if err != nil {
- log.Errorf("error: %v", err)
- break
- }
- switch messageType {
- case websocket.TextMessage:
- log.Infof("received text from agent: %s", message)
- clientBroadcast <- message
- default:
- log.Infof("received other from agent: %s", message)
- }
- }
- // remove the agent from the agent broadcast list
- delete(agents, ws)
-}
-
-func monitorClient(ws *websocket.Conn) {
-
- defer func() {
- log.Infof("closing client: %s", ws.RemoteAddr())
- err := ws.Close()
- if err != nil {
- log.Errorf("error closing agent websocket %v", err)
- }
- }()
-
- for {
- var managementServiceRequest lib.CCServiceRequest
- err := ws.ReadJSON(&managementServiceRequest)
- if err != nil {
- log.Errorf("error: %v", err)
- break
- }
-
- log.Infof("recv: %+v", managementServiceRequest)
- for index := range managementServiceRequest.TargetAgentList {
- log.Infof("target agent : %s", managementServiceRequest.TargetAgentList[index])
- }
- sendCommandToAgents(managementServiceRequest)
- err = ws.WriteJSON(managementServiceRequest)
- if err != nil {
- log.Warnf("error sending response to client: %v", err)
- break
- }
- }
- // remove the client from the client broadcast list
- delete(clients, ws)
-}
-
-func sendCommandToAgents(managementServiceRequest lib.CCServiceRequest) {
- log.Infof("sendCommandToAgents() sending command %+v", managementServiceRequest)
- log.Infof("sendCommandToAgents() there are %d agents", len(agents))
-
- agentBroadcast <- managementServiceRequest
-}
-
-func broadcastToAgents() {
- log.Infof("broadcastToAgents()\n")
- for {
- // Grab the next message from the agentBroadcast channel
- msg := <-agentBroadcast
-
- log.Infof("broadcastToAgents: there are %d agents", len(agents))
-
- // Send it out to every agent that is currently connected
- for agent := range agents {
- log.Infof("broadcastToAgents() sending message %+v", msg)
-
- err := agent.WriteJSON(msg)
- if err != nil {
- log.Errorf("error: %v", err)
- err = agent.Close()
- if err != nil {
- log.Errorf("error closing agent connection: %v", err)
- }
- delete(agents, agent)
- }
- }
- }
-}
-
-func broadcastToClients() {
- log.Infof("broadcastToClients()\n")
- for {
- // Grab the next message from the agentBroadcast channel
- msg := <-clientBroadcast
-
- log.Infof("broadcastToClients: there are %d clients", len(clients))
-
- // Send it out to every client that is currently connected
- for client := range clients {
- log.Infof("broadcastToClients() sending message %sn", msg)
-
- err := client.WriteMessage(websocket.TextMessage, msg)
- if err != nil {
- log.Warnf("can't write to client %v", err)
- err = client.Close()
- if err != nil {
- log.Warnf("closing agent connection: %v", err)
- }
- delete(clients, client)
- }
- }
- }
-}
-
-func webHome(w http.ResponseWriter, r *http.Request) {
- err := homeTemplate.Execute(w, "ws://"+r.Host+"/client")
- if err != nil {
- log.Errorf("error from web service: %v", err)
- }
-}
-
-var homeTemplate = template.Must(template.New("").Parse(`
-
-
-
-
-
-
-
-
-
-
Click "Open" to create a connection to the server,
-"Send" to send a message to the server and "Close" to close the connection.
-You can change the message and send multiple times.
-
-
-
-
-
-
-
-`))
diff --git a/test/commandandcontrol/example/cc_example.sh b/test/commandandcontrol/example/cc_example.sh
deleted file mode 100755
index 1fd34f9538..0000000000
--- a/test/commandandcontrol/example/cc_example.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env bash
-set -v
-set -x
-
-CC_SERVICE_HOST="localhost:9080"
-BIN_DIR=${GOPATH}/bin/
-TEMP_DIR=${TMPDIR}
-SLEEP_TIME=5
-
-# Start the cc_service
-cc_service \
- -addr ${CC_SERVICE_HOST} &
-
-sleep ${SLEEP_TIME}
-
-# Start the cc_agent for 2 local algod instances
-cc_agent \
- -service-addr ${CC_SERVICE_HOST} \
- -hostname Host1 \
- -bindir ${BIN_DIR} \
- -tempdir ${TEMP_DIR} \
- -d /tmp/test3/root/Node \
- -d /tmp/test3/root/Primary/ &
diff --git a/test/commandandcontrol/example/cc_example_client.sh b/test/commandandcontrol/example/cc_example_client.sh
deleted file mode 100755
index e0798639bd..0000000000
--- a/test/commandandcontrol/example/cc_example_client.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env bash
-set -v
-set -x
-
-CC_SERVICE_HOST=localhost:9080
-SLEEP_TIME=10
-
-# Start ping pong running on all known host and instances with configuration from pingpong1.json
-cc_client \
- -service-addr ${CC_SERVICE_HOST} \
- -target *:* \
- -component pingpong \
- -action start \
- -options ./pingpong1.json
-
-# Sleep
-sleep ${SLEEP_TIME}
-
-# Restart ping pong running on all host Host1 and node Primary with configuration from pingpong2.json
-cc_client \
- -service-addr ${CC_SERVICE_HOST} \
- -target Host1:Primary \
- -component pingpong \
- -action start \
- -options ./pingpong2.json
-
-# Sleep
-sleep ${SLEEP_TIME}
-
-# Stop ping pong on all known instances and nodes
-cc_client \
- -service-addr ${CC_SERVICE_HOST} \
- -target *:* \
- -component pingpong \
- -action stop \
- -options ./pingpong1.json
diff --git a/test/commandandcontrol/example/pingpong1.json b/test/commandandcontrol/example/pingpong1.json
deleted file mode 100644
index 9188f3b996..0000000000
--- a/test/commandandcontrol/example/pingpong1.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "SrcAccount": "",
- "DelayBetweenTxn": 100,
- "RandomizeFee": false,
- "RandomizeAmt": false,
- "RandomizeDst": false,
- "MaxFee": 5,
- "MaxAmt": 20,
- "NumPartAccounts": 10,
- "RunTime": 10000,
- "RestTime": 10000,
- "RefreshTime": 10000,
- "MinAccountFunds": 100000
-}
diff --git a/test/commandandcontrol/example/pingpong2.json b/test/commandandcontrol/example/pingpong2.json
deleted file mode 100644
index 6f43a7e661..0000000000
--- a/test/commandandcontrol/example/pingpong2.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "SrcAccount": "",
- "DelayBetweenTxn": 200,
- "RandomizeFee": true,
- "RandomizeAmt": true,
- "RandomizeDst": false,
- "MaxFee": 5,
- "MaxAmt": 200,
- "NumPartAccounts": 20,
- "RunTime": 10000,
- "RestTime": 10000,
- "RefreshTime": 10000,
- "MinAccountFunds": 100000
-}
diff --git a/test/e2e-go/cli/algod/cleanup_test.go b/test/e2e-go/cli/algod/cleanup_test.go
index e310dc9d81..b935a9838e 100644
--- a/test/e2e-go/cli/algod/cleanup_test.go
+++ b/test/e2e-go/cli/algod/cleanup_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/algod/expect/algod_expect_test.go b/test/e2e-go/cli/algod/expect/algod_expect_test.go
index 106b087319..c1e9734ad6 100644
--- a/test/e2e-go/cli/algod/expect/algod_expect_test.go
+++ b/test/e2e-go/cli/algod/expect/algod_expect_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/algod/stdstreams_test.go b/test/e2e-go/cli/algod/stdstreams_test.go
index 2573226939..f192b2fe71 100644
--- a/test/e2e-go/cli/algod/stdstreams_test.go
+++ b/test/e2e-go/cli/algod/stdstreams_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/algoh/expect/algoh_expect_test.go b/test/e2e-go/cli/algoh/expect/algoh_expect_test.go
index f3ea11e2fa..7f4ce79f84 100644
--- a/test/e2e-go/cli/algoh/expect/algoh_expect_test.go
+++ b/test/e2e-go/cli/algoh/expect/algoh_expect_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/goal/account_test.go b/test/e2e-go/cli/goal/account_test.go
index a289d03196..87bd4d20cd 100644
--- a/test/e2e-go/cli/goal/account_test.go
+++ b/test/e2e-go/cli/goal/account_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/goal/clerk_test.go b/test/e2e-go/cli/goal/clerk_test.go
index e791b3a368..9e9b9b196b 100644
--- a/test/e2e-go/cli/goal/clerk_test.go
+++ b/test/e2e-go/cli/goal/clerk_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/goal/common_test.go b/test/e2e-go/cli/goal/common_test.go
index ba6f912664..e656d5d82a 100644
--- a/test/e2e-go/cli/goal/common_test.go
+++ b/test/e2e-go/cli/goal/common_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/goal/expect/catchpointCatchupWebProxy/webproxy.go b/test/e2e-go/cli/goal/expect/catchpointCatchupWebProxy/webproxy.go
index 83621566a0..40a5a58c7a 100644
--- a/test/e2e-go/cli/goal/expect/catchpointCatchupWebProxy/webproxy.go
+++ b/test/e2e-go/cli/goal/expect/catchpointCatchupWebProxy/webproxy.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/goal/expect/goalCmdFlagsTest.exp b/test/e2e-go/cli/goal/expect/goalCmdFlagsTest.exp
old mode 100644
new mode 100755
index 2b833415b0..0498316c59
--- a/test/e2e-go/cli/goal/expect/goalCmdFlagsTest.exp
+++ b/test/e2e-go/cli/goal/expect/goalCmdFlagsTest.exp
@@ -37,11 +37,7 @@ if { [catch {
TestGoalCommandLineFlags "goal asset create --decimals 0 --validrounds 0 --creator ABC --total 100" ".*can not be zero.*"
TestGoalCommandLineFlags "goal asset create --decimals 0 --validrounds 1 --lastvalid 1 --creator ABC --total 100" "Only one of .* can be specified"
- TestGoalCommandLineFlags "goal account changeonlinestatus --validRounds 0 --online" ".*validRounds has been deprecated.*"
- TestGoalCommandLineFlags "goal account changeonlinestatus --firstRound 0 --online" ".*firstRound has been deprecated.*"
- TestGoalCommandLineFlags "goal account changeonlinestatus --validRounds 0 --online" ".*can not be zero.*"
TestGoalCommandLineFlags "goal account changeonlinestatus --validrounds 0 --online" ".*can not be zero.*"
- TestGoalCommandLineFlags "goal account changeonlinestatus --validRounds 0 --lastvalid 1 --online" "Only one of .* can be specified"
TestGoalCommandLineFlags "goal account changeonlinestatus --validrounds 0 --lastvalid 1 --online" "Only one of .* can be specified"
TestGoalCommandLineFlags "goal clerk send --validrounds 0 -a 1 -t ABC -f ABC" ".*can not be zero.*"
diff --git a/test/e2e-go/cli/goal/expect/goal_expect_test.go b/test/e2e-go/cli/goal/expect/goal_expect_test.go
index a61f503f58..f2833b66c0 100644
--- a/test/e2e-go/cli/goal/expect/goal_expect_test.go
+++ b/test/e2e-go/cli/goal/expect/goal_expect_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/goal/node_cleanup_test.go b/test/e2e-go/cli/goal/node_cleanup_test.go
index de2facf6f6..f26c08644b 100644
--- a/test/e2e-go/cli/goal/node_cleanup_test.go
+++ b/test/e2e-go/cli/goal/node_cleanup_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/perf/libgoal_test.go b/test/e2e-go/cli/perf/libgoal_test.go
index 5a23699eb0..8506493d14 100644
--- a/test/e2e-go/cli/perf/libgoal_test.go
+++ b/test/e2e-go/cli/perf/libgoal_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/perf/payment_test.go b/test/e2e-go/cli/perf/payment_test.go
index 98bec2c741..aa5178a2c5 100644
--- a/test/e2e-go/cli/perf/payment_test.go
+++ b/test/e2e-go/cli/perf/payment_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/tealdbg/cdtmock/main.go b/test/e2e-go/cli/tealdbg/cdtmock/main.go
index f2c109a843..77a889661d 100644
--- a/test/e2e-go/cli/tealdbg/cdtmock/main.go
+++ b/test/e2e-go/cli/tealdbg/cdtmock/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/cli/tealdbg/expect/tealdbg_expect_test.go b/test/e2e-go/cli/tealdbg/expect/tealdbg_expect_test.go
index c5da6ec89f..d4d695d662 100644
--- a/test/e2e-go/cli/tealdbg/expect/tealdbg_expect_test.go
+++ b/test/e2e-go/cli/tealdbg/expect/tealdbg_expect_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/accountPerf/sixMillion_test.go b/test/e2e-go/features/accountPerf/sixMillion_test.go
index c5ab87da38..1ed8e1cb4e 100644
--- a/test/e2e-go/features/accountPerf/sixMillion_test.go
+++ b/test/e2e-go/features/accountPerf/sixMillion_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/catchup/basicCatchup_test.go b/test/e2e-go/features/catchup/basicCatchup_test.go
index 1fadd93e49..e4324e2ba1 100644
--- a/test/e2e-go/features/catchup/basicCatchup_test.go
+++ b/test/e2e-go/features/catchup/basicCatchup_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/catchup/catchpointCatchup_test.go b/test/e2e-go/features/catchup/catchpointCatchup_test.go
index c4ff7a3040..a4499d5598 100644
--- a/test/e2e-go/features/catchup/catchpointCatchup_test.go
+++ b/test/e2e-go/features/catchup/catchpointCatchup_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/catchup/stateproofsCatchup_test.go b/test/e2e-go/features/catchup/stateproofsCatchup_test.go
index 9aad0231dc..f4a396286f 100644
--- a/test/e2e-go/features/catchup/stateproofsCatchup_test.go
+++ b/test/e2e-go/features/catchup/stateproofsCatchup_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/devmode/devmode_test.go b/test/e2e-go/features/devmode/devmode_test.go
index 209cc07eb3..4bc89b90c1 100644
--- a/test/e2e-go/features/devmode/devmode_test.go
+++ b/test/e2e-go/features/devmode/devmode_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/followernode/syncDeltas_test.go b/test/e2e-go/features/followernode/syncDeltas_test.go
index 0a76b26310..b360d6c698 100644
--- a/test/e2e-go/features/followernode/syncDeltas_test.go
+++ b/test/e2e-go/features/followernode/syncDeltas_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/followernode/syncRestart_test.go b/test/e2e-go/features/followernode/syncRestart_test.go
index 911e48593e..81030c8d35 100644
--- a/test/e2e-go/features/followernode/syncRestart_test.go
+++ b/test/e2e-go/features/followernode/syncRestart_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/incentives/challenge_test.go b/test/e2e-go/features/incentives/challenge_test.go
index 62856a7e93..6d4bb6552f 100644
--- a/test/e2e-go/features/incentives/challenge_test.go
+++ b/test/e2e-go/features/incentives/challenge_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/incentives/payouts_test.go b/test/e2e-go/features/incentives/payouts_test.go
index dd73aa2b73..27da27138b 100644
--- a/test/e2e-go/features/incentives/payouts_test.go
+++ b/test/e2e-go/features/incentives/payouts_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/incentives/suspension_test.go b/test/e2e-go/features/incentives/suspension_test.go
index 497822310a..965b837c98 100644
--- a/test/e2e-go/features/incentives/suspension_test.go
+++ b/test/e2e-go/features/incentives/suspension_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/incentives/whalejoin_test.go b/test/e2e-go/features/incentives/whalejoin_test.go
index 9334cfe03a..082b803f83 100644
--- a/test/e2e-go/features/incentives/whalejoin_test.go
+++ b/test/e2e-go/features/incentives/whalejoin_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/multisig/multisig_test.go b/test/e2e-go/features/multisig/multisig_test.go
index a04ff487a0..87d94adebb 100644
--- a/test/e2e-go/features/multisig/multisig_test.go
+++ b/test/e2e-go/features/multisig/multisig_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/p2p/p2p_basic_test.go b/test/e2e-go/features/p2p/p2p_basic_test.go
index 10da4632cd..2f5614ee5d 100644
--- a/test/e2e-go/features/p2p/p2p_basic_test.go
+++ b/test/e2e-go/features/p2p/p2p_basic_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/participation/accountParticipationTransitions_test.go b/test/e2e-go/features/participation/accountParticipationTransitions_test.go
index e2ee562121..271b134ef4 100644
--- a/test/e2e-go/features/participation/accountParticipationTransitions_test.go
+++ b/test/e2e-go/features/participation/accountParticipationTransitions_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/participation/deletePartKeys_test.go b/test/e2e-go/features/participation/deletePartKeys_test.go
index 951e80510f..b3a9c30026 100644
--- a/test/e2e-go/features/participation/deletePartKeys_test.go
+++ b/test/e2e-go/features/participation/deletePartKeys_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/participation/onlineOfflineParticipation_test.go b/test/e2e-go/features/participation/onlineOfflineParticipation_test.go
index 21193d120f..1b54c42c8e 100644
--- a/test/e2e-go/features/participation/onlineOfflineParticipation_test.go
+++ b/test/e2e-go/features/participation/onlineOfflineParticipation_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/participation/overlappingParticipationKeys_test.go b/test/e2e-go/features/participation/overlappingParticipationKeys_test.go
index e16a2fc270..8c35e00253 100644
--- a/test/e2e-go/features/participation/overlappingParticipationKeys_test.go
+++ b/test/e2e-go/features/participation/overlappingParticipationKeys_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/participation/participationExpiration_test.go b/test/e2e-go/features/participation/participationExpiration_test.go
index 0f7af6cb71..d6d44b5eaf 100644
--- a/test/e2e-go/features/participation/participationExpiration_test.go
+++ b/test/e2e-go/features/participation/participationExpiration_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/participation/participationRewards_test.go b/test/e2e-go/features/participation/participationRewards_test.go
index d65214f39f..ae81d26e4a 100644
--- a/test/e2e-go/features/participation/participationRewards_test.go
+++ b/test/e2e-go/features/participation/participationRewards_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/partitionRecovery/partitionRecovery_test.go b/test/e2e-go/features/partitionRecovery/partitionRecovery_test.go
index f2994b5a73..88fcd4aec6 100644
--- a/test/e2e-go/features/partitionRecovery/partitionRecovery_test.go
+++ b/test/e2e-go/features/partitionRecovery/partitionRecovery_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/privatenet/privatenet_test.go b/test/e2e-go/features/privatenet/privatenet_test.go
index 36232faf98..a5bbe3a542 100644
--- a/test/e2e-go/features/privatenet/privatenet_test.go
+++ b/test/e2e-go/features/privatenet/privatenet_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/stateproofs/stateproofs_test.go b/test/e2e-go/features/stateproofs/stateproofs_test.go
index df13c1bdc5..d2ab4af114 100644
--- a/test/e2e-go/features/stateproofs/stateproofs_test.go
+++ b/test/e2e-go/features/stateproofs/stateproofs_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -446,7 +446,7 @@ func verifyStateProofForRound(r *require.Assertions, fixture *fixtures.RestClien
return stateProofMessage, nextStateProofBlock
}
-// TestStateProofRecoveryDuringRecoveryInterval simulates a situation where the stateproof chain is lagging after the main chain.
+// TestStateProofRecoveryDuringRecoveryPeriod simulates a situation where the stateproof chain is lagging after the main chain.
// If the missing data is being accepted before StateProofMaxRecoveryIntervals * StateProofInterval rounds have passed, nodes should
// be able to produce stateproofs and continue as normal
func TestStateProofRecoveryDuringRecoveryPeriod(t *testing.T) {
diff --git a/test/e2e-go/features/teal/compile_test.go b/test/e2e-go/features/teal/compile_test.go
index 7cd71d191d..d4d58f23f7 100644
--- a/test/e2e-go/features/teal/compile_test.go
+++ b/test/e2e-go/features/teal/compile_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/transactions/accountv2_test.go b/test/e2e-go/features/transactions/accountv2_test.go
index 93e17f85e4..7f2fef82d3 100644
--- a/test/e2e-go/features/transactions/accountv2_test.go
+++ b/test/e2e-go/features/transactions/accountv2_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/transactions/app_pages_test.go b/test/e2e-go/features/transactions/app_pages_test.go
index 27d791acbc..7fd73a4c13 100644
--- a/test/e2e-go/features/transactions/app_pages_test.go
+++ b/test/e2e-go/features/transactions/app_pages_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/transactions/application_test.go b/test/e2e-go/features/transactions/application_test.go
index 8068b8c6fb..86221b642b 100644
--- a/test/e2e-go/features/transactions/application_test.go
+++ b/test/e2e-go/features/transactions/application_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/transactions/asset_test.go b/test/e2e-go/features/transactions/asset_test.go
index 16f7787113..0f193a3916 100644
--- a/test/e2e-go/features/transactions/asset_test.go
+++ b/test/e2e-go/features/transactions/asset_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/transactions/close_account_test.go b/test/e2e-go/features/transactions/close_account_test.go
index f6bcd791cb..3a941722cc 100644
--- a/test/e2e-go/features/transactions/close_account_test.go
+++ b/test/e2e-go/features/transactions/close_account_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/transactions/group_test.go b/test/e2e-go/features/transactions/group_test.go
index 0e580fda39..5d69dfb1a0 100644
--- a/test/e2e-go/features/transactions/group_test.go
+++ b/test/e2e-go/features/transactions/group_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/transactions/lease_test.go b/test/e2e-go/features/transactions/lease_test.go
index 135dea6073..937bc90be2 100644
--- a/test/e2e-go/features/transactions/lease_test.go
+++ b/test/e2e-go/features/transactions/lease_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/transactions/logicsig_test.go b/test/e2e-go/features/transactions/logicsig_test.go
index 2000a6f6a6..4a03e928d4 100644
--- a/test/e2e-go/features/transactions/logicsig_test.go
+++ b/test/e2e-go/features/transactions/logicsig_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/transactions/onlineStatusChange_test.go b/test/e2e-go/features/transactions/onlineStatusChange_test.go
index 98b1f76708..5b96589d40 100644
--- a/test/e2e-go/features/transactions/onlineStatusChange_test.go
+++ b/test/e2e-go/features/transactions/onlineStatusChange_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/transactions/proof_test.go b/test/e2e-go/features/transactions/proof_test.go
index a03c095ebd..ad95f8ef35 100644
--- a/test/e2e-go/features/transactions/proof_test.go
+++ b/test/e2e-go/features/transactions/proof_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/features/transactions/sendReceive_test.go b/test/e2e-go/features/transactions/sendReceive_test.go
index 067691a6a0..7c38c12a88 100644
--- a/test/e2e-go/features/transactions/sendReceive_test.go
+++ b/test/e2e-go/features/transactions/sendReceive_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/globals/constants.go b/test/e2e-go/globals/constants.go
index 48ab3624d5..48acc9ab94 100644
--- a/test/e2e-go/globals/constants.go
+++ b/test/e2e-go/globals/constants.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/kmd/e2e_kmd_server_client_test.go b/test/e2e-go/kmd/e2e_kmd_server_client_test.go
index fe326f3ea9..e2134c29e2 100644
--- a/test/e2e-go/kmd/e2e_kmd_server_client_test.go
+++ b/test/e2e-go/kmd/e2e_kmd_server_client_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/kmd/e2e_kmd_sqlite_test.go b/test/e2e-go/kmd/e2e_kmd_sqlite_test.go
index 52dbe88283..02f779f6d0 100644
--- a/test/e2e-go/kmd/e2e_kmd_sqlite_test.go
+++ b/test/e2e-go/kmd/e2e_kmd_sqlite_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/kmd/e2e_kmd_wallet_keyops_test.go b/test/e2e-go/kmd/e2e_kmd_wallet_keyops_test.go
index 142aad39aa..6e74b7556c 100644
--- a/test/e2e-go/kmd/e2e_kmd_wallet_keyops_test.go
+++ b/test/e2e-go/kmd/e2e_kmd_wallet_keyops_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/kmd/e2e_kmd_wallet_multisig_test.go b/test/e2e-go/kmd/e2e_kmd_wallet_multisig_test.go
index b69ffa76b7..17caed5244 100644
--- a/test/e2e-go/kmd/e2e_kmd_wallet_multisig_test.go
+++ b/test/e2e-go/kmd/e2e_kmd_wallet_multisig_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/kmd/e2e_kmd_wallet_test.go b/test/e2e-go/kmd/e2e_kmd_wallet_test.go
index 5105e0caae..64206c1425 100644
--- a/test/e2e-go/kmd/e2e_kmd_wallet_test.go
+++ b/test/e2e-go/kmd/e2e_kmd_wallet_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/perf/basic_test.go b/test/e2e-go/perf/basic_test.go
index 7c1e9c5125..3f29fdfdb2 100644
--- a/test/e2e-go/perf/basic_test.go
+++ b/test/e2e-go/perf/basic_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/restAPI/helpers.go b/test/e2e-go/restAPI/helpers.go
index 845c41bb62..7dec672cf2 100644
--- a/test/e2e-go/restAPI/helpers.go
+++ b/test/e2e-go/restAPI/helpers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/restAPI/other/appsRestAPI_test.go b/test/e2e-go/restAPI/other/appsRestAPI_test.go
index 17454a9de5..7cb209d9ee 100644
--- a/test/e2e-go/restAPI/other/appsRestAPI_test.go
+++ b/test/e2e-go/restAPI/other/appsRestAPI_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/restAPI/other/misc_test.go b/test/e2e-go/restAPI/other/misc_test.go
index 287aef0abd..aa4e72750f 100644
--- a/test/e2e-go/restAPI/other/misc_test.go
+++ b/test/e2e-go/restAPI/other/misc_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/restAPI/restClient_test.go b/test/e2e-go/restAPI/restClient_test.go
index b6a4fc96cb..c8585dd080 100644
--- a/test/e2e-go/restAPI/restClient_test.go
+++ b/test/e2e-go/restAPI/restClient_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/restAPI/simulate/simulateRestAPI_test.go b/test/e2e-go/restAPI/simulate/simulateRestAPI_test.go
index db3ca80be6..47903fa7b8 100644
--- a/test/e2e-go/restAPI/simulate/simulateRestAPI_test.go
+++ b/test/e2e-go/restAPI/simulate/simulateRestAPI_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/restAPI/stateproof/stateproofRestAPI_test.go b/test/e2e-go/restAPI/stateproof/stateproofRestAPI_test.go
index 038509a89d..f86230dc16 100644
--- a/test/e2e-go/restAPI/stateproof/stateproofRestAPI_test.go
+++ b/test/e2e-go/restAPI/stateproof/stateproofRestAPI_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/stress/transactions/createManyAndGoOnline_test.go b/test/e2e-go/stress/transactions/createManyAndGoOnline_test.go
index 3f7d779afc..5e17a72080 100644
--- a/test/e2e-go/stress/transactions/createManyAndGoOnline_test.go
+++ b/test/e2e-go/stress/transactions/createManyAndGoOnline_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/upgrades/application_support_test.go b/test/e2e-go/upgrades/application_support_test.go
index 4e8f04b8cf..8931c0736a 100644
--- a/test/e2e-go/upgrades/application_support_test.go
+++ b/test/e2e-go/upgrades/application_support_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -68,7 +68,7 @@ func makeApplicationUpgradeConsensus(t *testing.T) (appConsensus config.Consensu
return
}
-// TestApplicationsUpgrade tests that we can safely upgrade from a version that doesn't support applications
+// TestApplicationsUpgradeOverREST tests that we can safely upgrade from a version that doesn't support applications
// to a version that supports applications. It verify that prior to supporting applications, the node would not accept
// any application transaction and after the upgrade is complete, it would support that.
func TestApplicationsUpgradeOverREST(t *testing.T) {
@@ -295,7 +295,7 @@ int 1
a.Equal(creator, app.Params.Creator)
}
-// TestApplicationsUpgrade tests that we can safely upgrade from a version that doesn't support applications
+// TestApplicationsUpgradeOverGossip tests that we can safely upgrade from a version that doesn't support applications
// to a version that supports applications. It verify that prior to supporting applications, the node would not accept
// any application transaction and after the upgrade is complete, it would support that.
func TestApplicationsUpgradeOverGossip(t *testing.T) {
diff --git a/test/e2e-go/upgrades/rekey_support_test.go b/test/e2e-go/upgrades/rekey_support_test.go
index fce4f98d2b..f53dc2c113 100644
--- a/test/e2e-go/upgrades/rekey_support_test.go
+++ b/test/e2e-go/upgrades/rekey_support_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/e2e-go/upgrades/send_receive_upgrade_test.go b/test/e2e-go/upgrades/send_receive_upgrade_test.go
index 1f0a62ef8a..eba4b1beec 100644
--- a/test/e2e-go/upgrades/send_receive_upgrade_test.go
+++ b/test/e2e-go/upgrades/send_receive_upgrade_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -87,7 +87,7 @@ func TestAccountsCanSendMoneyAcrossUpgradeV32toV35(t *testing.T) {
testAccountsCanSendMoneyAcrossUpgrade(t, filepath.Join("nettemplates", "TwoNodes50EachV32Upgrade.json"), targetVersion)
}
-// ConsensusTestFastUpgrade is meant for testing of protocol upgrades:
+// consensusTestFastUpgrade is meant for testing of protocol upgrades:
// during testing, it is equivalent to another protocol with the exception
// of the upgrade parameters, which allow for upgrades to take place after
// only a few rounds.
diff --git a/test/e2e-go/upgrades/stateproof_participation_test.go b/test/e2e-go/upgrades/stateproof_participation_test.go
index db33661d25..0049a0bdd8 100644
--- a/test/e2e-go/upgrades/stateproof_participation_test.go
+++ b/test/e2e-go/upgrades/stateproof_participation_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/framework/fixtures/baseFixture.go b/test/framework/fixtures/baseFixture.go
index febefbce15..ad41ec6a4f 100644
--- a/test/framework/fixtures/baseFixture.go
+++ b/test/framework/fixtures/baseFixture.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/framework/fixtures/expectFixture.go b/test/framework/fixtures/expectFixture.go
index 418a2bd6bd..218d82ca86 100644
--- a/test/framework/fixtures/expectFixture.go
+++ b/test/framework/fixtures/expectFixture.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/framework/fixtures/fixture.go b/test/framework/fixtures/fixture.go
index 2a6fea1fab..025719a7f9 100644
--- a/test/framework/fixtures/fixture.go
+++ b/test/framework/fixtures/fixture.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/framework/fixtures/goalFixture.go b/test/framework/fixtures/goalFixture.go
index 5c5c3fa6ce..99170488b9 100644
--- a/test/framework/fixtures/goalFixture.go
+++ b/test/framework/fixtures/goalFixture.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -206,10 +206,10 @@ func (f *GoalFixture) ClerkSendNoteb64(from, to string, amount, fee int64, noteb
func parseClerkSendResponse(ret string) (txID string, err error) {
if strings.HasPrefix(ret, "Sent ") {
- txIndex := strings.Index(ret, "ID: ")
- if txIndex > 0 {
+ _, after, ok := strings.Cut(ret, "ID: ")
+ if ok {
// Extract "tx-" string
- txID = ret[txIndex+4:]
+ txID = after
txID = txID[:52] // 52 is the len of txid
return
}
diff --git a/test/framework/fixtures/kmdFixture.go b/test/framework/fixtures/kmdFixture.go
index f07b0a26b4..50ae577ce3 100644
--- a/test/framework/fixtures/kmdFixture.go
+++ b/test/framework/fixtures/kmdFixture.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/framework/fixtures/libgoalFixture.go b/test/framework/fixtures/libgoalFixture.go
index bd91a0d8e6..38d3b3ec4d 100644
--- a/test/framework/fixtures/libgoalFixture.go
+++ b/test/framework/fixtures/libgoalFixture.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/framework/fixtures/restClientFixture.go b/test/framework/fixtures/restClientFixture.go
index 9d05276933..01ac30c8f6 100644
--- a/test/framework/fixtures/restClientFixture.go
+++ b/test/framework/fixtures/restClientFixture.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/framework/fixtures/webProxyFixture.go b/test/framework/fixtures/webProxyFixture.go
index 8c43cc31c1..199008c3eb 100644
--- a/test/framework/fixtures/webProxyFixture.go
+++ b/test/framework/fixtures/webProxyFixture.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/heapwatch/block_history.py b/test/heapwatch/block_history.py
index b74267d6f3..e7e8a66c5b 100644
--- a/test/heapwatch/block_history.py
+++ b/test/heapwatch/block_history.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (C) 2019-2025 Algorand, Inc.
+# Copyright (C) 2019-2026 Algorand, Inc.
# This file is part of go-algorand
#
# go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/heapwatch/block_history_plot.py b/test/heapwatch/block_history_plot.py
index b893dc92ee..7738ee52da 100644
--- a/test/heapwatch/block_history_plot.py
+++ b/test/heapwatch/block_history_plot.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (C) 2019-2025 Algorand, Inc.
+# Copyright (C) 2019-2026 Algorand, Inc.
# This file is part of go-algorand
#
# go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/heapwatch/block_history_relays.py b/test/heapwatch/block_history_relays.py
index 78b4bd2544..785938d9c2 100644
--- a/test/heapwatch/block_history_relays.py
+++ b/test/heapwatch/block_history_relays.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (C) 2019-2025 Algorand, Inc.
+# Copyright (C) 2019-2026 Algorand, Inc.
# This file is part of go-algorand
#
# go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/heapwatch/client_ram_report.py b/test/heapwatch/client_ram_report.py
index 2660204401..108090791f 100644
--- a/test/heapwatch/client_ram_report.py
+++ b/test/heapwatch/client_ram_report.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (C) 2019-2025 Algorand, Inc.
+# Copyright (C) 2019-2026 Algorand, Inc.
# This file is part of go-algorand
#
# go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/heapwatch/heapWatch.py b/test/heapwatch/heapWatch.py
index f2443855bf..5826a4594b 100644
--- a/test/heapwatch/heapWatch.py
+++ b/test/heapwatch/heapWatch.py
@@ -1,6 +1,6 @@
#!/usr/bin/python3
#
-# Copyright (C) 2019-2025 Algorand, Inc.
+# Copyright (C) 2019-2026 Algorand, Inc.
# This file is part of go-algorand
#
# go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/heapwatch/metrics_delta.py b/test/heapwatch/metrics_delta.py
index 71439fe101..cc69a2fc67 100644
--- a/test/heapwatch/metrics_delta.py
+++ b/test/heapwatch/metrics_delta.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (C) 2019-2025 Algorand, Inc.
+# Copyright (C) 2019-2026 Algorand, Inc.
# This file is part of go-algorand
#
# go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/heapwatch/nodeHostTarget.py b/test/heapwatch/nodeHostTarget.py
index 434adfd564..101ad36e47 100644
--- a/test/heapwatch/nodeHostTarget.py
+++ b/test/heapwatch/nodeHostTarget.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (C) 2019-2025 Algorand, Inc.
+# Copyright (C) 2019-2026 Algorand, Inc.
# This file is part of go-algorand
#
# go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/heapwatch/runNodeHost.py b/test/heapwatch/runNodeHost.py
index c9c3e46b90..658a104167 100644
--- a/test/heapwatch/runNodeHost.py
+++ b/test/heapwatch/runNodeHost.py
@@ -1,5 +1,5 @@
#!/usr/bin/python3
-# Copyright (C) 2019-2025 Algorand, Inc.
+# Copyright (C) 2019-2026 Algorand, Inc.
# This file is part of go-algorand
#
# go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/netperf-go/puppeteer/main.go b/test/netperf-go/puppeteer/main.go
index f006089223..ee10b421b5 100644
--- a/test/netperf-go/puppeteer/main.go
+++ b/test/netperf-go/puppeteer/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/netperf-go/puppeteer/promMetricFetcher.go b/test/netperf-go/puppeteer/promMetricFetcher.go
index 059d5ac6b3..856a07720c 100644
--- a/test/netperf-go/puppeteer/promMetricFetcher.go
+++ b/test/netperf-go/puppeteer/promMetricFetcher.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/netperf-go/puppeteer/promMetricFetcher_test.go b/test/netperf-go/puppeteer/promMetricFetcher_test.go
index 62726c985b..8f63f931f0 100644
--- a/test/netperf-go/puppeteer/promMetricFetcher_test.go
+++ b/test/netperf-go/puppeteer/promMetricFetcher_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/netperf-go/puppeteer/puppeteer.go b/test/netperf-go/puppeteer/puppeteer.go
index 65716eac45..8c8e15c472 100644
--- a/test/netperf-go/puppeteer/puppeteer.go
+++ b/test/netperf-go/puppeteer/puppeteer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/netperf-go/puppeteer/puppeteer_test.go b/test/netperf-go/puppeteer/puppeteer_test.go
index 3b68efa0b2..74975af2e5 100644
--- a/test/netperf-go/puppeteer/puppeteer_test.go
+++ b/test/netperf-go/puppeteer/puppeteer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/netperf-go/puppeteer/roundpoller.go b/test/netperf-go/puppeteer/roundpoller.go
index 3a71c73c1c..4f55c1314e 100644
--- a/test/netperf-go/puppeteer/roundpoller.go
+++ b/test/netperf-go/puppeteer/roundpoller.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/partitiontest/filtering.go b/test/partitiontest/filtering.go
index 03ae217424..1989640098 100644
--- a/test/partitiontest/filtering.go
+++ b/test/partitiontest/filtering.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/reflectionhelpers/helpers.go b/test/reflectionhelpers/helpers.go
index 07d4cc26b1..7cd9334c3f 100644
--- a/test/reflectionhelpers/helpers.go
+++ b/test/reflectionhelpers/helpers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/test/release-testing/gossip-txsync-upgrade/functional-test.sh b/test/release-testing/gossip-txsync-upgrade/functional-test.sh
index 2153c982c0..18f98914a0 100755
--- a/test/release-testing/gossip-txsync-upgrade/functional-test.sh
+++ b/test/release-testing/gossip-txsync-upgrade/functional-test.sh
@@ -1145,7 +1145,7 @@ function generate_transactions() {
trace_if_needed "Creating keyreg tx"
fee=$(get_random_fee)
- "$bin_dir/goal" account changeonlinestatus --fee $fee --address $src_addr -o -t "$tx_dir/keyreg.tx" --firstRound "$firstvalid" --validRounds "$validrounds" -d "$network_dir/$sender_name"
+ "$bin_dir/goal" account changeonlinestatus --fee $fee --address $src_addr -o -t "$tx_dir/keyreg.tx" --firstvalid "$firstvalid" --validrounds "$validrounds" -d "$network_dir/$sender_name"
"$bin_dir/goal" clerk sign -i "$tx_dir/keyreg.tx" -o "$tx_dir/keyreg.stx" -d "$network_dir/$sender_name"
trace_if_needed "Creating logic sig payset tx"
diff --git a/test/scripts/e2e_client_runner.py b/test/scripts/e2e_client_runner.py
index 325a8a11e9..fd938d2a18 100755
--- a/test/scripts/e2e_client_runner.py
+++ b/test/scripts/e2e_client_runner.py
@@ -514,9 +514,9 @@ def main():
def finish_test_results(jsonfile, jsonpath, junitpath):
# This only runs in CI, since TEST_RESULTS env var controls the
# block that opens the jsonfile, and registers this atexit. So we
- # assume jsonfile is open, and gotestsum available.
+ # assume jsonfile is open.
jsonfile.close()
- xrun(["gotestsum", "--junitfile", junitpath, "--raw-command", "cat", jsonpath])
+ xrun(["go", "tool", "-modfile=tool.mod", "gotestsum", "--junitfile", junitpath, "--raw-command", "cat", jsonpath])
if __name__ == '__main__':
diff --git a/test/scripts/e2e_go_tests.sh b/test/scripts/e2e_go_tests.sh
index 66165c39b5..b0e2ffdb10 100755
--- a/test/scripts/e2e_go_tests.sh
+++ b/test/scripts/e2e_go_tests.sh
@@ -7,16 +7,6 @@ set -o pipefail
export GOPATH=$(go env GOPATH)
-# Needed for now because circleci doesn't use makefile yet
-if [ -z "$(which gotestsum)" ]; then
- GOTESTCOMMAND=${GOTESTCOMMAND:="go test"}
-else
- TEST_RESULTS=${TEST_RESULTS:="$(pwd)"}
- GOTESTCOMMAND=${GOTESTCOMMAND:="gotestsum --format testname --junitfile ${TEST_RESULTS}/results.xml --jsonfile ${TEST_RESULTS}/testresults.json --"}
-fi
-
-echo "GOTESTCOMMAND will be: ${GOTESTCOMMAND}"
-
# If one or more -t are specified, use GOTESTCOMMAND -run for each
TESTPATTERNS=()
@@ -54,6 +44,10 @@ fi
# Anchor our repo root reference location
REPO_ROOT="$( cd "$(dirname "$0")" ; pwd -P )"/../..
+# Needed for now because circleci doesn't use makefile yet
+TEST_RESULTS=${TEST_RESULTS:="$(pwd)"}
+GOTESTCOMMAND=${GOTESTCOMMAND:="go tool -modfile=${REPO_ROOT}/tool.mod gotestsum --format testname --junitfile ${TEST_RESULTS}/results.xml --jsonfile ${TEST_RESULTS}/testresults.json --"}
+
if [ "${NORACEBUILD}" = "" ]; then
# Need bin-race binaries for e2e tests
if [ "${NO_BUILD}" != "true" ]; then
diff --git a/test/scripts/e2e_subs/absentee.py b/test/scripts/e2e_subs/absentee.py
index 7e72d8a966..7c5285d36e 100755
--- a/test/scripts/e2e_subs/absentee.py
+++ b/test/scripts/e2e_subs/absentee.py
@@ -25,7 +25,9 @@
pblock = goal.algod.block_info(txinfo['confirmed-round'])['block']
assert pblock["prp"] != "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ"
prp_info = goal.algod.account_info(pblock["prp"])
-assert prp_info["round"] == pblock["rnd"], pblock
+# account_info returns data at the latest round, which may advance
+# beyond the block round by the time we query it.
+assert prp_info["round"] >= pblock["rnd"], (prp_info["round"], pblock["rnd"], pblock)
assert "last-proposed" in prp_info, prp_info # they just did!
assert prp_info["last-proposed"] > 0
assert "last-heartbeat" not in prp_info, prp_info # was a genesis account
diff --git a/test/scripts/e2e_subs/app-assets-access.sh b/test/scripts/e2e_subs/app-assets-access.sh
index 38078c8276..b8d58190c9 100755
--- a/test/scripts/e2e_subs/app-assets-access.sh
+++ b/test/scripts/e2e_subs/app-assets-access.sh
@@ -318,7 +318,7 @@ $ASSETID3"
appl "close(uint64):void" --from="$SMALL" --app-arg "int:$ASSETID" \
--holding="$ASSETID+$APPACCT,$ASSETID+$SMALL"
appl "close(uint64):void" --from="$SMALL" --app-arg "int:$ASSETID3" \
- --holding="$ASSETID3+$APPACCT,$ASSETID3+$SMALL"
+ --holding="$ASSETID3+$APPACCT" --holding="$ASSETID3+$SMALL"
[[ "$(asset_ids "$APPACCT")" = "" ]] || exit 1 # account has no assets
# app creates asset
diff --git a/test/scripts/e2e_subs/app-update.sh b/test/scripts/e2e_subs/app-update.sh
new file mode 100755
index 0000000000..4649512ec5
--- /dev/null
+++ b/test/scripts/e2e_subs/app-update.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+filename=$(basename "$0")
+scriptname="${filename%.*}"
+date "+${scriptname} start %Y%m%d_%H%M%S"
+
+set -e
+set -x
+set -o pipefail
+export SHELLOPTS
+
+WALLET=$1
+
+gcmd="goal -w ${WALLET}"
+
+ACCOUNT=$(${gcmd} account list|awk '{ print $3 }')
+
+# approval program
+printf '#pragma version 2\nint 1' > "${TEMPDIR}/simple.teal"
+PROGRAM_FILE="${TEMPDIR}/simple.teal"
+
+# Create app with two global ints
+APPID=$(${gcmd} app create --creator ${ACCOUNT} --approval-prog "${PROGRAM_FILE}" --clear-prog "${PROGRAM_FILE}" --global-ints 2 | grep Created | awk '{ print $6 }')
+
+APP_INFO=$(${gcmd} app info --app-id $APPID 2>&1)
+EXPECT="Max global integers: 2"
+if [[ $APP_INFO != *"${EXPECT}"* ]]; then
+ date "+${scriptname} FAIL wrong initial schema %Y%m%d_%H%M%S"
+ false
+fi
+
+${gcmd} app update --app-id $APPID --from ${ACCOUNT} --approval-prog "${PROGRAM_FILE}" --clear-prog "${PROGRAM_FILE}" --global-ints 3
+
+APP_INFO=$(${gcmd} app info --app-id $APPID 2>&1)
+EXPECT="Max global integers: 3"
+if [[ $APP_INFO != *"${EXPECT}"* ]]; then
+ date "+${scriptname} FAIL wrong updated schema %Y%m%d_%H%M%S"
+ false
+fi
+
+${gcmd} app update --app-id $APPID --from ${ACCOUNT} --approval-prog "${PROGRAM_FILE}" --clear-prog "${PROGRAM_FILE}" --global-ints 1 --extra-pages 2
+
+APP_INFO=$(${gcmd} app info --app-id $APPID 2>&1)
+EXPECT="Max global integers: 1"
+if [[ $APP_INFO != *"${EXPECT}"* ]]; then
+ date "+${scriptname} FAIL wrong shrunken schema %Y%m%d_%H%M%S"
+ false
+fi
+EXPECT="Extra program pages: 2"
+if [[ $APP_INFO != *"${EXPECT}"* ]]; then
+ date "+${scriptname} FAIL wrong program pages schema %Y%m%d_%H%M%S"
+ false
+fi
diff --git a/test/scripts/e2e_subs/asset-misc.sh b/test/scripts/e2e_subs/asset-misc.sh
index 58d27fbb0d..bb944578c6 100755
--- a/test/scripts/e2e_subs/asset-misc.sh
+++ b/test/scripts/e2e_subs/asset-misc.sh
@@ -113,7 +113,7 @@ else
fi
# case 3b: Reserve address opts into the the asset, and gets asset info successfully.
-${gcmd} asset optin --creator "${ACCOUNT}" --asset dma --account ${ACCOUNTC}
+${gcmd} asset optin --creator "${ACCOUNT}" --unitname dma --account ${ACCOUNTC}
DIFF_MANAGER_ASSET_ID=$(${gcmd} asset info --creator $ACCOUNT --unitname dma|grep 'Asset ID'|awk '{ print $3 }')
DMA_MANAGER_ADDRESS=$(${gcmd} asset info --assetid ${DIFF_MANAGER_ASSET_ID} |grep 'Manager address'|awk '{ print $3 }')
diff --git a/test/scripts/e2e_subs/assets-app-b.sh b/test/scripts/e2e_subs/assets-app-b.sh
deleted file mode 100755
index 168a35c911..0000000000
--- a/test/scripts/e2e_subs/assets-app-b.sh
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/env bash
-# TIMEOUT=300
-#
-# assets-app.sh and assets-app-b.sh both test the same TEAL app script, but in two separate parallelizeable chunks
-
-filename=$(basename "$0")
-scriptname="${filename%.*}"
-date "+${scriptname} start %Y%m%d_%H%M%S"
-
-set -ex
-set -o pipefail
-export SHELLOPTS
-
-WALLET=$1
-gcmd="goal -w ${WALLET}"
-
-# Directory of helper TEAL programs
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/tealprogs"
-
-CREATOR=$(${gcmd} account list|awk '{ print $3 }')
-ALICE=$(${gcmd} account new|awk '{ print $6 }')
-BOB=$(${gcmd} account new|awk '{ print $6 }')
-MANAGER=$(${gcmd} account new|awk '{ print $6 }')
-
-${gcmd} clerk send -a 100000000 -f ${CREATOR} -t ${ALICE} &
-WA=$!
-${gcmd} clerk send -a 100000000 -f ${CREATOR} -t ${BOB} &
-WB=$!
-${gcmd} clerk send -a 100000000 -f ${CREATOR} -t ${MANAGER} &
-WC=$!
-wait $WA
-wait $WB
-wait $WC
-
-SUPPLY=10000000
-XFER1=1000
-XFER2=42
-XFER3=99999
-XFER4=11
-
-APP_CREATED_STR='Created app with app index'
-ERR_APP_CL_STR='only ClearState is supported for an application'
-ERR_APP_NE_STR='application does not exist'
-ERR_APP_OI_STR1='has not opted in to application'
-ERR_APP_OI_STR2='not opted in to app'
-ERR_APP_OI_STR3='is not currently opted in'
-ERR_APP_REJ_STR1='transaction rejected by ApprovalProgram'
-ERR_APP_REJ_STR2='err opcode executed'
-ERR_APP_REJ_STR3='- would result negative'
-
-### Reconfiguration, default-frozen, and clawback
-
-date "+$scriptname wat4 %Y%m%d_%H%M%S"
-
-# create frozen
-APP_ID=$(${gcmd} app interact execute --header ${DIR}/asa.json --from $CREATOR --approval-prog ${DIR}/asa_approve.teal --clear-prog ${DIR}/asa_clear.teal create --manager $MANAGER --reserve $CREATOR --freezer $MANAGER --clawback $MANAGER --supply $SUPPLY --default-frozen 1 | grep "$APP_CREATED_STR" | cut -d ' ' -f 6)
-
-qcmd="${gcmd} app interact query --header ${DIR}/asa.json --app-id $APP_ID"
-xcmd="${gcmd} app interact execute --header ${DIR}/asa.json --app-id $APP_ID"
-
-function assertContains {
- if [[ $1 != *"$2"* ]]; then
- echo "$1" does not contain "$2"
- date "+$scriptname FAIL $3 %Y%m%d_%H%M%S"
- false
- fi
-}
-
-# destroy bad manager F
-RES=$(${xcmd} --from $CREATOR destroy 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "non-manager should not be able to delete asset"
-
-# optin alice
-${xcmd} --from $ALICE opt-in
-
-# xfer1 F
-RES=$(${xcmd} --from $CREATOR transfer --receiver $ALICE --amount $XFER1 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR2" "frozen account should not be able to receive"
-
-# bad unfreeze F
-RES=$(${xcmd} --from $ALICE freeze --frozen 0 --target $ALICE 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "non-freezer should not be able to unfreeze account"
-
-# set freezer alice
-${xcmd} --from $MANAGER reconfigure --manager $MANAGER --reserve $CREATOR --freezer $ALICE --clawback $MANAGER
-
-# unfreeze
-${xcmd} --from $ALICE freeze --frozen 0 --target $ALICE
-
-# xfer1
-${xcmd} --from $CREATOR transfer --receiver $ALICE --amount $XFER1
-
-# freeze
-${xcmd} --from $ALICE freeze --frozen 1 --target $ALICE
-
-# xfer1 F
-RES=$(${xcmd} --from $CREATOR transfer --receiver $ALICE --amount $XFER1 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR2" "re-frozen account should not be able to receive"
-
-date "+$scriptname wat6 %Y%m%d_%H%M%S"
-
-# closeout F
-RES=$(${xcmd} --from $ALICE close-out --close-to $CREATOR 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR2" "frozen account should not be able to closeout w/o clear"
-
-# clear alice
-${xcmd} --from $ALICE clear
-
-# optin bob
-${xcmd} --from $BOB opt-in
-
-# clawback transfer
-${xcmd} --from $MANAGER clawback --sender $CREATOR --receiver $BOB --amount $XFER1
-
-# destroy F
-RES=$(${xcmd} --from $MANAGER destroy 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "should not be able to delete asset while outstanding holdings exist"
-
-# clawback
-${xcmd} --from $MANAGER clawback --sender $BOB --receiver $CREATOR --amount $XFER1
-
-# destroy
-${xcmd} --from $MANAGER destroy
-
-# clear bob
-${xcmd} --from $BOB clear
-
-date "+$scriptname OK %Y%m%d_%H%M%S"
diff --git a/test/scripts/e2e_subs/assets-app.sh b/test/scripts/e2e_subs/assets-app.sh
deleted file mode 100755
index 4c25cd663d..0000000000
--- a/test/scripts/e2e_subs/assets-app.sh
+++ /dev/null
@@ -1,194 +0,0 @@
-#!/usr/bin/env bash
-# TIMEOUT=300
-#
-# assets-app.sh and assets-app-b.sh both test the same TEAL app script, but in two separate parallelizeable chunks
-
-filename=$(basename "$0")
-scriptname="${filename%.*}"
-date "+${scriptname} start %Y%m%d_%H%M%S"
-
-set -ex
-set -o pipefail
-export SHELLOPTS
-
-WALLET=$1
-gcmd="goal -w ${WALLET}"
-
-# Directory of helper TEAL programs
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/tealprogs"
-
-CREATOR=$(${gcmd} account list|awk '{ print $3 }')
-ALICE=$(${gcmd} account new|awk '{ print $6 }')
-BOB=$(${gcmd} account new|awk '{ print $6 }')
-MANAGER=$(${gcmd} account new|awk '{ print $6 }')
-
-${gcmd} clerk send -a 100000000 -f ${CREATOR} -t ${ALICE} &
-WA=$!
-${gcmd} clerk send -a 100000000 -f ${CREATOR} -t ${BOB} &
-WB=$!
-${gcmd} clerk send -a 100000000 -f ${CREATOR} -t ${MANAGER} &
-WC=$!
-wait $WA
-wait $WB
-wait $WC
-
-SUPPLY=10000000
-XFER1=1000
-XFER2=42
-XFER3=99999
-XFER4=11
-
-APP_CREATED_STR='Created app with app index'
-ERR_APP_CL_STR='only ClearState is supported for an application'
-ERR_APP_NE_STR='application does not exist'
-ERR_APP_OI_STR1='has not opted in to application'
-ERR_APP_OI_STR2='not opted in to app'
-ERR_APP_OI_STR3='is not currently opted in'
-ERR_APP_REJ_STR1='transaction rejected by ApprovalProgram'
-ERR_APP_REJ_STR2='err opcode executed'
-ERR_APP_REJ_STR3='- would result negative'
-
-### Basic reading, creation, deletion, transfers, and freezing
-
-# create
-APP_ID=$(${gcmd} app interact execute --header ${DIR}/asa.json --from $CREATOR --approval-prog ${DIR}/asa_approve.teal --clear-prog ${DIR}/asa_clear.teal create --manager $CREATOR --reserve $CREATOR --freezer $CREATOR --clawback $CREATOR --supply $SUPPLY | grep "$APP_CREATED_STR" | cut -d ' ' -f 6)
-
-qcmd="${gcmd} app interact query --header ${DIR}/asa.json --app-id $APP_ID"
-xcmd="${gcmd} app interact execute --header ${DIR}/asa.json --app-id $APP_ID"
-
-date "+$scriptname created %Y%m%d_%H%M%S"
-
-function assertContains {
- if [[ $1 != *"$2"* ]]; then
- echo "$1" does not contain "$2"
- date "+$scriptname FAIL $3 %Y%m%d_%H%M%S"
- false
- fi
-}
-
-# read global
-RES=$(${qcmd} total-supply)
-if [[ $RES != $SUPPLY ]]; then
- date "+$scriptname FAIL expected supply to be set to $SUPPLY %Y%m%d_%H%M%S"
- false
-fi
-
-RES=$(${qcmd} creator-balance)
-if [[ $RES != $SUPPLY ]]; then
- date "+$scriptname FAIL expected creator to begin with $SUPPLY %Y%m%d_%H%M%S"
- false
-fi
-
-# read alice F
-RES=$(${qcmd} --from $ALICE balance 2>&1 || true)
-assertContains "$RES" "$ERR_APP_OI_STR1" "expected read of non-opted in account to fail"
-
-# optin alice
-${xcmd} --from $ALICE opt-in
-
-# read alice
-RES=$(${qcmd} --from $ALICE balance)
-if [[ $RES != '0' ]]; then
- date "+$scriptname FAIL expected opted-in account to start with no balance %Y%m%d_%H%M%S"
- false
-fi
-
-RES=$(${qcmd} --from $ALICE frozen)
-if [[ $RES != '0' ]]; then
- date "+$scriptname FAIL expected opted-in account to be non-frozen %Y%m%d_%H%M%S"
- false
-fi
-
-date "+$scriptname wat1 %Y%m%d_%H%M%S"
-
-# xfer0 creator -> bob F
-RES=$(${xcmd} --from $CREATOR transfer --receiver $BOB --amount $XFER1 2>&1 || true)
-assertContains "$RES" "$ERR_APP_OI_STR2" "transfer succeeded on account which has not opted in"
-
-# xfer1 (2) creator -> alice
-${xcmd} --from $CREATOR transfer --receiver $ALICE --amount $XFER1 &
-WA=$!
-${xcmd} --from $CREATOR transfer --receiver $ALICE --amount $XFER1 &
-WB=$!
-wait $WA
-wait $WB
-
-# read alice
-RES=$(${qcmd} --from $ALICE balance)
-if [[ $RES != $(( $XFER1 + $XFER1 )) ]]; then
- date "+$scriptname FAIL transfer recipient does not have $XFER1 %Y%m%d_%H%M%S"
- false
-fi
-
-# destroy F
-RES=$(${xcmd} --from $CREATOR destroy 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "should not be able to destroy asset while outstanding holdings exist"
-
-# freeze
-${xcmd} --from $CREATOR freeze --frozen 1 --target $ALICE
-
-# xfer2 alice -> creator F
-RES=$(${xcmd} --from $ALICE transfer --receiver $CREATOR --amount $XFER2 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR2" "frozen account should not be able to send"
-
-date "+$scriptname wat2 %Y%m%d_%H%M%S"
-
-# xfer1 creator -> alice F
-RES=$(${xcmd} --from $CREATOR transfer --receiver $ALICE --amount $XFER1 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR2" "frozen account should not be able to receive"
-
-# unfreeze
-${xcmd} --from $CREATOR freeze --frozen 0 --target $ALICE
-
-# xfer1 creator -> alice
-${xcmd} --from $CREATOR transfer --receiver $ALICE --amount $XFER1
-
-# xfer5 alice |-> alice F
-RES=$(${xcmd} --from $ALICE close-out --close-to $ALICE 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "closing to self not permitted"
-
-# optin bob
-${xcmd} --from $BOB opt-in
-
-# xfer3 alice -> bob overdraw F
-RES=$(${xcmd} --from $ALICE transfer --receiver $BOB --amount $XFER3 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR3" "overdraws are not permitted"
-
-# xfer4 alice -> creator |-> bob
-${xcmd} --from $ALICE close-out --receiver $CREATOR --amount $XFER4 --close-to $BOB
-
-# xfer5 bob |-> alice F
-RES=$(${xcmd} --from $BOB close-out --close-to $ALICE 2>&1 || true)
-assertContains "$RES" "$ERR_APP_OI_STR2" "transfer succeeded on account which has closed out"
-
-# optin alice
-${xcmd} --from $ALICE opt-in
-
-# xfer5 bob |-> alice
-${xcmd} --from $BOB close-out --close-to $ALICE
-
-# clear alice
-${xcmd} --from $ALICE clear
-
-# clear alice F
-RES=$(${xcmd} --from $ALICE clear 2>&1 || true)
-assertContains "$RES" "$ERR_APP_OI_STR3" "should not be able to clear asset holding twice"
-
-# destroy
-${xcmd} --from $CREATOR destroy
-
-date "+$scriptname wat3 %Y%m%d_%H%M%S"
-
-# destroy F
-RES=$(${xcmd} --from $CREATOR destroy 2>&1 || true)
-assertContains "$RES" "$ERR_APP_CL_STR" "second deletion of application should fail"
-
-# optin alice F
-RES=$(${xcmd} --from $ALICE opt-in 2>&1 || true)
-assertContains "$RES" "$ERR_APP_CL_STR" "optin of deleted application should fail"
-
-# read global F
-RES=$(${qcmd} total-supply 2>&1 || true)
-assertContains "$RES" "$ERR_APP_NE_STR" "read global of deleted application should fail"
-
-date "+$scriptname OK %Y%m%d_%H%M%S"
diff --git a/test/scripts/e2e_subs/e2e-app-delete-clear.sh b/test/scripts/e2e_subs/e2e-app-delete-clear.sh
index 2795f869fc..27a60e437c 100755
--- a/test/scripts/e2e_subs/e2e-app-delete-clear.sh
+++ b/test/scripts/e2e_subs/e2e-app-delete-clear.sh
@@ -1,6 +1,8 @@
#!/bin/bash
-date '+app-delete-clear-test start %Y%m%d_%H%M%S'
+filename=$(basename "$0")
+scriptname="${filename%.*}"
+date "+${scriptname} start %Y%m%d_%H%M%S"
set -e
set -x
@@ -25,7 +27,7 @@ APPID=$(${gcmd} app create --creator ${ACCOUNT} --on-completion "DeleteApplicat
APPID_CHECK=$(${gcmd} app info --app-id $APPID 2>&1 || true)
EXPERROR="application does not exist"
if [[ $APPID_CHECK != *"${EXPERROR}"* ]]; then
- date '+app-create-delete-test FAIL the deleted application should not exist %Y%m%d_%H%M%S'
+ date '+${scriptname} FAIL the deleted application should not exist %Y%m%d_%H%M%S'
false
fi
@@ -34,7 +36,6 @@ RES=$(${gcmd} app create --creator ${ACCOUNT} --on-completion "ClearState" --ap
EXPERROR1='cannot clear state'
EXPERROR2='is not currently opted in'
if [[ $RES != *"${EXPERROR1}"*"${EXPERROR2}"* ]]; then
- date '+app-create-clear FAIL should fail to create app with on-completion ClearState %Y%m%d_%H%M%S'
+ date '+${scriptname} FAIL should fail to create app with on-completion ClearState %Y%m%d_%H%M%S'
false
fi
-
diff --git a/test/scripts/e2e_subs/hdr-access-logicsig.sh b/test/scripts/e2e_subs/hdr-access-logicsig.sh
index 103695c99a..2d6ca42a5a 100755
--- a/test/scripts/e2e_subs/hdr-access-logicsig.sh
+++ b/test/scripts/e2e_subs/hdr-access-logicsig.sh
@@ -41,8 +41,8 @@ int 1
>
assert
-int 6
-<
+int 25 // consensus allows MaxTimestampIncrement=25 sec between blocks
+<=
EOF
${gcmd} clerk compile -o ${TEMPDIR}/hdr.lsig -s -a ${ACCOUNT} ${TEMPDIR}/hdr.teal
diff --git a/test/scripts/e2e_subs/sectok-app.sh b/test/scripts/e2e_subs/sectok-app.sh
deleted file mode 100755
index 8e87c57c3c..0000000000
--- a/test/scripts/e2e_subs/sectok-app.sh
+++ /dev/null
@@ -1,217 +0,0 @@
-#!/usr/bin/env bash
-# TIMEOUT=380
-
-filename=$(basename "$0")
-scriptname="${filename%.*}"
-date "+${scriptname} start %Y%m%d_%H%M%S"
-
-set -ex
-set -o pipefail
-export SHELLOPTS
-
-WALLET=$1
-gcmd="goal -w ${WALLET}"
-
-# Directory of helper TEAL programs
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )/tealprogs"
-
-CREATOR=$(${gcmd} account list|awk '{ print $3 }')
-ALICE=$(${gcmd} account new|awk '{ print $6 }')
-BOB=$(${gcmd} account new|awk '{ print $6 }')
-CAROL=$(${gcmd} account new|awk '{ print $6 }')
-# MANAGER=$(${gcmd} account new|awk '{ print $6 }')
-
-${gcmd} clerk send -a 100000000 -f ${CREATOR} -t ${ALICE} &
-WA=$!
-${gcmd} clerk send -a 100000000 -f ${CREATOR} -t ${BOB} &
-WB=$!
-${gcmd} clerk send -a 100000000 -f ${CREATOR} -t ${CAROL} &
-WC=$!
-wait $WA
-wait $WB
-wait $WC
-# ${gcmd} clerk send -a 100000000 -f ${CREATOR} -t ${MANAGER}
-
-SUPPLY=10000000
-XFER1=1000
-XFER2=42
-XFER3=99999
-XFER4=11
-VERY_LATE=9999999999
-
-APP_CREATED_STR='Created app with app index'
-ERR_APP_CL_STR='only ClearState is supported for an application'
-ERR_APP_NE_STR='application does not exist'
-ERR_APP_OI_STR1='has not opted in to application'
-ERR_APP_OI_STR2='not opted in to app'
-ERR_APP_OI_STR3='is not currently opted in'
-ERR_APP_REJ_STR1='transaction rejected by ApprovalProgram'
-ERR_APP_REJ_STR2='err opcode executed'
-ERR_APP_REJ_STR3='- would result negative'
-
-# create
-APP_ID=$(${gcmd} app interact execute --header ${DIR}/sectok.json --from $CREATOR --approval-prog ${DIR}/sectok_approve.teal --clear-prog ${DIR}/sectok_clear.teal create --token-params '{}' --total-supply $SUPPLY | grep "$APP_CREATED_STR" | cut -d ' ' -f 6)
-
-xcmd="${gcmd} app interact execute --header ${DIR}/sectok.json --app-id ${APP_ID}"
-qcmd="${gcmd} app interact query --header ${DIR}/sectok.json --app-id ${APP_ID}"
-
-# read global
-RES=$(${qcmd} total-supply)
-if [[ $RES != $SUPPLY ]]; then
- date "+$scriptname FAIL expected supply to be set to $SUPPLY %Y%m%d_%H%M%S"
- false
-fi
-
-RES=$(${qcmd} reserve-supply)
-if [[ $RES != $SUPPLY ]]; then
- date "+$scriptname FAIL expected reserve to begin with $SUPPLY %Y%m%d_%H%M%S"
- false
-fi
-
-function assertContains {
- if [[ $1 != *"$2"* ]]; then
- echo "$1" does not contain "'$2'"
- date "+$scriptname FAIL $3 %Y%m%d_%H%M%S"
- false
- fi
-}
-
-# read alice F
-RES=$(${qcmd} --from $ALICE balance 2>&1 || true)
-assertContains "$RES" "$ERR_APP_OI_STR1" "expected read of non-opted in account to fail"
-
-# optin alice, bob, carol
-${xcmd} --from $ALICE opt-in &
-WA=$!
-${xcmd} --from $BOB opt-in &
-WB=$!
-${xcmd} --from $CAROL opt-in &
-WC=$!
-wait $WA
-wait $WB
-wait $WC
-
-RES=$(${qcmd} --from $ALICE transfer-group)
-if [[ $RES != '0' ]]; then
- date "+$scriptname FAIL expected opt-in account to start with transfer group 0 %Y%m%d_%H%M%S"
- false
-fi
-
-RES=$(${qcmd} --from $ALICE balance)
-if [[ $RES != '0' ]]; then
- date "+$scriptname FAIL expected opt-in account to start with 0 balance %Y%m%d_%H%M%S"
- false
-fi
-
-# assorted transfer-admin restrictions
-RES=$(${xcmd} --from $CREATOR set-transfer-group --target $ALICE --transfer-group 1 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "contract-admins cannot set transfer groups"
-
-RES=$(${xcmd} --from $CREATOR set-lock-until --target $ALICE --lock-until 1 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "contract-admins cannot set lock-until"
-
-RES=$(${xcmd} --from $CREATOR set-max-balance --target $ALICE --max-balance $SUPPLY 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "contract-admins cannot set max balance"
-
-RES=$(${xcmd} --from $ALICE set-transfer-group --target $ALICE --transfer-group 1 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "non-admins cannot set transfer groups"
-
-RES=$(${xcmd} --from $ALICE set-lock-until --target $ALICE --lock-until 1 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "non-admins cannot set lock-until"
-
-RES=$(${xcmd} --from $ALICE set-max-balance --target $ALICE --max-balance $SUPPLY 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "non-admins cannot set max balance"
-
-# setting transfer-admin
-RES=$(${xcmd} --from $ALICE freeze --target $ALICE --frozen 1 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "non-admins cannot freeze accounts"
-
-RES=$(${xcmd} --from $ALICE set-transfer-admin --target $ALICE --status 1 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR2" "non-admins cannot set transfer admin status"
-
-${xcmd} --from $CREATOR set-transfer-admin --target $ALICE --status 1
-${xcmd} --from $ALICE freeze --target $ALICE --frozen 1
-${xcmd} --from $ALICE set-max-balance --target $ALICE --max-balance $SUPPLY
-${xcmd} --from $CREATOR set-transfer-admin --target $ALICE --status 0
-
-RES=$(${xcmd} --from $ALICE freeze --target $ALICE --frozen 0 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR1" "non-admins (revoked) cannot freeze accounts"
-
-# setting contract-admin
-${xcmd} --from $CREATOR set-contract-admin --target $BOB --status 1
-${xcmd} --from $BOB set-transfer-admin --target $ALICE --status 1
-${xcmd} --from $CREATOR set-contract-admin --target $BOB --status 0
-
-RES=$(${xcmd} --from $BOB set-transfer-admin --target $ALICE --status 0 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR2" "non-admins cannot set transfer admin status"
-
-RES=$(${xcmd} --from $BOB set-contract-admin --target $BOB --status 1 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR2" "non-admins cannot set own contract admin status"
-
-# minting/burning
-${xcmd} --from $CREATOR mint --target $ALICE --amount $XFER1 &
-WA=$!
-${xcmd} --from $CREATOR mint --target $ALICE --amount $XFER1 &
-WB=$!
-wait $WA
-wait $WB
-
-RES=$(${qcmd} --from $ALICE balance)
-if [[ $RES != $(( $XFER1 + $XFER1 )) ]]; then
- date "+$scriptname FAIL minting twice did not produce the correct balance %Y%m%d_%H%M%S"
- false
-fi
-
-RES=$(${qcmd} reserve-supply)
-if [[ $RES != $(( $SUPPLY - $XFER1 - $XFER1 )) ]]; then
- date "+$scriptname FAIL minting twice did not produce the correct reserve balance %Y%m%d_%H%M%S"
- false
-fi
-
-${xcmd} --from $CREATOR burn --target $ALICE --amount $XFER1
-
-RES=$(${qcmd} --from $ALICE balance)
-if [[ $RES != $XFER1 ]]; then
- date "+$scriptname FAIL minting and then burning did not produce the correct balance %Y%m%d_%H%M%S"
- false
-fi
-
-${xcmd} --from $CREATOR burn --target $ALICE --amount $XFER1
-
-# allowing transfers and transferring
-${xcmd} --from $CREATOR mint --target $CAROL --amount $XFER1
-
-RES=$(${xcmd} --from $CAROL transfer --receiver $BOB --amount $XFER2 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR3" "new account should not be able to spend"
-
-${xcmd} --from $ALICE set-max-balance --target $CAROL --max-balance $SUPPLY &
-WA=$!
-${xcmd} --from $ALICE set-max-balance --target $BOB --max-balance $SUPPLY &
-WB=$!
-wait $WA
-wait $WB
-
-${xcmd} --from $ALICE set-lock-until --target $CAROL --lock-until 1 &
-WA=$!
-${xcmd} --from $ALICE set-lock-until --target $BOB --lock-until 1 &
-WB=$!
-wait $WA
-wait $WB
-
-${xcmd} --from $ALICE set-transfer-group --target $CAROL --transfer-group 1 &
-WA=$!
-${xcmd} --from $ALICE set-transfer-group --target $BOB --transfer-group 2 &
-WB=$!
-wait $WA
-wait $WB
-
-RES=$(${xcmd} --from $CAROL transfer --receiver $BOB --amount $XFER2 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR3" "no transfers allowed without transfer rules"
-
-${xcmd} --from $ALICE set-transfer-rule --send-group 1 --receive-group 2 --lock-until 1
-${xcmd} --from $CAROL transfer --receiver $BOB --amount $XFER2
-
-RES=$(${xcmd} --from $BOB transfer --receiver $CAROL --amount $XFER2 2>&1 || true)
-assertContains "$RES" "$ERR_APP_REJ_STR3" "reverse transfer (by group) should fail"
-
-date "+$scriptname OK %Y%m%d_%H%M%S"
diff --git a/test/scripts/e2e_subs/tealprogs/asa.json b/test/scripts/e2e_subs/tealprogs/asa.json
deleted file mode 100644
index 3a4b46e530..0000000000
--- a/test/scripts/e2e_subs/tealprogs/asa.json
+++ /dev/null
@@ -1,230 +0,0 @@
-{
- "execute" : {
- "create" : {
- "create" : true,
- "help" : "Create a new asset.",
- "args" : [
- {
- "name" : "manager",
- "kind" : "address",
- "help" : "The initial asset manager, if nonzero."
- },
- {
- "name" : "reserve",
- "kind" : "address",
- "help" : "The initial reserve address, if nonzero."
- },
- {
- "name" : "freezer",
- "kind" : "address",
- "help" : "The initial freezer address, if nonzero."
- },
- {
- "name" : "clawback",
- "kind" : "address",
- "help" : "The initial clawback address, if nonzero."
- },
- {
- "name" : "supply",
- "kind" : "integer",
- "help" : "The total asset supply."
- },
- {
- "name" : "default-frozen",
- "kind" : "integer",
- "help" : "The default frozen status for new accounts."
- }
- ]
- },
- "destroy" : {
- "on-completion" : "DeleteApplication",
- "help" : "Destroy an asset. The asset creator must hold the entire supply. This transaction must be sent by the asset creator."
- },
- "reconfigure" : {
- "help" : "Reconfigure an asset's managers. A manager can be set only if it is currently not the zero address. This transaction must be set by the asset's manager.",
- "args" : [
- {
- "name" : "manager",
- "kind" : "address",
- "help" : "The new asset manager (or zero to disable permanently)."
- },
- {
- "name" : "reserve",
- "kind" : "address",
- "help" : "The new reserve address (or zero to disable permanently)."
- },
- {
- "name" : "freezer",
- "kind" : "address",
- "help" : "The new freezer address (or zero to disable permanently)."
- },
- {
- "name" : "clawback",
- "kind" : "address",
- "help" : "The new clawback address (or zero to disable permanently)."
- },
- {
- "name" : "ignored0",
- "kind" : "integer",
- "pseudo" : true
- },
- {
- "name" : "ignored1",
- "kind" : "integer",
- "pseudo" : true
- }
- ]
- },
- "opt-in" : {
- "on-completion" : "OptIn",
- "help" : "Opt into an asset. The asset creator is always opted in."
- },
- "freeze" : {
- "args" : [
- {
- "name" : "frozen",
- "kind" : "integer",
- "help" : "The new frozen value of the account."
- }
- ],
- "accounts" : [
- {
- "name" : "target",
- "help" : "The target account whose frozen value to set."
- }
- ],
- "help" : "Set the frozen value of an account. This transaction must be sent by the asset freezer."
- },
- "transfer" : {
- "args" : [
- {
- "name" : "amount",
- "kind" : "integer",
- "help" : "The amount of the asset to transfer."
- }
- ],
- "accounts" : [
- {
- "name" : "receiver",
- "help" : "The account receiving the assets."
- },
- {
- "name" : "ignored",
- "pseudo" : true
- }
- ],
- "help" : "Transfer an asset to a receiver."
- },
- "clawback" : {
- "args" : [
- {
- "name" : "amount",
- "kind" : "integer",
- "help" : "The amount of the asset to transfer."
- },
- {
- "name" : "ignored",
- "kind" : "integer",
- "pseudo" : true
- }
- ],
- "accounts" : [
- {
- "name" : "sender",
- "help" : "The account sending the assets."
- },
- {
- "name" : "receiver",
- "help" : "The account receiving the assets."
- }
- ],
- "help" : "Force the transfer of an asset from some sender to some receiver. This transaction must be sent by the asset clawback account."
- },
- "close-out" : {
- "on-completion" : "CloseOut",
- "args" : [
- {
- "name" : "amount",
- "kind" : "integer",
- "help" : "An optional amount of the asset to transfer to a receiver before closing out."
- }
- ],
- "accounts" : [
- {
- "name" : "receiver",
- "help" : "An optional account to receive assets before closing out."
- },
- {
- "name" : "close-to",
- "help" : "The address receiving all remaining assets."
- }
- ],
- "help" : "Close out all assets to an account, with an optional transfer beforehand."
- },
- "clear" : {
- "on-completion" : "ClearState",
- "help" : "Clear out all assets from the account."
- }
- },
- "query" : {
- "global" : {
- "creator" : {
- "key" : "cr",
- "kind" : "address",
- "help" : "The asset creator created the asset. The asset creator is always opted in to the asset: its balance and freeze status are stored in global storage at \"creator-balance\" and \"creator-frozen\", respectively. This value is constant."
- },
- "manager" : {
- "key" : "mn",
- "kind" : "address",
- "help" : "The asset manager can set the manager, reserve, freezer, and clawback addresses if they are nonzero."
- },
- "reserve" : {
- "key" : "rv",
- "kind" : "address",
- "help" : "The asset reserve for the asset."
- },
- "freezer" : {
- "key" : "fr",
- "kind" : "address",
- "help" : "The asset freezer can execute the \"freeze\" procedure on accounts."
- },
- "clawback" : {
- "key" : "cl",
- "kind" : "address",
- "help" : "The asset clawback address can execute the \"clawback\" procedure on accounts."
- },
- "total-supply" : {
- "key" : "tt",
- "kind" : "integer",
- "help" : "The total supply of the asset when initially created. This value is constant."
- },
- "default-frozen" : {
- "key" : "df",
- "kind" : "integer",
- "help" : "The default frozen status of any created new account (excepting the creator, whose frozen status is initialized to 0). A value of 1 signifies that the account is frozen and cannot make ordinary transactions. This value is constant."
- },
- "creator-balance" : {
- "key" : "bl",
- "kind" : "integer",
- "help" : "The balance of the \"creator\"."
- },
- "creator-frozen" : {
- "key" : "fz",
- "kind" : "integer",
- "help" : "The frozen status of the \"creator\". This value is always initialized to 0."
- }
- },
- "local" : {
- "balance" : {
- "key" : "bl",
- "kind" : "integer",
- "help" : "The balance of the account."
- },
- "frozen" : {
- "key" : "fz",
- "kind" : "integer",
- "help" : "The frozen status of the account. This value is initialized to \"default-frozen\" when the account is first created. This value may be modified via the \"freeze\" procedure."
- }
- }
- }
-}
diff --git a/test/scripts/e2e_subs/tealprogs/asa_approve.teal b/test/scripts/e2e_subs/tealprogs/asa_approve.teal
deleted file mode 100644
index 710405f797..0000000000
--- a/test/scripts/e2e_subs/tealprogs/asa_approve.teal
+++ /dev/null
@@ -1,532 +0,0 @@
-#pragma version 2
-txn NumAppArgs
-int 6
-==
-bnz if0
-txn ApplicationID
-int 0
-==
-!
-bnz assert2
-err
-assert2:
-txn NumAccounts
-int 0
-==
-bnz cond4
-txn NumAccounts
-int 1
-==
-bnz cond5
-txn NumAppArgs
-int 2
-==
-bnz cond6
-// transfer asset
-txna ApplicationArgs 0
-btoi
-store 1
-load 1
-int 0
-==
-bnz unless7
-// cannot modify frozen asset
-txn Sender
-byte base64 Y3I=
-app_global_get
-==
-bnz if9
-int 0
-byte base64 Zno=
-app_local_get
-int 1
-==
-int 1
-bnz if_end10
-if9:
-byte base64 Zno=
-app_global_get
-int 1
-==
-if_end10:
-!
-bnz assert8
-err
-assert8:
-txn Sender
-byte base64 Y3I=
-app_global_get
-==
-bnz if11
-int 0
-byte base64 Ymw=
-int 0
-byte base64 Ymw=
-app_local_get
-load 1
--
-app_local_put
-int 1
-bnz if_end12
-if11:
-byte base64 Ymw=
-byte base64 Ymw=
-app_global_get
-load 1
--
-app_global_put
-if_end12:
-unless7:
-load 1
-int 0
-==
-bnz unless13
-// cannot modify frozen asset
-txna Accounts 1
-byte base64 Y3I=
-app_global_get
-==
-bnz if15
-int 1
-byte base64 Zno=
-app_local_get
-int 1
-==
-int 1
-bnz if_end16
-if15:
-byte base64 Zno=
-app_global_get
-int 1
-==
-if_end16:
-!
-bnz assert14
-err
-assert14:
-txna Accounts 1
-byte base64 Y3I=
-app_global_get
-==
-bnz if17
-int 1
-byte base64 Ymw=
-int 1
-byte base64 Ymw=
-app_local_get
-load 1
-+
-app_local_put
-int 1
-bnz if_end18
-if17:
-byte base64 Ymw=
-byte base64 Ymw=
-app_global_get
-load 1
-+
-app_global_put
-if_end18:
-unless13:
-txna Accounts 2
-global ZeroAddress
-==
-bnz unless19
-int 0
-byte base64 Ymw=
-app_local_get
-store 2
-load 2
-int 0
-==
-bnz unless20
-// cannot modify frozen asset
-txn Sender
-byte base64 Y3I=
-app_global_get
-==
-bnz if22
-int 0
-byte base64 Zno=
-app_local_get
-int 1
-==
-int 1
-bnz if_end23
-if22:
-byte base64 Zno=
-app_global_get
-int 1
-==
-if_end23:
-!
-bnz assert21
-err
-assert21:
-txn Sender
-byte base64 Y3I=
-app_global_get
-==
-bnz if24
-int 0
-byte base64 Ymw=
-int 0
-byte base64 Ymw=
-app_local_get
-load 2
--
-app_local_put
-int 1
-bnz if_end25
-if24:
-byte base64 Ymw=
-byte base64 Ymw=
-app_global_get
-load 2
--
-app_global_put
-if_end25:
-unless20:
-load 2
-int 0
-==
-bnz unless26
-// cannot modify frozen asset
-txna Accounts 2
-byte base64 Y3I=
-app_global_get
-==
-bnz if28
-int 2
-byte base64 Zno=
-app_local_get
-int 1
-==
-int 1
-bnz if_end29
-if28:
-byte base64 Zno=
-app_global_get
-int 1
-==
-if_end29:
-!
-bnz assert27
-err
-assert27:
-txna Accounts 2
-byte base64 Y3I=
-app_global_get
-==
-bnz if30
-int 2
-byte base64 Ymw=
-int 2
-byte base64 Ymw=
-app_local_get
-load 2
-+
-app_local_put
-int 1
-bnz if_end31
-if30:
-byte base64 Ymw=
-byte base64 Ymw=
-app_global_get
-load 2
-+
-app_global_put
-if_end31:
-unless26:
-unless19:
-txn NumAppArgs
-int 1
-==
-txn NumAccounts
-int 2
-==
-&&
-txn OnCompletion
-int 0
-==
-bnz if32
-txn OnCompletion
-int 2
-==
-int 0
-byte base64 Ymw=
-app_local_get
-int 0
-==
-&&
-txna Accounts 2
-global ZeroAddress
-==
-!
-&&
-int 1
-bnz if_end33
-if32:
-txna Accounts 2
-global ZeroAddress
-==
-if_end33:
-&&
-int 1
-bnz cond_end3
-cond6:
-// clawback asset
-txna ApplicationArgs 0
-btoi
-store 0
-txna Accounts 1
-byte base64 Y3I=
-app_global_get
-==
-bnz if34
-int 1
-byte base64 Ymw=
-int 1
-byte base64 Ymw=
-app_local_get
-load 0
--
-app_local_put
-int 1
-bnz if_end35
-if34:
-byte base64 Ymw=
-byte base64 Ymw=
-app_global_get
-load 0
--
-app_global_put
-if_end35:
-txna Accounts 2
-byte base64 Y3I=
-app_global_get
-==
-bnz if36
-int 2
-byte base64 Ymw=
-int 2
-byte base64 Ymw=
-app_local_get
-load 0
-+
-app_local_put
-int 1
-bnz if_end37
-if36:
-byte base64 Ymw=
-byte base64 Ymw=
-app_global_get
-load 0
-+
-app_global_put
-if_end37:
-txn NumAccounts
-int 2
-==
-txn OnCompletion
-int 0
-==
-&&
-txn Sender
-byte base64 Y2w=
-app_global_get
-==
-&&
-int 1
-bnz cond_end3
-cond5:
-// freeze asset holding
-txna Accounts 1
-byte base64 Y3I=
-app_global_get
-==
-bnz if38
-int 1
-byte base64 Zno=
-txna ApplicationArgs 0
-btoi
-app_local_put
-int 1
-bnz if_end39
-if38:
-byte base64 Zno=
-txna ApplicationArgs 0
-btoi
-app_global_put
-if_end39:
-txn NumAppArgs
-int 1
-==
-txn OnCompletion
-int 0
-==
-&&
-txn Sender
-byte base64 ZnI=
-app_global_get
-==
-&&
-int 1
-bnz cond_end3
-cond4:
-// asset deletion or opt-in
-txn OnCompletion
-int 1
-==
-!
-bnz when40
-// opting in to implicit zero bl
-int 0
-byte base64 Zno=
-byte base64 ZGY=
-app_global_get
-app_local_put
-when40:
-txn NumAppArgs
-int 0
-==
-txn OnCompletion
-int 5
-==
-txn Sender
-byte base64 bW4=
-app_global_get
-==
-&&
-byte base64 dHQ=
-app_global_get
-byte base64 Ymw=
-app_global_get
-==
-&&
-txn OnCompletion
-int 1
-==
-txn Sender
-byte base64 Y3I=
-app_global_get
-==
-!
-&&
-||
-&&
-cond_end3:
-int 1
-bnz if_end1
-if0:
-// asset configuration
-txn ApplicationID
-int 0
-==
-bnz if41
-txn Sender
-byte base64 bW4=
-app_global_get
-==
-txna ApplicationArgs 0
-global ZeroAddress
-==
-byte base64 bW4=
-app_global_get
-global ZeroAddress
-==
-!
-||
-&&
-txna ApplicationArgs 1
-global ZeroAddress
-==
-byte base64 cnY=
-app_global_get
-global ZeroAddress
-==
-!
-||
-&&
-txna ApplicationArgs 2
-global ZeroAddress
-==
-byte base64 ZnI=
-app_global_get
-global ZeroAddress
-==
-!
-||
-&&
-txna ApplicationArgs 3
-global ZeroAddress
-==
-byte base64 Y2w=
-app_global_get
-global ZeroAddress
-==
-!
-||
-&&
-bnz assert43
-err
-assert43:
-int 1
-bnz if_end42
-if41:
-byte base64 Y3I=
-txn Sender
-app_global_put
-byte base64 dHQ=
-txna ApplicationArgs 4
-btoi
-app_global_put
-byte base64 Ymw=
-txna ApplicationArgs 4
-btoi
-app_global_put
-byte base64 ZGY=
-txna ApplicationArgs 5
-btoi
-app_global_put
-if_end42:
-byte base64 bW4=
-txna ApplicationArgs 0
-app_global_put
-byte base64 cnY=
-txna ApplicationArgs 1
-app_global_put
-byte base64 ZnI=
-txna ApplicationArgs 2
-app_global_put
-byte base64 Y2w=
-txna ApplicationArgs 3
-app_global_put
-txn NumAccounts
-int 0
-==
-txn OnCompletion
-int 0
-==
-&&
-txna ApplicationArgs 0
-len
-int 32
-==
-&&
-txna ApplicationArgs 1
-len
-int 32
-==
-&&
-txna ApplicationArgs 2
-len
-int 32
-==
-&&
-txna ApplicationArgs 3
-len
-int 32
-==
-&&
-if_end1:
diff --git a/test/scripts/e2e_subs/tealprogs/asa_clear.teal b/test/scripts/e2e_subs/tealprogs/asa_clear.teal
deleted file mode 100644
index 999b8312cd..0000000000
--- a/test/scripts/e2e_subs/tealprogs/asa_clear.teal
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma version 2
-byte base64 Ymw=
-byte base64 Ymw=
-app_global_get
-int 0
-byte base64 Ymw=
-app_local_get
-+
-app_global_put
-int 1
diff --git a/test/scripts/e2e_subs/tealprogs/sectok.json b/test/scripts/e2e_subs/tealprogs/sectok.json
deleted file mode 100644
index ef0d74c293..0000000000
--- a/test/scripts/e2e_subs/tealprogs/sectok.json
+++ /dev/null
@@ -1,414 +0,0 @@
-{
- "query": {
- "global": {
- "lock-until-group": {
- "map": {
- "kind": "byte",
- "prefix": "0x0001"
- },
- "size": 40,
- "kind": "int",
- "help": "The first timestamp at which accounts in one group can issue transfers to accounts in another group."
- },
- "token-params": {
- "kind": "string",
- "key": "px",
- "help": "The parameters of the security token. This is a JSON object with the string \"symbol\" attribute, the string \"name\" attribute, and the integer \"decimals\" attribute."
- },
- "reserve-supply": {
- "kind": "int",
- "key": "rv",
- "help": "The supply of this security token currently sitting in reserve."
- },
- "total-supply": {
- "kind": "int",
- "key": "tt",
- "help": "The total supply of this security token when first created. This value is constant."
- },
- "paused": {
- "kind": "int",
- "key": "ps",
- "help": "Whether all trading is paused. No trading occurs unless this is zero."
- }
- },
- "local": {
- "lock-until": {
- "kind": "int",
- "key": "tl",
- "help": "The first timestamp at which this account can issue and accept transfers."
- },
- "contract-admin": {
- "kind": "int",
- "key": "cX",
- "help": "Whether this account is a contract admin. If this is one, this account may upgrade the application code, set the contract and transfer admin status of accounts, destroy the asset if the reserve holds the supply, mint and burn from the supply, pause and unpause all transfers, and freeze and unfreeze accounts. This is automatically set to one for the token creator."
- },
- "frozen": {
- "kind": "int",
- "key": "fz",
- "help": "Whether this account is frozen. This account issue and accept transfers unless this is zero."
- },
- "balance": {
- "kind": "int",
- "key": "bl",
- "help": "The number of tokens held by this account."
- },
- "transfer-admin": {
- "kind": "int",
- "key": "tX",
- "help": "Whether this account is a transfer admin. A transfer admin can set transfer rules between groups, freeze and unfreeze accounts, and set the max balance, transfer group, and timed locks for accounts."
- },
- "transfer-group": {
- "kind": "int",
- "key": "tg",
- "help": "The transfer group of this account, which affects the set of allowed transfers to and from other groups."
- },
- "max-balance": {
- "kind": "int",
- "key": "mb",
- "help": "The maximum token balance allowed for this account."
- }
- }
- },
- "execute": {
- "clear": {
- "on-completion": "ClearState",
- "accounts": [],
- "foreign": [],
- "create": false,
- "help": "Clear all tokens out of the account.",
- "args": []
- },
- "destroy": {
- "on-completion": "DeleteApplication",
- "accounts": [],
- "foreign": [],
- "create": false,
- "help": "Destroy a security token. The entire token supply must be in the reserve. This transaction must be sent by a contract admin.",
- "args": []
- },
- "set-transfer-rule": {
- "on-completion": "NoOp",
- "accounts": [],
- "foreign": [],
- "create": false,
- "help": "Create, update, or delete a transfer rule. This transaction must be sent by a transfer admin.",
- "args": [
- {
- "name": "send-group",
- "pseudo": false,
- "kind": "int",
- "help": "The sending group the rule applies to."
- },
- {
- "name": "receive-group",
- "pseudo": false,
- "kind": "int",
- "help": "The receiving group the rule applies to."
- },
- {
- "name": "lock-until",
- "pseudo": false,
- "kind": "int",
- "help": "The first timestamp at which accounts in the sending group may make transfers to accounts in the receiving group."
- }
- ]
- },
- "pause": {
- "on-completion": "NoOp",
- "accounts": [],
- "foreign": [],
- "create": false,
- "help": "Control whether all transfers are disallowed.",
- "args": [
- {
- "name": "paused",
- "pseudo": false,
- "kind": "int",
- "help": "No transfers will be allowed unless this is zero."
- }
- ]
- },
- "opt-in": {
- "on-completion": "OptIn",
- "accounts": [],
- "foreign": [],
- "create": false,
- "help": "Opt into a token. The initial transfer group of all accounts is zero.",
- "args": []
- },
- "mint": {
- "on-completion": "NoOp",
- "accounts": [
- {
- "name": "target",
- "pseudo": false,
- "help": "The account to which to mint to."
- }
- ],
- "foreign": [],
- "create": false,
- "help": "Mint funds into an account. This circumvents other restrictions on that account. This transaction must be sent by a contract admin.",
- "args": [
- {
- "name": "ignored",
- "pseudo": true,
- "kind": "string",
- "help": "",
- "default": "mn"
- },
- {
- "name": "amount",
- "pseudo": false,
- "kind": "int",
- "help": "The number of tokens to mint into the account."
- }
- ]
- },
- "set-transfer-admin": {
- "on-completion": "NoOp",
- "accounts": [
- {
- "name": "target",
- "pseudo": false,
- "help": "The account to configure."
- }
- ],
- "foreign": [],
- "create": false,
- "help": "Configure the transfer admin status of an account. This transaction must be sent by a contract admin.",
- "args": [
- {
- "name": "ignored",
- "pseudo": true,
- "kind": "string",
- "help": "",
- "default": "tX"
- },
- {
- "name": "status",
- "pseudo": false,
- "kind": "int",
- "help": "If this is 1, confer transfer admin status on the account; otherwise, revoke transfer admin status on the account."
- }
- ]
- },
- "set-contract-admin": {
- "on-completion": "NoOp",
- "accounts": [
- {
- "name": "target",
- "pseudo": false,
- "help": "The account to configure."
- }
- ],
- "foreign": [],
- "create": false,
- "help": "Configure the contract admin status of an account. This transaction must be sent by a contract admin.",
- "args": [
- {
- "name": "ignored",
- "pseudo": true,
- "kind": "string",
- "help": "",
- "default": "cX"
- },
- {
- "name": "status",
- "pseudo": false,
- "kind": "int",
- "help": "If this is 1, confer contract admin status on the account; otherwise, revoke contract admin status on the account."
- }
- ]
- },
- "transfer": {
- "on-completion": "NoOp",
- "accounts": [
- {
- "name": "receiver",
- "pseudo": false,
- "help": "The account receiving the tokens."
- }
- ],
- "foreign": [],
- "create": false,
- "help": "Transfer tokens to a receiver.",
- "args": [
- {
- "name": "amount",
- "pseudo": false,
- "kind": "int",
- "help": "The number of tokens to transfer."
- }
- ]
- },
- "upgrade": {
- "on-completion": "UpdateApplication",
- "accounts": [],
- "foreign": [],
- "create": false,
- "help": "Update the programs implementing the token. This transaction must be sent by a contract admin.",
- "args": []
- },
- "set-lock-until": {
- "on-completion": "NoOp",
- "accounts": [
- {
- "name": "target",
- "pseudo": false,
- "help": "The account to configure."
- }
- ],
- "foreign": [],
- "create": false,
- "help": "Set the first timestamp at which an account can issue transactions. This transaction must be sent by a transfer admin.",
- "args": [
- {
- "name": "ignored",
- "pseudo": true,
- "kind": "string",
- "help": "",
- "default": "tl"
- },
- {
- "name": "lock-until",
- "pseudo": false,
- "kind": "int",
- "help": "Transfers from the account will be restricted until this timestamp passes."
- }
- ]
- },
- "set-max-balance": {
- "on-completion": "NoOp",
- "accounts": [
- {
- "name": "target",
- "pseudo": false,
- "help": "The account to configure."
- }
- ],
- "foreign": [],
- "create": false,
- "help": "Set the maximum balance of an account. This transaction must be sent by a transfer admin.",
- "args": [
- {
- "name": "ignored",
- "pseudo": true,
- "kind": "string",
- "help": "",
- "default": "mb"
- },
- {
- "name": "max-balance",
- "pseudo": false,
- "kind": "int",
- "help": "The new maximum balance of the account."
- }
- ]
- },
- "create": {
- "on-completion": "OptIn",
- "accounts": [],
- "foreign": [],
- "create": true,
- "help": "Create a new security token.",
- "args": [
- {
- "name": "token-params",
- "pseudo": false,
- "kind": "string",
- "help": "The parameters for the token."
- },
- {
- "name": "total-supply",
- "pseudo": false,
- "kind": "int",
- "help": "The total supply for the token."
- }
- ]
- },
- "burn": {
- "on-completion": "NoOp",
- "accounts": [
- {
- "name": "target",
- "pseudo": false,
- "help": "The account from which to mint from."
- }
- ],
- "foreign": [],
- "create": false,
- "help": "Burn funds from an account. This circumvents other restrictions on that account. This transaction must be sent by a contract admin.",
- "args": [
- {
- "name": "ignored",
- "pseudo": true,
- "kind": "string",
- "help": "",
- "default": "br"
- },
- {
- "name": "amount",
- "pseudo": false,
- "kind": "int",
- "help": "The number of tokens to burn from the account."
- }
- ]
- },
- "freeze": {
- "on-completion": "NoOp",
- "accounts": [
- {
- "name": "target",
- "pseudo": false,
- "help": "The account which to freeze/unfreeze."
- }
- ],
- "foreign": [],
- "create": false,
- "help": "Freeze or unfreeze an account. This transaction must be sent by either a contract or a transfer admin.",
- "args": [
- {
- "name": "ignored",
- "pseudo": true,
- "kind": "string",
- "help": "",
- "default": "fz"
- },
- {
- "name": "frozen",
- "pseudo": false,
- "kind": "int",
- "help": "No transfers from this account will be allowed unless this is zero."
- }
- ]
- },
- "set-transfer-group": {
- "on-completion": "NoOp",
- "accounts": [
- {
- "name": "target",
- "pseudo": false,
- "help": "The account to configure."
- }
- ],
- "foreign": [],
- "create": false,
- "help": "Set the transfer group an account belongs to. This transaction must be sent by a transfer admin.",
- "args": [
- {
- "name": "ignored",
- "pseudo": true,
- "kind": "string",
- "help": "",
- "default": "tg"
- },
- {
- "name": "transfer-group",
- "pseudo": false,
- "kind": "int",
- "help": "The new transfer group of the account."
- }
- ]
- }
- }
-}
diff --git a/test/scripts/e2e_subs/tealprogs/sectok_approve.teal b/test/scripts/e2e_subs/tealprogs/sectok_approve.teal
deleted file mode 100644
index f8f0e00aa1..0000000000
--- a/test/scripts/e2e_subs/tealprogs/sectok_approve.teal
+++ /dev/null
@@ -1,389 +0,0 @@
-#pragma version 2
-txn ApplicationID
-int 0
-==
-bnz cond1
-txn OnCompletion
-int 5
-==
-bnz cond2
-txn OnCompletion
-int 4
-==
-bnz cond3
-txn OnCompletion
-int 1
-==
-bnz cond4
-txn OnCompletion
-int 0
-==
-txn NumAccounts
-int 2
-<
-&&
-bnz assert5
-err
-assert5:
-txn NumAccounts
-int 0
-==
-bnz if6
-txn NumAppArgs
-int 1
-==
-bnz if8
-// config
-txn NumAppArgs
-int 2
-==
-bnz assert10
-err
-assert10:
-txna ApplicationArgs 0
-byte "cX"
-==
-txna ApplicationArgs 0
-byte "tX"
-==
-||
-bnz cond12
-txna ApplicationArgs 0
-byte "mn"
-==
-bnz cond13
-txna ApplicationArgs 0
-byte "br"
-==
-bnz cond14
-// set max balance, lock until, transfer group, freeze
-int 1
-txna ApplicationArgs 0
-txna ApplicationArgs 1
-btoi
-app_local_put
-txna ApplicationArgs 0
-byte "fz"
-==
-int 0
-byte base64 Y1g=
-app_local_get
-int 1
-==
-int 0
-byte base64 dFg=
-app_local_get
-int 1
-==
-||
-&&
-int 0
-byte base64 dFg=
-app_local_get
-int 1
-==
-txna ApplicationArgs 0
-byte "mb"
-==
-txna ApplicationArgs 0
-byte "tl"
-==
-||
-txna ApplicationArgs 0
-byte "tg"
-==
-||
-&&
-||
-int 1
-bnz cond_end11
-cond14:
-// burn
-int 1
-byte base64 Ymw=
-int 1
-byte base64 Ymw=
-app_local_get
-txna ApplicationArgs 1
-btoi
--
-app_local_put
-byte base64 cnY=
-byte base64 cnY=
-app_global_get
-txna ApplicationArgs 1
-btoi
-+
-app_global_put
-int 0
-byte base64 Y1g=
-app_local_get
-int 1
-==
-int 1
-bnz cond_end11
-cond13:
-// mint
-int 1
-byte base64 Ymw=
-int 1
-byte base64 Ymw=
-app_local_get
-txna ApplicationArgs 1
-btoi
-+
-app_local_put
-byte base64 cnY=
-byte base64 cnY=
-app_global_get
-txna ApplicationArgs 1
-btoi
--
-app_global_put
-int 0
-byte base64 Y1g=
-app_local_get
-int 1
-==
-int 1
-bnz cond_end11
-cond12:
-// contract/transfer admin
-int 0
-byte base64 Y1g=
-app_local_get
-int 1
-==
-bnz assert15
-err
-assert15:
-int 1
-txna ApplicationArgs 0
-txna ApplicationArgs 1
-btoi
-app_local_put
-int 1
-cond_end11:
-int 1
-bnz if_end9
-if8:
-// transfer
-int 0
-byte base64 Ymw=
-int 0
-byte base64 Ymw=
-app_local_get
-txna ApplicationArgs 0
-btoi
--
-app_local_put
-int 1
-byte base64 Ymw=
-int 1
-byte base64 Ymw=
-app_local_get
-txna ApplicationArgs 0
-btoi
-+
-app_local_put
-byte base64 cHM=
-app_global_get
-int 0
-==
-int 1
-byte base64 Ymw=
-app_local_get
-int 1
-byte base64 bWI=
-app_local_get
-<=
-&&
-int 0
-byte base64 Zno=
-app_local_get
-int 0
-==
-&&
-int 1
-byte base64 Zno=
-app_local_get
-int 0
-==
-&&
-int 0
-byte base64 dGw=
-app_local_get
-global LatestTimestamp
-<
-&&
-int 1
-byte base64 dGw=
-app_local_get
-global LatestTimestamp
-<
-&&
-byte 0x0001
-int 0
-byte base64 dGc=
-app_local_get
-itob
-concat
-int 1
-byte base64 dGc=
-app_local_get
-itob
-concat
-app_global_get
-int 1
--
-global LatestTimestamp
-<
-&&
-if_end9:
-int 1
-bnz if_end7
-if6:
-txn NumAppArgs
-int 1
-==
-bnz if16
-// transfer-rule
-txna ApplicationArgs 2
-btoi
-int 0
-==
-bnz if18
-byte 0x0001
-txna ApplicationArgs 0
-concat
-txna ApplicationArgs 1
-concat
-txna ApplicationArgs 2
-btoi
-app_global_put
-int 1
-bnz if_end19
-if18:
-byte 0x0001
-txna ApplicationArgs 0
-concat
-txna ApplicationArgs 1
-concat
-app_global_del
-if_end19:
-txna ApplicationArgs 0
-len
-int 8
-==
-txna ApplicationArgs 1
-len
-int 8
-==
-&&
-txn NumAppArgs
-int 3
-==
-&&
-int 0
-byte base64 dFg=
-app_local_get
-int 1
-==
-&&
-int 1
-bnz if_end17
-if16:
-// pause
-byte base64 cHM=
-txna ApplicationArgs 0
-btoi
-app_global_put
-int 0
-byte base64 Y1g=
-app_local_get
-int 1
-==
-if_end17:
-if_end7:
-int 1
-bnz cond_end0
-cond4:
-// opt-in
-txn NumAppArgs
-int 0
-==
-txn NumAccounts
-int 0
-==
-&&
-int 1
-bnz cond_end0
-cond3:
-// upgrade
-txn NumAppArgs
-int 0
-==
-txn NumAccounts
-int 0
-==
-&&
-int 0
-byte base64 Y1g=
-app_local_get
-int 1
-==
-&&
-int 1
-bnz cond_end0
-cond2:
-// destroy
-txn NumAppArgs
-int 0
-==
-txn NumAccounts
-int 0
-==
-&&
-int 0
-byte base64 Y1g=
-app_local_get
-int 1
-==
-&&
-byte base64 cnY=
-app_global_get
-byte base64 dHQ=
-app_global_get
-==
-&&
-int 1
-bnz cond_end0
-cond1:
-// create
-int 0
-byte base64 Y1g=
-int 1
-app_local_put
-byte base64 cHg=
-txna ApplicationArgs 0
-app_global_put
-byte base64 cnY=
-txna ApplicationArgs 1
-btoi
-app_global_put
-byte base64 dHQ=
-txna ApplicationArgs 1
-btoi
-app_global_put
-txn NumAppArgs
-int 2
-==
-txn NumAccounts
-int 0
-==
-&&
-txn OnCompletion
-int 1
-==
-&&
-cond_end0:
diff --git a/test/scripts/e2e_subs/tealprogs/sectok_clear.teal b/test/scripts/e2e_subs/tealprogs/sectok_clear.teal
deleted file mode 100644
index 79d6193fa9..0000000000
--- a/test/scripts/e2e_subs/tealprogs/sectok_clear.teal
+++ /dev/null
@@ -1,10 +0,0 @@
-#pragma version 2
-
-byte base64 cnY=
-byte base64 cnY=
-app_global_get
-int 0
-byte base64 Ymw=
-app_local_get
-+
-app_global_put
diff --git a/test/testdata/configs/config-v38.json b/test/testdata/configs/config-v38.json
new file mode 100644
index 0000000000..245017d4e8
--- /dev/null
+++ b/test/testdata/configs/config-v38.json
@@ -0,0 +1,151 @@
+{
+ "Version": 38,
+ "AccountUpdatesStatsInterval": 5000000000,
+ "AccountsRebuildSynchronousMode": 1,
+ "AgreementIncomingBundlesQueueLength": 15,
+ "AgreementIncomingProposalsQueueLength": 50,
+ "AgreementIncomingVotesQueueLength": 20000,
+ "AnnounceParticipationKey": true,
+ "Archival": false,
+ "BaseLoggerDebugLevel": 4,
+ "BlockDBDir": "",
+ "BlockServiceCustomFallbackEndpoints": "",
+ "BlockServiceMemCap": 500000000,
+ "BroadcastConnectionsLimit": -1,
+ "CadaverDirectory": "",
+ "CadaverSizeTarget": 0,
+ "CatchpointDir": "",
+ "CatchpointFileHistoryLength": 365,
+ "CatchpointInterval": 10000,
+ "CatchpointTracking": 0,
+ "CatchupBlockDownloadRetryAttempts": 1000,
+ "CatchupBlockValidateMode": 0,
+ "CatchupFailurePeerRefreshRate": 10,
+ "CatchupGossipBlockFetchTimeoutSec": 4,
+ "CatchupHTTPBlockFetchTimeoutSec": 4,
+ "CatchupLedgerDownloadRetryAttempts": 50,
+ "CatchupParallelBlocks": 16,
+ "ColdDataDir": "",
+ "ConnectionsRateLimitingCount": 60,
+ "ConnectionsRateLimitingWindowSeconds": 1,
+ "CrashDBDir": "",
+ "DHTMode": "",
+ "DNSBootstrapID": ".algorand.network?backup=.algorand.net&dedup=.algorand-.(network|net)",
+ "DNSSecurityFlags": 9,
+ "DeadlockDetection": 0,
+ "DeadlockDetectionThreshold": 30,
+ "DisableAPIAuth": false,
+ "DisableLedgerLRUCache": false,
+ "DisableLocalhostConnectionRateLimit": true,
+ "DisableNetworking": false,
+ "DisableOutgoingConnectionThrottling": false,
+ "EnableAccountUpdatesStats": false,
+ "EnableAgreementReporting": false,
+ "EnableAgreementTimeMetrics": false,
+ "EnableAssembleStats": false,
+ "EnableBatchVerification": true,
+ "EnableBlockService": false,
+ "EnableDHTProviders": false,
+ "EnableDeveloperAPI": false,
+ "EnableExperimentalAPI": false,
+ "EnableFollowMode": false,
+ "EnableGossipBlockService": true,
+ "EnableGossipService": true,
+ "EnableIncomingMessageFilter": false,
+ "EnableLedgerService": false,
+ "EnableMetricReporting": false,
+ "EnableNetDevMetrics": false,
+ "EnableOutgoingNetworkMessageFiltering": true,
+ "EnableP2P": false,
+ "EnableP2PHybridMode": false,
+ "EnablePingHandler": true,
+ "EnablePrivateNetworkAccessHeader": false,
+ "EnableProcessBlockStats": false,
+ "EnableProfiler": false,
+ "EnableRequestLogger": false,
+ "EnableRuntimeMetrics": false,
+ "EnableTopAccountsReporting": false,
+ "EnableTxBacklogAppRateLimiting": true,
+ "EnableTxBacklogRateLimiting": true,
+ "EnableTxnEvalTracer": false,
+ "EnableUsageLog": false,
+ "EnableVerbosedTransactionSyncLogging": false,
+ "EnableVoteCompression": true,
+ "EndpointAddress": "127.0.0.1:0",
+ "FallbackDNSResolverAddress": "",
+ "ForceFetchTransactions": false,
+ "ForceRelayMessages": false,
+ "GoMemLimit": 0,
+ "GossipFanout": 4,
+ "HeartbeatUpdateInterval": 600,
+ "HotDataDir": "",
+ "IncomingConnectionsLimit": 2400,
+ "IncomingMessageFilterBucketCount": 5,
+ "IncomingMessageFilterBucketSize": 512,
+ "LedgerSynchronousMode": 2,
+ "LogArchiveDir": "",
+ "LogArchiveMaxAge": "",
+ "LogArchiveName": "node.archive.log",
+ "LogFileDir": "",
+ "LogSizeLimit": 1073741824,
+ "MaxAPIBoxPerApplication": 100000,
+ "MaxAPIResourcesPerAccount": 100000,
+ "MaxAcctLookback": 4,
+ "MaxBlockHistoryLookback": 0,
+ "MaxCatchpointDownloadDuration": 43200000000000,
+ "MaxConnectionsPerIP": 8,
+ "MinCatchpointFileDownloadBytesPerSecond": 20480,
+ "NetAddress": "",
+ "NetworkMessageTraceServer": "",
+ "NetworkProtocolVersion": "",
+ "NodeExporterListenAddress": ":9100",
+ "NodeExporterPath": "./node_exporter",
+ "OptimizeAccountsDatabaseOnStartup": false,
+ "OutgoingMessageFilterBucketCount": 3,
+ "OutgoingMessageFilterBucketSize": 128,
+ "P2PHybridIncomingConnectionsLimit": 1200,
+ "P2PHybridNetAddress": "",
+ "P2PPersistPeerID": false,
+ "P2PPrivateKeyLocation": "",
+ "ParticipationKeysRefreshInterval": 60000000000,
+ "PeerConnectionsUpdateInterval": 3600,
+ "PeerPingPeriodSeconds": 0,
+ "PriorityPeers": {},
+ "ProposalAssemblyTime": 500000000,
+ "PublicAddress": "",
+ "ReconnectTime": 60000000000,
+ "ReservedFDs": 256,
+ "RestConnectionsHardLimit": 2048,
+ "RestConnectionsSoftLimit": 1024,
+ "RestReadTimeoutSeconds": 15,
+ "RestWriteTimeoutSeconds": 120,
+ "RunHosted": false,
+ "StatefulVoteCompressionTableSize": 2048,
+ "StateproofDir": "",
+ "StorageEngine": "sqlite",
+ "SuggestedFeeBlockHistory": 3,
+ "SuggestedFeeSlidingWindowSize": 50,
+ "TLSCertFile": "",
+ "TLSKeyFile": "",
+ "TelemetryToLog": true,
+ "TrackerDBDir": "",
+ "TransactionSyncDataExchangeRate": 0,
+ "TransactionSyncSignificantMessageThreshold": 0,
+ "TxBacklogAppRateLimitingCongestionPct": 10,
+ "TxBacklogAppRateLimitingCountERLDrops": false,
+ "TxBacklogAppTxPerSecondRate": 100,
+ "TxBacklogAppTxRateLimiterMaxSize": 1048576,
+ "TxBacklogRateLimitingCongestionPct": 50,
+ "TxBacklogReservedCapacityPerPeer": 20,
+ "TxBacklogServiceRateWindowSeconds": 10,
+ "TxBacklogSize": 26000,
+ "TxIncomingFilterMaxSize": 500000,
+ "TxIncomingFilteringFlags": 1,
+ "TxPoolExponentialIncreaseFactor": 2,
+ "TxPoolSize": 75000,
+ "TxSyncIntervalSeconds": 60,
+ "TxSyncServeResponseSize": 1000000,
+ "TxSyncTimeoutSeconds": 30,
+ "UseXForwardedForAddressField": "",
+ "VerifiedTranscationsCacheSize": 150000
+}
diff --git a/tool.mod b/tool.mod
new file mode 100644
index 0000000000..bc34310d1e
--- /dev/null
+++ b/tool.mod
@@ -0,0 +1,25 @@
+module github.com/algorand/go-algorand/tools
+
+go 1.25.3
+
+tool (
+ golang.org/x/tools/cmd/stringer
+ gotest.tools/gotestsum
+)
+
+require (
+ github.com/bitfield/gotestdox v0.2.2 // indirect
+ github.com/dnephin/pflag v1.0.7 // indirect
+ github.com/fatih/color v1.18.0 // indirect
+ github.com/fsnotify/fsnotify v1.9.0 // indirect
+ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ golang.org/x/mod v0.29.0 // indirect
+ golang.org/x/sync v0.17.0 // indirect
+ golang.org/x/sys v0.37.0 // indirect
+ golang.org/x/term v0.35.0 // indirect
+ golang.org/x/text v0.17.0 // indirect
+ golang.org/x/tools v0.38.0 // indirect
+ gotest.tools/gotestsum v1.13.0 // indirect
+)
diff --git a/tool.sum b/tool.sum
new file mode 100644
index 0000000000..e14cfa5dd1
--- /dev/null
+++ b/tool.sum
@@ -0,0 +1,31 @@
+github.com/bitfield/gotestdox v0.2.2 h1:x6RcPAbBbErKLnapz1QeAlf3ospg8efBsedU93CDsnE=
+github.com/bitfield/gotestdox v0.2.2/go.mod h1:D+gwtS0urjBrzguAkTM2wodsTQYFHdpx8eqRJ3N+9pY=
+github.com/dnephin/pflag v1.0.7 h1:oxONGlWxhmUct0YzKTgrpQv9AUA1wtPBn7zuSjJqptk=
+github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE=
+github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
+github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
+github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
+github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
+github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
+golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
+golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
+golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
+golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
+golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
+golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
+golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
+golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
+gotest.tools/gotestsum v1.13.0 h1:+Lh454O9mu9AMG1APV4o0y7oDYKyik/3kBOiCqiEpRo=
+gotest.tools/gotestsum v1.13.0/go.mod h1:7f0NS5hFb0dWr4NtcsAsF0y1kzjEFfAil0HiBQJE03Q=
diff --git a/tools/block-generator/core/commands.go b/tools/block-generator/core/commands.go
index 37b78feb6c..a67fc80e95 100644
--- a/tools/block-generator/core/commands.go
+++ b/tools/block-generator/core/commands.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/generator/config.go b/tools/block-generator/generator/config.go
index fc833c1171..862c8acdd0 100644
--- a/tools/block-generator/generator/config.go
+++ b/tools/block-generator/generator/config.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/generator/config_test.go b/tools/block-generator/generator/config_test.go
index 1f86aff09b..dd8ba9919a 100644
--- a/tools/block-generator/generator/config_test.go
+++ b/tools/block-generator/generator/config_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/generator/daemon.go b/tools/block-generator/generator/daemon.go
index 5d0e3d8317..3eb369c94b 100644
--- a/tools/block-generator/generator/daemon.go
+++ b/tools/block-generator/generator/daemon.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/generator/generate.go b/tools/block-generator/generator/generate.go
index 5efe9d016d..42665efd11 100644
--- a/tools/block-generator/generator/generate.go
+++ b/tools/block-generator/generator/generate.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -552,7 +552,7 @@ func (g *generator) generateTxGroup(round basics.Round, intra uint64) ([]txn.Sig
txnGroupAD := make([]txn.SignedTxnWithAD, len(signedTxns))
for i := range signedTxns {
- txnGroupAD[i] = txn.SignedTxnWithAD{SignedTxn: signedTxns[i]}
+ txnGroupAD[i] = signedTxns[i].WithAD()
// for debugging:
g.latestPaysetWithExpectedID = append(
diff --git a/tools/block-generator/generator/generate_apps.go b/tools/block-generator/generator/generate_apps.go
index 25665fb7ad..c4b5873cd3 100644
--- a/tools/block-generator/generator/generate_apps.go
+++ b/tools/block-generator/generator/generate_apps.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/generator/generate_test.go b/tools/block-generator/generator/generate_test.go
index 4040c0724d..fa15d45c48 100644
--- a/tools/block-generator/generator/generate_test.go
+++ b/tools/block-generator/generator/generate_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/generator/generator_ledger.go b/tools/block-generator/generator/generator_ledger.go
index 71f95aa9d7..b9e08f9554 100644
--- a/tools/block-generator/generator/generator_ledger.go
+++ b/tools/block-generator/generator/generator_ledger.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -179,7 +179,7 @@ func (g *generator) evaluateBlock(hdr bookkeeping.BlockHeader, txGroups [][]txn.
}
for i, txGroup := range txGroups {
for {
- txErr := eval.TransactionGroup(txGroup)
+ txErr := eval.TransactionGroup(txGroup...)
if txErr != nil {
if strings.Contains(txErr.Error(), "database table is locked") {
time.Sleep(waitDelay)
diff --git a/tools/block-generator/generator/generator_types.go b/tools/block-generator/generator/generator_types.go
index a13d652f8f..16371bf511 100644
--- a/tools/block-generator/generator/generator_types.go
+++ b/tools/block-generator/generator/generator_types.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/generator/make_transactions.go b/tools/block-generator/generator/make_transactions.go
index 76c5590555..464b090a39 100644
--- a/tools/block-generator/generator/make_transactions.go
+++ b/tools/block-generator/generator/make_transactions.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/generator/server.go b/tools/block-generator/generator/server.go
index 3694f95df6..246be56f52 100644
--- a/tools/block-generator/generator/server.go
+++ b/tools/block-generator/generator/server.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/generator/server_test.go b/tools/block-generator/generator/server_test.go
index 562d81f8ff..2c318e0e96 100644
--- a/tools/block-generator/generator/server_test.go
+++ b/tools/block-generator/generator/server_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/generator/utils.go b/tools/block-generator/generator/utils.go
index 40afb7b1a1..e40365a47c 100644
--- a/tools/block-generator/generator/utils.go
+++ b/tools/block-generator/generator/utils.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/generator/utils_test.go b/tools/block-generator/generator/utils_test.go
index 9728a98aa6..73148fcb4b 100644
--- a/tools/block-generator/generator/utils_test.go
+++ b/tools/block-generator/generator/utils_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/go.mod b/tools/block-generator/go.mod
index 3610115047..984ef0c5c4 100644
--- a/tools/block-generator/go.mod
+++ b/tools/block-generator/go.mod
@@ -155,7 +155,7 @@ require (
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
- github.com/sirupsen/logrus v1.8.1 // indirect
+ github.com/sirupsen/logrus v1.8.3 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
@@ -169,14 +169,15 @@ require (
go.uber.org/mock v0.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
- golang.org/x/crypto v0.37.0 // indirect
+ golang.org/x/crypto v0.45.0 // indirect
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
- golang.org/x/mod v0.22.0 // indirect
- golang.org/x/net v0.39.0 // indirect
- golang.org/x/sync v0.13.0 // indirect
- golang.org/x/sys v0.32.0 // indirect
- golang.org/x/text v0.24.0 // indirect
- golang.org/x/tools v0.27.0 // indirect
+ golang.org/x/mod v0.29.0 // indirect
+ golang.org/x/net v0.47.0 // indirect
+ golang.org/x/sync v0.18.0 // indirect
+ golang.org/x/sys v0.38.0 // indirect
+ golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect
+ golang.org/x/text v0.31.0 // indirect
+ golang.org/x/tools v0.38.0 // indirect
gonum.org/v1/gonum v0.15.0 // indirect
google.golang.org/protobuf v1.35.1 // indirect
gopkg.in/sohlich/elogrus.v3 v3.0.0-20180410122755-1fa29e2f2009 // indirect
diff --git a/tools/block-generator/go.sum b/tools/block-generator/go.sum
index 0ada99f446..8f3402d323 100644
--- a/tools/block-generator/go.sum
+++ b/tools/block-generator/go.sum
@@ -564,8 +564,8 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
-github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.8.3 h1:DBBfY8eMYazKEJHb3JKpSPfpgd2mBCoNFlQx6C5fftU=
+github.com/sirupsen/logrus v1.8.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
@@ -678,8 +678,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
-golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
-golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
+golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
+golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
@@ -696,8 +696,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
-golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
+golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
+golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -728,8 +728,8 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
-golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
-golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
+golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
+golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
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=
@@ -745,8 +745,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
-golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
+golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -775,6 +775,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/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=
@@ -783,8 +784,10 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
-golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
+golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU=
+golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -802,8 +805,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
-golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
+golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
+golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
@@ -827,8 +830,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
-golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
+golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
+golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/tools/block-generator/main.go b/tools/block-generator/main.go
index fb2a3f5287..2a3116b4d3 100644
--- a/tools/block-generator/main.go
+++ b/tools/block-generator/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/runner/metrics_collector.go b/tools/block-generator/runner/metrics_collector.go
index 412078ab73..159a0927bc 100644
--- a/tools/block-generator/runner/metrics_collector.go
+++ b/tools/block-generator/runner/metrics_collector.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/runner/reporting_test.go b/tools/block-generator/runner/reporting_test.go
index 536feab779..d84825cfa5 100644
--- a/tools/block-generator/runner/reporting_test.go
+++ b/tools/block-generator/runner/reporting_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/runner/run.go b/tools/block-generator/runner/run.go
index 28216d868f..529629a386 100644
--- a/tools/block-generator/runner/run.go
+++ b/tools/block-generator/runner/run.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/runner/runner.go b/tools/block-generator/runner/runner.go
index e3c857c3ce..06252006a9 100644
--- a/tools/block-generator/runner/runner.go
+++ b/tools/block-generator/runner/runner.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/block-generator/util/util.go b/tools/block-generator/util/util.go
index e1c66df7e0..c447730194 100644
--- a/tools/block-generator/util/util.go
+++ b/tools/block-generator/util/util.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/boxkey/convertBoxKey.go b/tools/boxkey/convertBoxKey.go
index f1f4d31ed2..ae1afda261 100644
--- a/tools/boxkey/convertBoxKey.go
+++ b/tools/boxkey/convertBoxKey.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/debug/algodump/compress.go b/tools/debug/algodump/compress.go
new file mode 100644
index 0000000000..a0aed9566a
--- /dev/null
+++ b/tools/debug/algodump/compress.go
@@ -0,0 +1,633 @@
+// Copyright (C) 2019-2026 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 main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "os/signal"
+ "sort"
+ "strconv"
+ "strings"
+ "syscall"
+ "time"
+
+ "github.com/DataDog/zstd"
+ "github.com/algorand/go-algorand/agreement"
+ "github.com/algorand/go-algorand/crypto"
+ "github.com/algorand/go-algorand/data/transactions"
+ "github.com/algorand/go-algorand/network"
+ "github.com/algorand/go-algorand/network/vpack"
+ "github.com/algorand/go-algorand/protocol"
+ "github.com/algorand/go-deadlock"
+ kzstd "github.com/klauspost/compress/zstd"
+ "github.com/valyala/gozstd"
+)
+
+// Compression-specific flags
+var compress = flag.Bool("compress", false, "Compress messages and show statistics")
+var dictionaryFile = flag.String("dict", "", "Path to zstd dictionary file to use for compression")
+var compressionLevel = flag.Int("level", 3, "Compression level (1-9, higher = better compression but slower)")
+var printCompressGrow = flag.Bool("printCompressGrow", false, "Print hex dump of messages that grow after compression")
+var storeDir = flag.String("store", "", "Directory to store messages in")
+var storeBatchSize = flag.Int("storeBatch", 1024*1024, "Flush messages to disk after accumulating this many bytes")
+var compressionWindowSize = flag.Int("windowSize", 32768, "Compression window size in bytes")
+var contextConfig = flag.String("contextcfg", "", "Configure tag-specific compression contexts with window sizes. Format: TAG1:size1;TAG2,TAG3:size2 (e.g. AV:4096;TX,PP:32768)")
+var useGozstd = flag.Bool("useGozstd", false, "Use gozstd (C implementation) instead of klauspost (Go implementation) for compression contexts")
+var useVpack = flag.Bool("useVpack", false, "Use vpack compression library (optimized for AgreementVote messages) instead of zstd")
+
+// CompressionInterface defines the methods needed for a compression implementation
+type CompressionInterface interface {
+ Write(p []byte) (n int, err error)
+ Flush() error
+ Close() error
+}
+
+// GozstdWriterAdapter adapts the gozstd Writer to implement our CompressionInterface
+type GozstdWriterAdapter struct {
+ writer *gozstd.Writer
+ buf *bytes.Buffer
+ level int
+ windowLog int
+}
+
+func NewGozstdWriterAdapter(buf *bytes.Buffer, level, windowLog int, cd *gozstd.CDict) *GozstdWriterAdapter {
+ // Create parameters including dictionary if provided
+ params := &gozstd.WriterParams{
+ CompressionLevel: level,
+ WindowLog: windowLog,
+ Dict: cd,
+ }
+ writer := gozstd.NewWriterParams(buf, params)
+
+ return &GozstdWriterAdapter{
+ writer: writer,
+ buf: buf,
+ level: level,
+ windowLog: windowLog,
+ }
+}
+
+func (a *GozstdWriterAdapter) Write(p []byte) (n int, err error) { return a.writer.Write(p) }
+func (a *GozstdWriterAdapter) Flush() error { return a.writer.Flush() }
+func (a *GozstdWriterAdapter) Close() error { return a.writer.Close() }
+
+// CompressionContext holds the state for a compression context, which can use either
+// klauspost/zstd (pure Go) or valyala/gozstd (C-based) implementation
+type CompressionContext struct {
+ w CompressionInterface // Interface that wraps either klauspost or gozstd writer
+ buf *bytes.Buffer // Buffer to hold compressed data
+ cnt uint64 // Counter for bytes processed
+ isGozstd bool // Whether this context uses gozstd
+}
+
+type tagStats struct {
+ originalBytes uint64
+ compressedBytes uint64
+ messageCount uint64
+ contextBytes uint64
+ mu deadlock.Mutex
+}
+
+// compressDumpHandler extends dumpHandler with compression functionality
+type compressDumpHandler struct {
+ *dumpHandler // Embed the original dumpHandler
+ stats map[protocol.Tag]*tagStats
+ statsMutex deadlock.Mutex
+ compressor *zstd.BulkProcessor
+ contexts map[string]*CompressionContext
+ contextMu deadlock.Mutex
+ dict []byte
+ cdict *gozstd.CDict // Reusable gozstd dictionary
+
+ // vpack-related fields
+ vpackEncoder *vpack.StatelessEncoder
+ vpackDecoder *vpack.StatelessDecoder
+
+ // Tag-specific context configuration
+ tagContexts map[protocol.Tag]int // Maps tag to window size
+ tagGroups map[protocol.Tag]string // Maps tag to group name for shared contexts
+ tagContextsMu deadlock.Mutex
+}
+
+// setupCompressSignalHandler sets up a signal handler for the compressDumpHandler
+func setupCompressSignalHandler(dh *compressDumpHandler) {
+ c := make(chan os.Signal, 1)
+ signal.Notify(c, os.Interrupt, syscall.SIGTERM)
+ go func() {
+ <-c
+ // Flush any remaining messages
+ if *storeDir != "" {
+ dh.storeFlush()
+ }
+ // Print compression stats on exit
+ dh.printStats()
+ os.Exit(0)
+ }()
+}
+
+// Handle implements the network.MessageHandler interface for compressDumpHandler
+func (dh *compressDumpHandler) Handle(msg network.IncomingMessage) network.OutgoingMessage {
+ // First check if we should handle this message based on tag filtering
+ if dh.tags != nil && !dh.tags[msg.Tag] {
+ return network.OutgoingMessage{Action: network.Ignore}
+ }
+
+ var src string
+ // In playback mode, create a fake peer if none exists
+ if msg.Sender == nil && *playbackDir != "" {
+ msg.Sender = &fakePeer{}
+ }
+
+ hp, ok := msg.Sender.(network.HTTPPeer)
+ if ok {
+ a := hp.GetAddress()
+ if a != *serverAddress {
+ src = " " + hp.GetAddress()
+ }
+ }
+
+ ts := time.Now().Format("15:04:05.000000")
+ var txnstr string
+ // Extract message data (reuse code from original dumpHandler)
+ switch msg.Tag {
+ case protocol.AgreementVoteTag:
+ var v agreement.UnauthenticatedVote
+ err := protocol.Decode(msg.Data, &v)
+ if err != nil {
+ txnstr = fmt.Sprintf("[decode error: %v]", err)
+ goto compress
+ }
+
+ txnstr = fmt.Sprintf("%d/%d/%d from %s for %s", v.R.Round, v.R.Period, v.R.Step, shortaddr(v.R.Sender), shortdigest(v.R.Proposal.BlockDigest))
+
+ case protocol.ProposalPayloadTag:
+ var p agreement.TransmittedPayload
+ err := protocol.Decode(msg.Data, &p)
+ if err != nil {
+ txnstr = fmt.Sprintf("[decode error: %v]", err)
+ goto compress
+ }
+
+ txnstr = fmt.Sprintf("proposal %s", shortdigest(crypto.Digest(p.Block.Hash())))
+
+ case protocol.TxnTag:
+ dec := protocol.NewMsgpDecoderBytes(msg.Data)
+ for {
+ var stx transactions.SignedTxn
+ err := dec.Decode(&stx)
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ txnstr = fmt.Sprintf("[decode error: %v]", err)
+ goto compress
+ }
+ if len(txnstr) > 0 {
+ txnstr = txnstr + ", "
+ }
+ txnstr = txnstr + fmt.Sprintf("%s from %s", stx.Txn.Type, shortaddr(stx.Txn.Sender))
+ }
+ }
+
+compress:
+ // Compress the message and update statistics
+ dh.statsMutex.Lock()
+ if dh.stats[msg.Tag] == nil {
+ dh.stats[msg.Tag] = &tagStats{}
+ }
+ stats := dh.stats[msg.Tag]
+ dh.statsMutex.Unlock()
+
+ var compressed []byte
+ var err error
+ var contextCompressed []byte
+ var vpackCompressed []byte
+
+ // If using vpack, try to compress the message with vpack first
+ if *useVpack && dh.vpackEncoder != nil {
+ if msg.Tag == protocol.AgreementVoteTag {
+ // Use vpack compression for Agreement Vote messages
+ vpackCompressed, err = dh.vpackEncoder.CompressVote(nil, msg.Data)
+ if err != nil {
+ // Log error but continue with standard compression
+ fmt.Fprintf(os.Stderr, "vpack CompressVote error: %v\n", err)
+ }
+ }
+ }
+
+ // Handle context reuse compression first (if not using vpack or vpack failed or message is not an AV)
+ if !*useVpack || vpackCompressed == nil {
+ if hp, ok := msg.Sender.(network.HTTPPeer); ok {
+ addr := hp.GetAddress()
+ // Add the tag group or tag as a suffix if we have tag-specific contexts configured
+ contextKey := addr
+ windowSize := *compressionWindowSize
+
+ dh.tagContextsMu.Lock()
+ if len(dh.tagContexts) > 0 {
+ if tagWindowSize, ok := dh.tagContexts[msg.Tag]; ok {
+ // Use the group name if this tag belongs to a group
+ if groupName, ok := dh.tagGroups[msg.Tag]; ok {
+ contextKey = addr + "-" + groupName
+ } else {
+ contextKey = addr + "-" + string(msg.Tag)
+ }
+ windowSize = tagWindowSize
+ }
+ }
+ dh.tagContextsMu.Unlock()
+
+ dh.contextMu.Lock()
+ ctx := dh.contexts[contextKey]
+ if ctx == nil {
+ // Create new context
+ buf := &bytes.Buffer{}
+
+ if *useGozstd {
+ // Calculate window log from window size (converting bytes to power of 2)
+ windowLog := 0
+ size := windowSize
+ for size > 1 {
+ size >>= 1
+ windowLog++
+ }
+ // Clamp to valid gozstd window log range
+ if windowLog < gozstd.WindowLogMin {
+ windowLog = gozstd.WindowLogMin
+ } else if windowLog > gozstd.WindowLogMax64 {
+ windowLog = gozstd.WindowLogMax64
+ }
+
+ // Create adapter for gozstd writer that implements CompressionInterface
+ adapter := NewGozstdWriterAdapter(buf, *compressionLevel, windowLog, dh.cdict)
+
+ // Create compression context
+ ctx = &CompressionContext{
+ w: adapter,
+ buf: buf,
+ isGozstd: true,
+ }
+ } else {
+ // Use klauspost implementation (pure Go)
+ klevel := kzstd.EncoderLevelFromZstd(*compressionLevel)
+ opts := []kzstd.EOption{
+ kzstd.WithEncoderLevel(klevel),
+ kzstd.WithWindowSize(windowSize),
+ }
+ if dh.dict != nil {
+ opts = append(opts, kzstd.WithEncoderDict(dh.dict))
+ }
+ w, err := kzstd.NewWriter(buf, opts...)
+ if err != nil {
+ log.Fatalf("Failed to create klauspost zstd writer: %v", err)
+ }
+ ctx = &CompressionContext{w: w, buf: buf}
+ }
+
+ dh.contexts[contextKey] = ctx
+ }
+
+ // Write message to context
+ ctx.buf.Reset()
+ _, err = ctx.w.Write(msg.Data)
+ if err != nil {
+ log.Fatalf("Error writing to compression context: %v", err)
+ }
+ err = ctx.w.Flush()
+ if err != nil {
+ log.Fatalf("Error flushing compression context: %v", err)
+ }
+ ctx.cnt += uint64(len(msg.Data))
+ contextCompressed = ctx.buf.Bytes()
+ dh.contextMu.Unlock()
+ }
+
+ // Do regular compression for comparison
+ if dh.compressor != nil {
+ // Use dictionary-based compression
+ compressed, err = dh.compressor.Compress(nil, msg.Data)
+ } else {
+ // Use standard compression
+ compressed, err = zstd.Compress(nil, msg.Data)
+ }
+ if err != nil {
+ log.Fatalf("Error compressing data: %v", err)
+ }
+ } else {
+ // Use the vpack compressed data if available
+ compressed = vpackCompressed
+ }
+
+ stats.mu.Lock()
+ stats.originalBytes += uint64(len(msg.Data))
+ stats.compressedBytes += uint64(len(compressed))
+ if len(contextCompressed) > 0 {
+ stats.contextBytes += uint64(len(contextCompressed))
+ }
+ stats.messageCount++
+ stats.mu.Unlock()
+
+ if !*quiet {
+ reduction := (1.0 - float64(len(compressed))/float64(len(msg.Data))) * 100
+ output := fmt.Sprintf("%s%s %s [%d->%d bytes %.1f%% reduction]",
+ ts, src, msg.Tag,
+ len(msg.Data), len(compressed),
+ reduction)
+
+ if len(contextCompressed) > 0 {
+ ctxReduction := (1.0 - float64(len(contextCompressed))/float64(len(msg.Data))) * 100
+ ctxInfo := fmt.Sprintf(" [ctx: %d bytes %.1f%% reduction]",
+ len(contextCompressed), ctxReduction)
+
+ dh.tagContextsMu.Lock()
+ if tagWindowSize, ok := dh.tagContexts[msg.Tag]; ok {
+ ctxInfo = fmt.Sprintf(" [ctx(%s:%d): %d bytes %.1f%% reduction]",
+ string(msg.Tag), tagWindowSize, len(contextCompressed), ctxReduction)
+ }
+ dh.tagContextsMu.Unlock()
+
+ output += ctxInfo
+ }
+
+ if len(txnstr) > 0 {
+ output += " " + txnstr
+ }
+
+ fmt.Println(output)
+
+ // Print if compression made it bigger
+ if *printCompressGrow && len(compressed) > len(msg.Data) {
+ fmt.Printf("Message grew after compression! Original (%d bytes):\n", len(msg.Data))
+ fmt.Printf("%x\n", msg.Data)
+ fmt.Printf("Compressed (%d bytes):\n", len(compressed))
+ fmt.Printf("%x\n", compressed)
+ fmt.Println()
+ }
+ }
+
+ // Store message if enabled
+ if *storeDir != "" {
+ dh.storeMessages(msg.Tag, msg.Data)
+ }
+
+ return network.OutgoingMessage{Action: network.Ignore}
+}
+
+// printStats prints the compression statistics
+func (dh *compressDumpHandler) printStats() {
+ dh.statsMutex.Lock()
+ defer dh.statsMutex.Unlock()
+
+ fmt.Println("\nCompression Statistics:")
+
+ // If using vpack, include that in the header
+ if *useVpack {
+ fmt.Println("Using vpack compression library for AgreementVote messages")
+ }
+
+ fmt.Println("Tag Messages Original % of Total Compressed Ratio CtxBytes CtxRatio WindowSize")
+ fmt.Println("----- ---------- ------------ ---------- ------------ -------- ------------ -------- ----------")
+
+ // Calculate total original bytes first
+ var totalOrig, totalComp, totalCtx uint64
+ for tag := range dh.stats {
+ stats := dh.stats[tag]
+ stats.mu.Lock()
+ totalOrig += stats.originalBytes
+ stats.mu.Unlock()
+ }
+
+ // Get all tags and sort them
+ tags := make([]protocol.Tag, 0, len(dh.stats))
+ for tag := range dh.stats {
+ tags = append(tags, tag)
+ }
+ sort.Slice(tags, func(i, j int) bool {
+ return string(tags[i]) < string(tags[j])
+ })
+ for _, tag := range tags {
+ stats := dh.stats[protocol.Tag(tag)]
+ stats.mu.Lock()
+ var reduction float64
+ if stats.originalBytes > 0 {
+ reduction = (1.0 - float64(stats.compressedBytes)/float64(stats.originalBytes)) * 100
+ }
+ ctxReduction := 0.0
+ if stats.originalBytes > 0 {
+ ctxReduction = (1.0 - float64(stats.contextBytes)/float64(stats.originalBytes)) * 100
+ }
+ windowSize := *compressionWindowSize
+ dh.tagContextsMu.Lock()
+ if tagWindowSize, ok := dh.tagContexts[protocol.Tag(tag)]; ok {
+ windowSize = tagWindowSize
+ }
+ dh.tagContextsMu.Unlock()
+
+ // Calculate percentage of total traffic
+ pctOfTotal := 0.0
+ if totalOrig > 0 {
+ pctOfTotal = float64(stats.originalBytes) / float64(totalOrig) * 100.0
+ }
+
+ // Add vpack indicator for AgreementVote messages when using vpack
+ tagDisplay := string(tag)
+ if *useVpack && tag == protocol.AgreementVoteTag {
+ tagDisplay = string(tag) + "*" // Add asterisk to indicate vpack compression
+ }
+
+ fmt.Printf("%-5s %10d %12d %8.1f%% %12d %7.1f%% %12d %7.1f%% %10d\n",
+ tagDisplay,
+ stats.messageCount,
+ stats.originalBytes,
+ pctOfTotal,
+ stats.compressedBytes,
+ reduction,
+ stats.contextBytes,
+ ctxReduction,
+ windowSize)
+ totalComp += stats.compressedBytes
+ totalCtx += stats.contextBytes
+ stats.mu.Unlock()
+ }
+
+ if totalOrig > 0 {
+ fmt.Println("----- ---------- ------------ ---------- ------------ -------- ------------ -------- ----------")
+ reduction := (1.0 - float64(totalComp)/float64(totalOrig)) * 100
+ ctxReduction := (1.0 - float64(totalCtx)/float64(totalOrig)) * 100
+ fmt.Printf("%-5s %10s %12d %8.1f%% %12d %7.1f%% %12d %7.1f%% %10s\n",
+ "TOTAL", "-", totalOrig, 100.0, totalComp, reduction, totalCtx, ctxReduction, "-")
+
+ // Add a legend for vpack if enabled
+ if *useVpack {
+ fmt.Println("\n* AV tag uses vpack compression optimized for AgreementVote messages")
+ }
+ }
+}
+
+// initCompressDumpHandler initializes a compressDumpHandler
+func initCompressDumpHandler() *compressDumpHandler {
+ dh := initDumpHandler() // Start with base handler
+
+ cdh := &compressDumpHandler{
+ dumpHandler: dh,
+ stats: make(map[protocol.Tag]*tagStats),
+ contexts: make(map[string]*CompressionContext),
+ tagContexts: make(map[protocol.Tag]int),
+ tagGroups: make(map[protocol.Tag]string),
+ }
+
+ // Initialize vpack encoder/decoder if -useVpack flag is enabled
+ if *useVpack {
+ fmt.Println("Using vpack compression library")
+ cdh.vpackEncoder = vpack.NewStatelessEncoder()
+ cdh.vpackDecoder = vpack.NewStatelessDecoder()
+ }
+
+ // Initialize dictionary-based compression if a dictionary file is provided
+ if *dictionaryFile != "" && !*useVpack { // Don't use dictionary with vpack
+ fmt.Printf("Using dictionary-based compression with %s\n", *dictionaryFile)
+ var err error
+ cdh.dict, err = os.ReadFile(*dictionaryFile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error reading dictionary file: %v\n", err)
+ os.Exit(1)
+ }
+
+ // Create a bulk processor with the dictionary
+ cdh.compressor, err = zstd.NewBulkProcessor(cdh.dict, *compressionLevel)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error creating dictionary processor: %v\n", err)
+ os.Exit(1)
+ }
+
+ // If using gozstd, create the reusable dictionary for it too
+ if *useGozstd {
+ cdh.cdict, err = gozstd.NewCDictLevel(cdh.dict, *compressionLevel)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error creating gozstd compression dictionary: %v\n", err)
+ os.Exit(1)
+ }
+ }
+ }
+
+ return cdh
+}
+
+func parseContextConfig(config string) (map[protocol.Tag]int, map[protocol.Tag]string, error) {
+ if config == "" {
+ return nil, nil, nil
+ }
+
+ result := make(map[protocol.Tag]int) // Maps tag to window size
+ groups := make(map[protocol.Tag]string) // Maps tag to group name
+ groupNum := 0
+
+ configGroups := strings.Split(config, ";")
+
+ for _, group := range configGroups {
+ parts := strings.Split(group, ":")
+ if len(parts) != 2 {
+ return nil, nil, fmt.Errorf("invalid context config format: %s", group)
+ }
+
+ tagList := strings.Split(parts[0], ",")
+ windowSize, err := strconv.Atoi(parts[1])
+ if err != nil {
+ return nil, nil, fmt.Errorf("invalid window size %s: %v", parts[1], err)
+ }
+
+ // Validate window size
+ if !isPowerOfTwo(windowSize) {
+ return nil, nil, fmt.Errorf("window size must be a power of 2: %d", windowSize)
+ }
+
+ if *useGozstd {
+ // Calculate window log from window size
+ windowLog := 0
+ size := windowSize
+ for size > 1 {
+ size >>= 1
+ windowLog++
+ }
+
+ // Validate against gozstd constraints
+ if windowLog < gozstd.WindowLogMin || windowLog > gozstd.WindowLogMax64 {
+ return nil, nil, fmt.Errorf("for gozstd, window size must be between %d and %d bytes: %d",
+ 1< kzstd.MaxWindowSize {
+ return nil, nil, fmt.Errorf("for klauspost, window size must be between %d and %d: %d",
+ kzstd.MinWindowSize, kzstd.MaxWindowSize, windowSize)
+ }
+ }
+
+ // Create a group name for this set of tags
+ groupName := fmt.Sprintf("group%d", groupNum)
+ groupNum++
+
+ // Add each tag with the specified window size and group
+ for _, tag := range tagList {
+ tagStr := protocol.Tag(tag)
+ result[tagStr] = windowSize
+ groups[tagStr] = groupName
+ }
+ }
+
+ return result, groups, nil
+}
+
+// configureCompression sets up tag-specific contexts for the compressDumpHandler
+func configureCompression(dh *compressDumpHandler) error {
+ // Configure tag-specific contexts if provided
+ if *contextConfig != "" {
+ tagContexts, tagGroups, err := parseContextConfig(*contextConfig)
+ if err != nil {
+ return fmt.Errorf("error parsing context configuration: %v", err)
+ }
+ dh.tagContexts = tagContexts
+ dh.tagGroups = tagGroups
+
+ // Print a more user-friendly summary of the configuration
+ libraryName := "klauspost/zstd (Go)"
+ if *useGozstd {
+ libraryName = "valyala/gozstd (C)"
+ }
+ fmt.Printf("Configured compression contexts using %s library:\n", libraryName)
+
+ // Group tags by their group name for shared contexts
+ groupedTags := make(map[string][]string)
+ groupSizes := make(map[string]int)
+ for tag, group := range tagGroups {
+ groupedTags[group] = append(groupedTags[group], string(tag))
+ groupSizes[group] = tagContexts[tag]
+ }
+
+ // Print each context group
+ for group, tags := range groupedTags {
+ fmt.Printf(" Context %s: tags [%s] with window size %d bytes\n",
+ group, strings.Join(tags, ","), groupSizes[group])
+ }
+ }
+ return nil
+}
diff --git a/tools/debug/algodump/compress_bench_test.go b/tools/debug/algodump/compress_bench_test.go
new file mode 100644
index 0000000000..f1ce7c5ece
--- /dev/null
+++ b/tools/debug/algodump/compress_bench_test.go
@@ -0,0 +1,884 @@
+// Copyright (C) 2019-2026 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 main
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/hex"
+ "flag"
+ "fmt"
+ "maps"
+ "os"
+ "path/filepath"
+ "runtime"
+ "slices"
+ "strconv"
+ "strings"
+ "testing"
+
+ "github.com/DataDog/zstd"
+ "github.com/algorand/go-algorand/network/vpack"
+ "github.com/algorand/go-algorand/protocol"
+ kzstd "github.com/klauspost/compress/zstd"
+ "github.com/valyala/gozstd"
+)
+
+// testCorpus holds all the test data loaded from message files
+type testCorpus struct {
+ messages []StoredMessage
+ total int64
+}
+
+// Global cache for test corpus
+var cachedCorpus *testCorpus
+
+func TestVPackMemoryUsage(t *testing.T) {
+ windowSizes := []uint{256, 512, 1024, 2048, 4096, 8192}
+
+ t.Log("Measuring VPack StatefulEncoder/Decoder memory usage:")
+ t.Log("Memory breakdown per direction (encoder OR decoder):")
+ t.Log(" - sndTable: (N/2 buckets) Ă— (2 slots) Ă— (32 bytes/slot) + (N/16 MRU bytes)")
+ t.Log(" - pkTable: (N/2 buckets) Ă— (2 slots) Ă— (96 bytes/slot) + (N/16 MRU bytes)")
+ t.Log(" - pk2Table: (N/2 buckets) Ă— (2 slots) Ă— (96 bytes/slot) + (N/16 MRU bytes)")
+ t.Log(" - Fixed overhead (propWindow + pointers + lastRnd) = 800 bytes")
+ t.Log(" Per direction: (N Ă— 224) + 800 bytes")
+ t.Log(" Per bidirectional connection: 2 Ă— [(N Ă— 224) + 800] bytes")
+ t.Log("")
+ t.Log("Window Size | Measured | Expected | Buckets | Ratio | Per-Connection")
+ t.Log("----------- | -------- | -------- | ------- | ----- | --------------")
+
+ for _, windowSize := range windowSizes {
+ var m1, m2 runtime.MemStats
+
+ // Force GC and get baseline
+ runtime.GC()
+ runtime.ReadMemStats(&m1)
+
+ // Create encoder
+ enc, err := vpack.NewStatefulEncoder(windowSize)
+ if err != nil {
+ t.Fatalf("Failed to create encoder with size %d: %v", windowSize, err)
+ }
+
+ // Measure after creation
+ runtime.ReadMemStats(&m2)
+
+ // Calculate actual memory increase
+ actualBytes := int64(m2.HeapAlloc - m1.HeapAlloc)
+ expectedBytes := int64(windowSize)*224 + 800 // (N Ă— 224) + fixed overhead per direction
+ bidirectionalBytes := expectedBytes * 2 // Both encoder and decoder
+ numBuckets := windowSize / 2
+ ratio := float64(actualBytes) / float64(expectedBytes)
+
+ t.Logf("%11d | %8s | %8s | %7d | %.2f | %s",
+ windowSize,
+ formatBytes(actualBytes),
+ formatBytes(expectedBytes),
+ numBuckets,
+ ratio,
+ formatBytes(bidirectionalBytes))
+
+ // Keep encoder alive
+ _ = enc
+ }
+}
+
+func formatBytes(b int64) string {
+ if b < 1024 {
+ return fmt.Sprintf("%d B", b)
+ } else if b < 1024*1024 {
+ return fmt.Sprintf("%.1f KB", float64(b)/1024)
+ }
+ return fmt.Sprintf("%.1f MB", float64(b)/(1024*1024))
+}
+
+func TestPrintTestCorpus(t *testing.T) {
+ corpus := loadTestCorpus(t)
+ t.Logf("Loaded %d messages (%d bytes)", len(corpus.messages), corpus.total)
+ cnt := 0
+ var origBytes, compBytes int64
+ enc := vpack.NewStatelessEncoder()
+ dec := vpack.NewStatelessDecoder()
+ for i, msg := range corpus.messages {
+ if msg.Tag != "AV" {
+ continue
+ }
+ cnt++
+ encBytes, err := enc.CompressVote(nil, msg.Data)
+ if err != nil {
+ t.Logf("parseVoteMsgpack: %v", err)
+ }
+ decBytes, err := dec.DecompressVote(nil, encBytes)
+ if err != nil {
+ t.Fatalf("DecompressSimple: %v", err)
+ }
+ if !bytes.Equal(decBytes, msg.Data) {
+ t.Logf("msgbuf: %s", hex.EncodeToString(decBytes))
+ t.Logf("msgDat: %s", hex.EncodeToString(msg.Data))
+ b64data := base64.StdEncoding.EncodeToString(msg.Data)
+ t.Logf("Message %d len %d: tag %s: %s", i, len(msg.Data), msg.Tag, b64data)
+ t.Fatalf("Message %d: mismatch: %d vs %d bytes", i, len(encBytes), len(msg.Data))
+ }
+ origBytes += int64(len(msg.Data))
+ compBytes += int64(len(encBytes))
+ }
+ t.Logf("Processed %d messages", cnt)
+ t.Logf("Total bytes: %d, compressed: %d, ratio: %0.4f", origBytes, compBytes, (1.0 - float64(compBytes)/float64(origBytes)))
+}
+
+// filterMessages returns a slice of messages filtered by criteria.
+// If onlyAV is true, only messages with Tag "AV" will be included.
+// The function will also check if the filtered list is empty and call b.Fatal if it is.
+func filterMessages(b *testing.B, corpus *testCorpus, onlyAV bool) []StoredMessage {
+ var filtered []StoredMessage
+ for _, msg := range corpus.messages {
+ // Filter by tag if needed
+ if onlyAV && msg.Tag != "AV" {
+ continue
+ }
+
+ filtered = append(filtered, msg)
+ }
+
+ // Report an error if no messages pass the filter
+ if len(filtered) == 0 {
+ b.Fatal("No messages to benchmark")
+ }
+
+ return filtered
+}
+
+type filterOption struct {
+ name string
+ onlyAV bool
+}
+
+var defaultFilterOptions = []filterOption{
+ {name: "all", onlyAV: false},
+ {name: "av", onlyAV: true},
+}
+
+func parseFilterOptions(key string) []filterOption {
+ val := strings.TrimSpace(os.Getenv(key))
+ var opts []filterOption
+ for _, part := range strings.Split(val, ",") {
+ switch strings.ToLower(strings.TrimSpace(part)) {
+ case "all":
+ opts = append(opts, filterOption{name: "all", onlyAV: false})
+ case "av":
+ opts = append(opts, filterOption{name: "av", onlyAV: true})
+ }
+ }
+ if len(opts) > 0 {
+ return opts
+ }
+ return defaultFilterOptions
+}
+
+func parseIntListFromEnv(key string, defaults []int) []int {
+ val := strings.TrimSpace(os.Getenv(key))
+ var parsed []int
+ for _, part := range strings.Split(val, ",") {
+ numStr := strings.TrimSpace(part)
+ if numStr == "" {
+ continue
+ }
+ num, err := strconv.Atoi(numStr)
+ if err != nil {
+ continue
+ }
+ parsed = append(parsed, num)
+ }
+ if len(parsed) > 0 {
+ return parsed
+ }
+ return defaults
+}
+
+type simpleCompressor func(dst, src []byte) ([]byte, error)
+
+type simpleCompressorBuilder func(level int) (simpleCompressor, func(), error)
+
+func runSimpleCompressionMatrix(b *testing.B, benchName string, corpus *testCorpus, levels []int, filters []filterOption, build simpleCompressorBuilder) {
+ for _, opt := range filters {
+ filtered := filterMessages(b, corpus, opt.onlyAV)
+ for _, level := range levels {
+ opt := opt
+ b.Run(fmt.Sprintf("%s/level=%d/%s", benchName, level, opt.name), func(b *testing.B) {
+ compress, cleanup, err := build(level)
+ if err != nil {
+ b.Fatalf("setup failed: %v", err)
+ }
+ if cleanup != nil {
+ defer cleanup()
+ }
+ runCompressionLoop(b, filtered, compress)
+ })
+ }
+ }
+}
+
+func runCompressionLoop(b *testing.B, msgs []StoredMessage, compress simpleCompressor) {
+ if len(msgs) == 0 {
+ b.Fatal("no messages to benchmark")
+ }
+ compressed := make([]byte, 0, 4096)
+ var totalCompressed int64
+ var origBytes int64
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ msg := msgs[i%len(msgs)]
+ var err error
+ compressed, err = compress(compressed[:0], msg.Data)
+ if err != nil {
+ b.Fatalf("compression failed: %v", err)
+ }
+ totalCompressed += int64(len(compressed))
+ origBytes += int64(len(msg.Data))
+ }
+ b.StopTimer()
+ if totalCompressed == 0 {
+ b.Fatalf("compression produced zero bytes")
+ }
+ if b.N > 0 {
+ perIteration := origBytes / int64(b.N)
+ b.SetBytes(perIteration)
+ }
+ ratio := float64(origBytes) / float64(totalCompressed)
+ reduction := 100 - float64(totalCompressed)/float64(origBytes)*100
+ b.ReportMetric(ratio, "ratio")
+ b.ReportMetric(reduction, "%smaller")
+}
+
+type simpleDecompressor func(dst, src []byte) ([]byte, error)
+
+type decompressionSetup func(level int, msgs []StoredMessage) ([][]byte, simpleDecompressor, func(), error)
+
+func runSimpleDecompressionMatrix(b *testing.B, benchName string, corpus *testCorpus, levels []int, filters []filterOption, setup decompressionSetup) {
+ for _, opt := range filters {
+ filtered := filterMessages(b, corpus, opt.onlyAV)
+ for _, level := range levels {
+ opt := opt
+ b.Run(fmt.Sprintf("%s/level=%d/%s", benchName, level, opt.name), func(b *testing.B) {
+ compressed, decompress, cleanup, err := setup(level, filtered)
+ if err != nil {
+ b.Fatalf("setup failed: %v", err)
+ }
+ if cleanup != nil {
+ defer cleanup()
+ }
+ runDecompressionLoop(b, compressed, decompress)
+ })
+ }
+ }
+}
+
+func runDecompressionLoop(b *testing.B, compressed [][]byte, decompress simpleDecompressor) {
+ if len(compressed) == 0 {
+ b.Fatal("no compressed data to benchmark")
+ }
+ decompressed := make([]byte, 0, 4096)
+ var totalCompressed int64
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ block := compressed[i%len(compressed)]
+ var err error
+ decompressed, err = decompress(decompressed[:0], block)
+ if err != nil {
+ b.Fatalf("decompression failed: %v", err)
+ }
+ totalCompressed += int64(len(block))
+ }
+ b.StopTimer()
+ if b.N > 0 {
+ b.SetBytes(totalCompressed / int64(b.N))
+ }
+}
+
+type levelWindow struct {
+ level int
+ window int
+}
+
+func parseLevelWindows(key string, defaults []levelWindow) []levelWindow {
+ val := strings.TrimSpace(os.Getenv(key))
+ var result []levelWindow
+ for _, part := range strings.Split(val, ",") {
+ fields := strings.Split(part, ":")
+ if len(fields) != 2 {
+ continue
+ }
+ level, err1 := strconv.Atoi(strings.TrimSpace(fields[0]))
+ window, err2 := strconv.Atoi(strings.TrimSpace(fields[1]))
+ if err1 != nil || err2 != nil {
+ continue
+ }
+ result = append(result, levelWindow{level: level, window: window})
+ }
+ if len(result) > 0 {
+ return result
+ }
+ return defaults
+}
+
+var (
+ // Default compression levels for klauspost benchmarks
+ defaultKlauspostLevels = []int{1, 3}
+ // Default compression levels for zstd benchmarks (gozstd and datadog)
+ defaultZstdLevels = []int{1, 3, 7, 11}
+
+ // Default windowLog configurations for gozstd benchmarks
+ defaultGozstdWindowLog = []levelWindow{
+ {level: 1, window: 15},
+ {level: 1, window: 18},
+ {level: 1, window: 20},
+ {level: 3, window: 15},
+ {level: 3, window: 18},
+ {level: 3, window: 20},
+ {level: 7, window: 18},
+ {level: 11, window: 18},
+ }
+ // Default windowLog configurations for klauspost benchmarks
+ defaultKlauspostWindowLog = []levelWindow{
+ {level: 1, window: 12},
+ {level: 1, window: 15},
+ {level: 1, window: 18},
+ {level: 1, window: 20},
+ {level: 2, window: 15},
+ {level: 2, window: 18},
+ {level: 2, window: 20},
+ {level: 3, window: 18},
+ {level: 3, window: 20},
+ }
+)
+
+func loadTestCorpus(t testing.TB) *testCorpus {
+ // If we already have a cached corpus, return it without reloading
+ if cachedCorpus != nil {
+ return cachedCorpus
+ }
+
+ // Default directories to scan
+ directories := []string{"./messages"}
+
+ // If environment variable is set, use it to override defaults
+ if customDirsSetting := os.Getenv("ALGODUMP_TEST_MESSAGES"); customDirsSetting != "" {
+ directories = strings.Split(customDirsSetting, ",")
+ }
+
+ var corpus testCorpus
+ var totalFiles int
+ var dirCounts = make(map[string]int)
+ // Track messages per tag
+ tagCounts := make(map[protocol.Tag]int)
+
+ // Process each directory
+ for _, dir := range directories {
+ entries, err := os.ReadDir(dir)
+ if err != nil {
+ // Just log an error and continue with other directories
+ t.Logf("Warning: failed to read directory %s: %v", dir, err)
+ continue
+ }
+
+ dirMessageCount := 0
+ for _, entry := range entries {
+ if !entry.IsDir() && strings.HasPrefix(entry.Name(), "messages-") {
+ path := filepath.Join(dir, entry.Name())
+ data, err := os.ReadFile(path)
+ if err != nil {
+ t.Fatalf("failed to read test data: %v", err)
+ }
+ var messages []StoredMessage
+ err = protocol.DecodeReflect(data, &messages)
+ if err != nil {
+ t.Fatalf("failed to decode test data: %v", err)
+ }
+
+ // Count messages from this file
+ dirMessageCount += len(messages)
+ totalFiles++
+
+ // Calculate total bytes and count by tag
+ for _, msg := range messages {
+ corpus.total += int64(len(msg.Data))
+ tagCounts[msg.Tag]++
+ }
+
+ // Add messages to corpus
+ corpus.messages = append(corpus.messages, messages...)
+ }
+ }
+
+ // Store count of messages from this directory
+ dirCounts[dir] = dirMessageCount
+ }
+
+ // Print loading statistics (only happens once since we cache the corpus)
+ // Only print if verbose mode is enabled via GO_TEST_VERBOSE=1
+ if vFlag := flag.Lookup("test.v"); vFlag != nil && vFlag.Value.String() == "true" {
+ t.Logf("Loaded %d messages (%.2f MB) from %d files across %d directories:",
+ len(corpus.messages),
+ float64(corpus.total)/1024/1024,
+ totalFiles,
+ len(dirCounts))
+
+ // Print per-directory counts
+ for dir, count := range dirCounts {
+ if count > 0 {
+ t.Logf(" - %s: %d messages", dir, count)
+ }
+ }
+
+ // Print message counts by tag
+ t.Log("Messages by tag:")
+
+ for _, tagStr := range slices.Sorted(maps.Keys(tagCounts)) {
+ tag := protocol.Tag(tagStr)
+ t.Logf(" - %s: %d messages", tagStr, tagCounts[tag])
+ }
+ }
+
+ if len(corpus.messages) == 0 {
+ t.Skip("no message files found in any test directory")
+ }
+
+ // Cache the corpus for future calls
+ cachedCorpus = &corpus
+ return cachedCorpus
+}
+
+// BenchmarkVPackCompression benchmarks stateless vpack compression
+func BenchmarkVPackCompression(b *testing.B) {
+ corpus := loadTestCorpus(b)
+
+ // Filter messages to only include AV votes
+ filtered := filterMessages(b, corpus, true)
+
+ enc := vpack.NewStatelessEncoder()
+ compressed := make([]byte, 0, 4096)
+
+ b.ResetTimer()
+ var totalCompressed int64
+ var origBytes int64
+ for i := 0; i < b.N; i++ {
+ // Process one message per iteration, cycling through messages
+ msg := filtered[i%len(filtered)]
+
+ var err error
+ compressed, err = enc.CompressVote(compressed, msg.Data)
+ if err != nil {
+ b.Fatalf("CompressVote failed: %v", err)
+ }
+ totalCompressed += int64(len(compressed))
+ origBytes += int64(len(msg.Data))
+ }
+ b.StopTimer()
+
+ b.ReportMetric(float64(origBytes)/float64(totalCompressed), "ratio")
+ b.ReportMetric(100-float64(totalCompressed)/float64(origBytes)*100, "%smaller")
+ b.SetBytes(origBytes / int64(b.N))
+}
+
+// BenchmarkVPackDecompression benchmarks stateless vpack decompression
+func BenchmarkVPackDecompression(b *testing.B) {
+ corpus := loadTestCorpus(b)
+
+ // First compress all AV messages to have compressed data for benchmark
+ filtered := filterMessages(b, corpus, true)
+ compressedData := make([][]byte, 0, len(filtered))
+ var totalDecompressed int64
+
+ enc := vpack.NewStatelessEncoder()
+
+ // Pre-compress the messages
+ for _, msg := range filtered {
+ encBytes, err := enc.CompressVote(nil, msg.Data)
+ if err != nil {
+ b.Fatalf("CompressVote failed during setup: %v", err)
+ }
+ compressedData = append(compressedData, encBytes)
+ }
+
+ if len(compressedData) == 0 {
+ b.Fatal("No compressed data to benchmark")
+ }
+
+ b.ResetTimer()
+ decompressed := make([]byte, 0, 1024)
+ dec := vpack.NewStatelessDecoder()
+ for i := 0; i < b.N; i++ {
+ // Process one compressed message per iteration, cycling through compressedData
+ compressed := compressedData[i%len(compressedData)]
+
+ decompressed, err := dec.DecompressVote(decompressed[:0], compressed)
+ if err != nil {
+ b.Fatalf("DecompressSimple failed: %v", err)
+ }
+ totalDecompressed += int64(len(decompressed))
+ }
+ b.StopTimer()
+
+ b.SetBytes(totalDecompressed / int64(b.N))
+}
+
+// benchmarkGozstdWindow benchmarks the valyala/gozstd implementation
+// with a specific window size (using WriterParams)
+func benchmarkGozstdWindow(b *testing.B, level int, windowLog int) {
+ corpus := loadTestCorpus(b)
+
+ filtered := filterMessages(b, corpus, false)
+
+ // Create parameters with the specified window size
+ params := &gozstd.WriterParams{
+ CompressionLevel: level,
+ WindowLog: windowLog,
+ }
+
+ // Create a buffer to hold the compressed data that will be reused
+ var buf bytes.Buffer
+
+ // Create a writer with our window size parameters that will be reused
+ zw := gozstd.NewWriterParams(&buf, params)
+ defer zw.Release()
+
+ compress := func(dst, src []byte) ([]byte, error) {
+ buf.Reset()
+ if _, err := zw.Write(src); err != nil {
+ return nil, err
+ }
+ if err := zw.Flush(); err != nil {
+ return nil, err
+ }
+ return append(dst[:0], buf.Bytes()...), nil
+ }
+ runCompressionLoop(b, filtered, compress)
+}
+
+// benchmarkKlauspostWindow benchmarks the Klauspost zstd implementation
+// with specific window size (one encoder for all messages, resetting window after each)
+func benchmarkKlauspostWindow(b *testing.B, level int, windowLog int) {
+ corpus := loadTestCorpus(b)
+
+ filtered := filterMessages(b, corpus, false)
+
+ windowSize := 1 << windowLog
+ enc, err := kzstd.NewWriter(nil, kzstd.WithEncoderLevel(kzstd.EncoderLevel(level)),
+ kzstd.WithWindowSize(windowSize))
+ if err != nil {
+ b.Fatal(err)
+ }
+ defer enc.Close()
+
+ compress := func(dst, src []byte) ([]byte, error) {
+ return enc.EncodeAll(src, dst[:0]), nil
+ }
+ runCompressionLoop(b, filtered, compress)
+}
+
+// benchmarkKlauspostStream benchmarks the Klauspost zstd implementation
+// with a streaming approach (accumulating context across messages)
+func benchmarkKlauspostStream(b *testing.B, level int, windowLog int) {
+ corpus := loadTestCorpus(b)
+
+ filtered := filterMessages(b, corpus, false)
+
+ windowSize := 1 << windowLog
+ var buf bytes.Buffer
+ enc, err := kzstd.NewWriter(&buf,
+ kzstd.WithEncoderLevel(kzstd.EncoderLevel(level)),
+ kzstd.WithWindowSize(windowSize))
+ if err != nil {
+ b.Fatal(err)
+ }
+ defer enc.Close()
+
+ compress := func(dst, src []byte) ([]byte, error) {
+ buf.Reset()
+ if _, err := enc.Write(src); err != nil {
+ return nil, err
+ }
+ if err := enc.Flush(); err != nil {
+ return nil, err
+ }
+ return append(dst[:0], buf.Bytes()...), nil
+ }
+ runCompressionLoop(b, filtered, compress)
+}
+
+func benchmarkVPackDynamicHelper(b *testing.B, windowSize int) {
+ corpus := loadTestCorpus(b)
+ filtered := filterMessages(b, corpus, true)
+
+ stEnc := vpack.NewStatelessEncoder()
+ dynEnc, err := vpack.NewStatefulEncoder(uint(windowSize))
+ if err != nil {
+ b.Fatalf("Failed to create StatefulEncoder: %v", err)
+ }
+
+ statelessBuf := make([]byte, 0, 4096)
+ compressed := make([]byte, 0, 4096)
+ var statelessTotalSize, statefulTotalSize int64
+
+ b.ResetTimer()
+ var totalCompressed int64
+ var origBytes int64
+ for i := 0; i < b.N; i++ {
+ msg := filtered[i%len(filtered)]
+ statelessBuf, err = stEnc.CompressVote(statelessBuf[:0], msg.Data)
+ if err != nil {
+ b.Fatalf("StatelessEncoder failed: %v", err)
+ }
+ statelessTotalSize += int64(len(statelessBuf))
+
+ compressed, err = dynEnc.Compress(compressed[:0], statelessBuf)
+ if err != nil {
+ b.Fatalf("StatefulEncoder failed: %v", err)
+ }
+ statefulTotalSize += int64(len(compressed))
+ totalCompressed += int64(len(compressed))
+ origBytes += int64(len(msg.Data))
+ }
+ b.StopTimer()
+
+ b.ReportMetric(float64(origBytes)/float64(totalCompressed), "ratio")
+ b.ReportMetric(100-float64(totalCompressed)/float64(origBytes)*100, "%smaller")
+ b.SetBytes(origBytes / int64(b.N))
+
+ if statelessTotalSize > 0 && statefulTotalSize > 0 {
+ b.ReportMetric(float64(statelessTotalSize)/float64(statefulTotalSize), "addl_ratio")
+ b.ReportMetric((1.0-float64(statefulTotalSize)/float64(statelessTotalSize))*100, "%addl_smaller")
+ }
+}
+
+// BenchmarkVPackDynamicCompression benchmarks the stateful vpack compression implementation
+// This uses the two-layer compression: StatelessEncoder → StatefulEncoder
+func BenchmarkVPackDynamicCompression(b *testing.B) {
+ windowSizes := parseIntListFromEnv("ALGODUMP_VPACK_WINDOWS", []int{1024})
+ for _, windowSize := range windowSizes {
+ b.Run(fmt.Sprintf("window=%d", windowSize), func(b *testing.B) {
+ benchmarkVPackDynamicHelper(b, windowSize)
+ })
+ }
+}
+
+// BenchmarkVPackDynamicDecompression benchmarks the stateful vpack decompression implementation
+// This uses the two-layer decompression: StatefulDecoder → StatelessDecoder
+func BenchmarkVPackDynamicDecompression(b *testing.B) {
+ corpus := loadTestCorpus(b)
+
+ // First compress all AV messages to have compressed data for benchmark
+ filtered := filterMessages(b, corpus, true)
+ compressedData := make([][]byte, 0, len(filtered))
+
+ // Create both encoder types for pre-compression
+ stEnc := vpack.NewStatelessEncoder()
+ dynEnc, err := vpack.NewStatefulEncoder(1024)
+ if err != nil {
+ b.Fatalf("Failed to create StatefulEncoder: %v", err)
+ }
+
+ // Pre-compress the messages through both layers
+ for _, msg := range filtered {
+ // First layer: stateless
+ stBuf, err := stEnc.CompressVote(nil, msg.Data)
+ if err != nil {
+ b.Fatalf("StatelessEncoder failed during setup: %v", err)
+ }
+
+ // Second layer: stateful
+ encBytes, err := dynEnc.Compress(nil, stBuf)
+ if err != nil {
+ b.Fatalf("StatefulEncoder failed during setup: %v", err)
+ }
+
+ compressedData = append(compressedData, encBytes)
+ }
+
+ if len(compressedData) == 0 {
+ b.Fatal("No compressed data to benchmark")
+ }
+
+ b.ResetTimer()
+ var totalDecompressed int64
+
+ // Create both decoder types for benchmark
+ dynDec, err := vpack.NewStatefulDecoder(1024)
+ if err != nil {
+ b.Fatalf("Failed to create StatefulDecoder: %v", err)
+ }
+ stDec := vpack.NewStatelessDecoder()
+
+ // Intermediate and final buffers
+ statelessBuf := make([]byte, 0, 1024)
+ decompressed := make([]byte, 0, 1024)
+
+ for i := 0; i < b.N; i++ {
+ // Process one compressed message per iteration, cycling through compressedData
+ compressed := compressedData[i%len(compressedData)]
+
+ // First layer: stateful decompression
+ var err error
+ statelessBuf, err = dynDec.Decompress(statelessBuf[:0], compressed)
+ if err != nil {
+ b.Fatalf("StatefulDecoder failed: %v", err)
+ }
+
+ // Second layer: stateless decompression
+ decompressed, err = stDec.DecompressVote(decompressed[:0], statelessBuf)
+ if err != nil {
+ b.Fatalf("StatelessDecoder failed: %v", err)
+ }
+
+ totalDecompressed += int64(len(decompressed))
+ }
+ b.StopTimer()
+
+ b.SetBytes(totalDecompressed / int64(b.N))
+}
+
+func BenchmarkGozstdSimple(b *testing.B) {
+ corpus := loadTestCorpus(b)
+ levels := parseIntListFromEnv("ALGODUMP_GOZSTD_LEVELS", defaultZstdLevels)
+ filters := parseFilterOptions("ALGODUMP_BENCH_FILTERS")
+ runSimpleCompressionMatrix(b, "gozstd/simple", corpus, levels, filters, func(level int) (simpleCompressor, func(), error) {
+ return func(dst, src []byte) ([]byte, error) {
+ return gozstd.CompressLevel(dst[:0], src, level), nil
+ }, nil, nil
+ })
+}
+
+func BenchmarkZstdSimple(b *testing.B) {
+ corpus := loadTestCorpus(b)
+ levels := parseIntListFromEnv("ALGODUMP_ZSTD_LEVELS", defaultZstdLevels)
+ filters := parseFilterOptions("ALGODUMP_BENCH_FILTERS")
+ runSimpleCompressionMatrix(b, "zstd/simple", corpus, levels, filters, func(level int) (simpleCompressor, func(), error) {
+ return func(dst, src []byte) ([]byte, error) {
+ return zstd.CompressLevel(dst[:0], src, level)
+ }, nil, nil
+ })
+}
+
+func BenchmarkKlauspostSimple(b *testing.B) {
+ corpus := loadTestCorpus(b)
+ levels := parseIntListFromEnv("ALGODUMP_KLAUSPOST_LEVELS", defaultKlauspostLevels)
+ filters := parseFilterOptions("ALGODUMP_BENCH_FILTERS")
+ runSimpleCompressionMatrix(b, "klauspost/simple", corpus, levels, filters, func(level int) (simpleCompressor, func(), error) {
+ enc, err := kzstd.NewWriter(nil, kzstd.WithEncoderLevel(kzstd.EncoderLevel(level)))
+ if err != nil {
+ return nil, nil, err
+ }
+ compress := func(dst, src []byte) ([]byte, error) {
+ return enc.EncodeAll(src, dst[:0]), nil
+ }
+ cleanup := func() { enc.Close() }
+ return compress, cleanup, nil
+ })
+}
+
+func BenchmarkGozstdDecompress(b *testing.B) {
+ corpus := loadTestCorpus(b)
+ levels := parseIntListFromEnv("ALGODUMP_GOZSTD_LEVELS", defaultZstdLevels)
+ filters := parseFilterOptions("ALGODUMP_BENCH_FILTERS")
+ runSimpleDecompressionMatrix(b, "gozstd/decompress", corpus, levels, filters, func(level int, msgs []StoredMessage) ([][]byte, simpleDecompressor, func(), error) {
+ compressed := make([][]byte, len(msgs))
+ for i, msg := range msgs {
+ compressed[i] = gozstd.CompressLevel(nil, msg.Data, level)
+ }
+ decompress := func(dst, src []byte) ([]byte, error) {
+ return gozstd.Decompress(dst[:0], src)
+ }
+ return compressed, decompress, nil, nil
+ })
+}
+
+func BenchmarkZstdDecompress(b *testing.B) {
+ corpus := loadTestCorpus(b)
+ levels := parseIntListFromEnv("ALGODUMP_ZSTD_LEVELS", defaultZstdLevels)
+ filters := parseFilterOptions("ALGODUMP_BENCH_FILTERS")
+ runSimpleDecompressionMatrix(b, "zstd/decompress", corpus, levels, filters, func(level int, msgs []StoredMessage) ([][]byte, simpleDecompressor, func(), error) {
+ compressed := make([][]byte, len(msgs))
+ for i, msg := range msgs {
+ comp, err := zstd.CompressLevel(nil, msg.Data, level)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ compressed[i] = comp
+ }
+ decompress := func(dst, src []byte) ([]byte, error) {
+ return zstd.Decompress(dst[:0], src)
+ }
+ return compressed, decompress, nil, nil
+ })
+}
+
+func BenchmarkKlauspostDecompress(b *testing.B) {
+ corpus := loadTestCorpus(b)
+ levels := parseIntListFromEnv("ALGODUMP_KLAUSPOST_LEVELS", defaultKlauspostLevels)
+ filters := parseFilterOptions("ALGODUMP_BENCH_FILTERS")
+ runSimpleDecompressionMatrix(b, "klauspost/decompress", corpus, levels, filters, func(level int, msgs []StoredMessage) ([][]byte, simpleDecompressor, func(), error) {
+ enc, err := kzstd.NewWriter(nil, kzstd.WithEncoderLevel(kzstd.EncoderLevel(level)))
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ dec, err := kzstd.NewReader(nil)
+ if err != nil {
+ enc.Close()
+ return nil, nil, nil, err
+ }
+ compressed := make([][]byte, len(msgs))
+ for i, msg := range msgs {
+ compressed[i] = enc.EncodeAll(msg.Data, make([]byte, 0, 4096))
+ }
+ decompress := func(dst, src []byte) ([]byte, error) {
+ return dec.DecodeAll(src, dst[:0])
+ }
+ cleanup := func() {
+ enc.Close()
+ dec.Close()
+ }
+ return compressed, decompress, cleanup, nil
+ })
+}
+
+func BenchmarkGozstdWindow(b *testing.B) {
+ configs := parseLevelWindows("ALGODUMP_GOZSTD_WINDOW_LOGS", defaultGozstdWindowLog)
+ for _, cfg := range configs {
+ b.Run(fmt.Sprintf("gozstd/window/level=%d/windowLog=%d", cfg.level, cfg.window), func(b *testing.B) {
+ benchmarkGozstdWindow(b, cfg.level, cfg.window)
+ })
+ }
+}
+
+func BenchmarkKlauspostWindow(b *testing.B) {
+ configs := parseLevelWindows("ALGODUMP_KLAUSPOST_WINDOW_LOGS", defaultKlauspostWindowLog)
+ for _, cfg := range configs {
+ b.Run(fmt.Sprintf("klauspost/window/level=%d/windowLog=%d", cfg.level, cfg.window), func(b *testing.B) {
+ benchmarkKlauspostWindow(b, cfg.level, cfg.window)
+ })
+ }
+}
+
+func BenchmarkKlauspostStream(b *testing.B) {
+ configs := parseLevelWindows("ALGODUMP_KLAUSPOST_STREAM_WINDOW_LOGS", defaultKlauspostWindowLog)
+ for _, cfg := range configs {
+ b.Run(fmt.Sprintf("klauspost/stream/level=%d/windowLog=%d", cfg.level, cfg.window), func(b *testing.B) {
+ benchmarkKlauspostStream(b, cfg.level, cfg.window)
+ })
+ }
+}
diff --git a/tools/debug/algodump/go.mod b/tools/debug/algodump/go.mod
new file mode 100644
index 0000000000..4bb7552d0d
--- /dev/null
+++ b/tools/debug/algodump/go.mod
@@ -0,0 +1,165 @@
+module github.com/algorand/go-algorand/tools/debug/algodump
+
+go 1.25.0
+
+replace github.com/algorand/go-algorand => ../../..
+
+require (
+ github.com/DataDog/zstd v1.5.2
+ github.com/algorand/go-algorand v0.0.0
+ github.com/algorand/go-deadlock v0.2.5
+ github.com/klauspost/compress v1.17.11
+ github.com/valyala/gozstd v1.21.2
+)
+
+require (
+ filippo.io/edwards25519 v1.0.0 // indirect
+ github.com/algorand/falcon v0.1.0 // indirect
+ github.com/algorand/go-codec/codec v1.1.10 // indirect
+ github.com/algorand/go-sumhash v0.1.0 // indirect
+ github.com/algorand/msgp v1.1.61 // indirect
+ github.com/algorand/sortition v1.0.0 // indirect
+ github.com/algorand/websocket v1.4.6 // indirect
+ github.com/aws/aws-sdk-go v1.34.0 // indirect
+ github.com/benbjohnson/clock v1.3.5 // indirect
+ github.com/beorn7/perks v1.0.1 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/containerd/cgroups v1.1.0 // indirect
+ github.com/coreos/go-systemd/v22 v22.5.0 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
+ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
+ github.com/docker/go-units v0.5.0 // indirect
+ github.com/elastic/gosigar v0.14.3 // indirect
+ github.com/flynn/noise v1.1.0 // indirect
+ github.com/francoispqt/gojay v1.2.13 // indirect
+ github.com/go-logr/logr v1.4.2 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
+ github.com/godbus/dbus/v5 v5.1.0 // indirect
+ github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
+ github.com/google/go-cmp v0.6.0 // indirect
+ github.com/google/gopacket v1.1.19 // indirect
+ github.com/google/pprof v0.0.0-20241017200806-017d972448fc // indirect
+ github.com/google/uuid v1.6.0 // indirect
+ github.com/gorilla/mux v1.8.1 // indirect
+ github.com/gorilla/websocket v1.5.3 // indirect
+ github.com/hashicorp/errwrap v1.1.0 // indirect
+ github.com/hashicorp/go-multierror v1.1.1 // indirect
+ github.com/hashicorp/golang-lru v1.0.2 // indirect
+ github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
+ github.com/hdevalence/ed25519consensus v0.2.0 // indirect
+ github.com/huin/goupnp v1.3.0 // indirect
+ github.com/ipfs/boxo v0.24.3 // indirect
+ github.com/ipfs/go-cid v0.4.1 // indirect
+ github.com/ipfs/go-datastore v0.6.0 // indirect
+ github.com/ipfs/go-log/v2 v2.5.1 // indirect
+ github.com/ipld/go-ipld-prime v0.21.0 // indirect
+ github.com/jackpal/go-nat-pmp v1.0.2 // indirect
+ github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
+ github.com/jbenet/goprocess v0.1.4 // indirect
+ github.com/jmespath/go-jmespath v0.3.0 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
+ github.com/josharian/native v1.1.0 // indirect
+ github.com/jsimonetti/rtnetlink v1.4.2 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.8 // indirect
+ github.com/koron/go-ssdp v0.0.4 // indirect
+ github.com/libp2p/go-buffer-pool v0.1.0 // indirect
+ github.com/libp2p/go-cidranger v1.1.0 // indirect
+ github.com/libp2p/go-flow-metrics v0.2.0 // indirect
+ github.com/libp2p/go-libp2p v0.37.0 // indirect
+ github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
+ github.com/libp2p/go-libp2p-kad-dht v0.28.0 // indirect
+ github.com/libp2p/go-libp2p-kbucket v0.6.4 // indirect
+ github.com/libp2p/go-libp2p-pubsub v0.12.0 // indirect
+ github.com/libp2p/go-libp2p-record v0.2.0 // indirect
+ github.com/libp2p/go-libp2p-routing-helpers v0.7.4 // indirect
+ github.com/libp2p/go-msgio v0.3.0 // indirect
+ github.com/libp2p/go-nat v0.2.0 // indirect
+ github.com/libp2p/go-netroute v0.2.1 // indirect
+ github.com/libp2p/go-reuseport v0.4.0 // indirect
+ github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/mattn/go-sqlite3 v1.14.16 // indirect
+ github.com/mdlayher/netlink v1.7.2 // indirect
+ github.com/mdlayher/socket v0.4.1 // indirect
+ github.com/miekg/dns v1.1.62 // indirect
+ github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
+ github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
+ github.com/minio/sha256-simd v1.0.1 // indirect
+ github.com/mr-tron/base58 v1.2.0 // indirect
+ github.com/multiformats/go-base32 v0.1.0 // indirect
+ github.com/multiformats/go-base36 v0.2.0 // indirect
+ github.com/multiformats/go-multiaddr v0.13.0 // indirect
+ github.com/multiformats/go-multiaddr-dns v0.4.0 // indirect
+ github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
+ github.com/multiformats/go-multibase v0.2.0 // indirect
+ github.com/multiformats/go-multicodec v0.9.0 // indirect
+ github.com/multiformats/go-multihash v0.2.3 // indirect
+ github.com/multiformats/go-multistream v0.5.0 // indirect
+ github.com/multiformats/go-varint v0.0.7 // indirect
+ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/olivere/elastic v6.2.14+incompatible // indirect
+ github.com/onsi/ginkgo/v2 v2.20.2 // indirect
+ github.com/opencontainers/runtime-spec v1.2.0 // indirect
+ github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
+ github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe // indirect
+ github.com/pion/datachannel v1.5.9 // indirect
+ github.com/pion/dtls/v2 v2.2.12 // indirect
+ github.com/pion/ice/v2 v2.3.36 // indirect
+ github.com/pion/interceptor v0.1.39 // indirect
+ github.com/pion/logging v0.2.3 // indirect
+ github.com/pion/mdns v0.0.12 // indirect
+ github.com/pion/randutil v0.1.0 // indirect
+ github.com/pion/rtcp v1.2.15 // indirect
+ github.com/pion/rtp v1.8.18 // indirect
+ github.com/pion/sctp v1.8.33 // indirect
+ github.com/pion/sdp/v3 v3.0.9 // indirect
+ github.com/pion/srtp/v2 v2.0.20 // indirect
+ github.com/pion/stun v0.6.1 // indirect
+ github.com/pion/transport/v2 v2.2.10 // indirect
+ github.com/pion/turn/v2 v2.1.6 // indirect
+ github.com/pion/webrtc/v3 v3.3.4 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/polydawn/refmt v0.89.0 // indirect
+ github.com/prometheus/client_golang v1.20.5 // indirect
+ github.com/prometheus/client_model v0.6.1 // indirect
+ github.com/prometheus/common v0.60.0 // indirect
+ github.com/prometheus/procfs v0.15.1 // indirect
+ github.com/quic-go/qpack v0.5.1 // indirect
+ github.com/quic-go/quic-go v0.49.1 // indirect
+ github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect
+ github.com/raulk/go-watchdog v1.3.0 // indirect
+ github.com/sirupsen/logrus v1.8.3 // indirect
+ github.com/spaolacci/murmur3 v1.1.0 // indirect
+ github.com/stretchr/testify v1.10.0 // indirect
+ github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 // indirect
+ github.com/wlynxg/anet v0.0.5 // indirect
+ go.opencensus.io v0.24.0 // indirect
+ go.opentelemetry.io/otel v1.31.0 // indirect
+ go.opentelemetry.io/otel/metric v1.31.0 // indirect
+ go.opentelemetry.io/otel/trace v1.31.0 // indirect
+ go.uber.org/dig v1.18.0 // indirect
+ go.uber.org/fx v1.23.0 // indirect
+ go.uber.org/mock v0.5.0 // indirect
+ go.uber.org/multierr v1.11.0 // indirect
+ go.uber.org/zap v1.27.0 // indirect
+ golang.org/x/crypto v0.45.0 // indirect
+ golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
+ golang.org/x/mod v0.29.0 // indirect
+ golang.org/x/net v0.47.0 // indirect
+ golang.org/x/sync v0.18.0 // indirect
+ golang.org/x/sys v0.38.0 // indirect
+ golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect
+ golang.org/x/text v0.31.0 // indirect
+ golang.org/x/tools v0.38.0 // indirect
+ gonum.org/v1/gonum v0.15.0 // indirect
+ google.golang.org/protobuf v1.35.1 // indirect
+ gopkg.in/sohlich/elogrus.v3 v3.0.0-20180410122755-1fa29e2f2009 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+ lukechampine.com/blake3 v1.3.0 // indirect
+)
diff --git a/tools/debug/algodump/go.sum b/tools/debug/algodump/go.sum
new file mode 100644
index 0000000000..ac755aa94a
--- /dev/null
+++ b/tools/debug/algodump/go.sum
@@ -0,0 +1,732 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
+dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
+dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
+dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
+dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
+filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
+filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
+git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8=
+github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
+github.com/algorand/avm-abi v0.2.0 h1:bkjsG+BOEcxUcnGSALLosmltE0JZdg+ZisXKx0UDX2k=
+github.com/algorand/avm-abi v0.2.0/go.mod h1:+CgwM46dithy850bpTeHh9MC99zpn2Snirb3QTl2O/g=
+github.com/algorand/falcon v0.1.0 h1:xl832kfZ7hHG6B4p90DQynjfKFGbIUgUOnsRiMZXfAo=
+github.com/algorand/falcon v0.1.0/go.mod h1:OkQyHlGvS0kLNcIWbC21/uQcnbfwSOQm+wiqWwBG9pQ=
+github.com/algorand/go-codec/codec v1.1.10 h1:zmWYU1cp64jQVTOG8Tw8wa+k0VfwgXIPbnDfiVa+5QA=
+github.com/algorand/go-codec/codec v1.1.10/go.mod h1:YkEx5nmr/zuCeaDYOIhlDg92Lxju8tj2d2NrYqP7g7k=
+github.com/algorand/go-deadlock v0.2.5 h1:Kn3WJMn9+wK1pqJrr2+1/y3Z8p1dcftpr2Mbbl1CShw=
+github.com/algorand/go-deadlock v0.2.5/go.mod h1:z0g1kdYBhezsHoEKqYf5dVnP9dGMwOOqqxUSTCk2Oks=
+github.com/algorand/go-sumhash v0.1.0 h1:b/QRhyLuF//vOcicBIxBXYW8bERNoeLxieht/dUYpVg=
+github.com/algorand/go-sumhash v0.1.0/go.mod h1:OOe7jdDWUhLkuP1XytkK5gnLu9entAviN5DfDZh6XAc=
+github.com/algorand/msgp v1.1.61 h1:IDSCGKLIi60n6j0lHDu37GTsCo9anw49Rq4PTwsDQsQ=
+github.com/algorand/msgp v1.1.61/go.mod h1:j9sEjNKkS12H0Yhwov/3MfzhM60n3iyr81Ymzv49pu8=
+github.com/algorand/sortition v1.0.0 h1:PJiZtdSTBm4nArQrZXBnhlljHXhuyAXRJBqVWowQu3E=
+github.com/algorand/sortition v1.0.0/go.mod h1:23CZwAbTWPv0bBsq+Php/2J6Y/iXDyzlfcZyepeY5Fo=
+github.com/algorand/websocket v1.4.6 h1:I0kV4EYwatuUrKtNiwzYYgojgwh6pksDmlqntKG2Woc=
+github.com/algorand/websocket v1.4.6/go.mod h1:HJmdGzFtnlUQ4nTzZP6WrT29oGYf1t6Ybi64vROcT+M=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
+github.com/aws/aws-sdk-go v1.34.0 h1:brux2dRrlwCF5JhTL7MUT3WUwo9zfDHZZp3+g3Mvlmo=
+github.com/aws/aws-sdk-go v1.34.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
+github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
+github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
+github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
+github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
+github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU=
+github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
+github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
+github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
+github.com/cilium/ebpf v0.12.3 h1:8ht6F9MquybnY97at+VDZb3eQQr8ev79RueWeVaEcG4=
+github.com/cilium/ebpf v0.12.3/go.mod h1:TctK1ivibvI3znr66ljgi4hqOT8EYQjz1KWBfb1UVgM=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/consensys/gnark-crypto v0.18.1 h1:RyLV6UhPRoYYzaFnPQA4qK3DyuDgkTgskDdoGqFt3fI=
+github.com/consensys/gnark-crypto v0.18.1/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c=
+github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
+github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
+github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
+github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
+github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
+github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU=
+github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U=
+github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
+github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
+github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
+github.com/elastic/gosigar v0.14.3 h1:xwkKwPia+hSfg9GqrCUKYdId102m9qTJIIr7egmK/uo=
+github.com/elastic/gosigar v0.14.3/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
+github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg=
+github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
+github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
+github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
+github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
+github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
+github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
+github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
+github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
+github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
+github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
+github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
+github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
+github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
+github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20241017200806-017d972448fc h1:NGyrhhFhwvRAZg02jnYVg3GBQy0qGBKmFQJwaPmpmxs=
+github.com/google/pprof v0.0.0-20241017200806-017d972448fc/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
+github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
+github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
+github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
+github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
+github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
+github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
+github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
+github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
+github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
+github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
+github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU=
+github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo=
+github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
+github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
+github.com/ipfs/boxo v0.24.3 h1:gldDPOWdM3Rz0v5LkVLtZu7A7gFNvAlWcmxhCqlHR3c=
+github.com/ipfs/boxo v0.24.3/go.mod h1:h0DRzOY1IBFDHp6KNvrJLMFdSXTYID0Zf+q7X05JsNg=
+github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
+github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
+github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
+github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
+github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
+github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
+github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
+github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
+github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0=
+github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs=
+github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
+github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
+github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
+github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
+github.com/ipfs/go-test v0.0.4 h1:DKT66T6GBB6PsDFLoO56QZPrOmzJkqU1FZH5C9ySkew=
+github.com/ipfs/go-test v0.0.4/go.mod h1:qhIM1EluEfElKKM6fnWxGn822/z9knUGM1+I/OAQNKI=
+github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
+github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ=
+github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
+github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
+github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
+github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
+github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk=
+github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o=
+github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
+github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
+github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
+github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
+github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
+github.com/jsimonetti/rtnetlink v1.4.2 h1:Df9w9TZ3npHTyDn0Ev9e1uzmN2odmXd0QX+J5GTEn90=
+github.com/jsimonetti/rtnetlink v1.4.2/go.mod h1:92s6LJdE+1iOrw+F2/RO7LYI2Qd8pPpFNNUYW06gcoM=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
+github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
+github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
+github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
+github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0=
+github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
+github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
+github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
+github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
+github.com/libp2p/go-flow-metrics v0.2.0 h1:EIZzjmeOE6c8Dav0sNv35vhZxATIXWZg6j/C08XmmDw=
+github.com/libp2p/go-flow-metrics v0.2.0/go.mod h1:st3qqfu8+pMfh+9Mzqb2GTiwrAGjIPszEjZmtksN8Jc=
+github.com/libp2p/go-libp2p v0.37.0 h1:8K3mcZgwTldydMCNOiNi/ZJrOB9BY+GlI3UxYzxBi9A=
+github.com/libp2p/go-libp2p v0.37.0/go.mod h1:GOKmSN99scDuYGTwaTbQPR8Nt6dxrK3ue7OjW2NGDg4=
+github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94=
+github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8=
+github.com/libp2p/go-libp2p-kad-dht v0.28.0 h1:sDqfW784w7CZQLlnMUwfeqWfXcpedKeZIM/B9/w0Tbk=
+github.com/libp2p/go-libp2p-kad-dht v0.28.0/go.mod h1:0wHURlSFdAC42+wF7GEmpLoARw8JuS8do2guCtc/Y/w=
+github.com/libp2p/go-libp2p-kbucket v0.6.4 h1:OjfiYxU42TKQSB8t8WYd8MKhYhMJeO2If+NiuKfb6iQ=
+github.com/libp2p/go-libp2p-kbucket v0.6.4/go.mod h1:jp6w82sczYaBsAypt5ayACcRJi0lgsba7o4TzJKEfWA=
+github.com/libp2p/go-libp2p-pubsub v0.12.0 h1:PENNZjSfk8KYxANRlpipdS7+BfLmOl3L2E/6vSNjbdI=
+github.com/libp2p/go-libp2p-pubsub v0.12.0/go.mod h1:Oi0zw9aw8/Y5GC99zt+Ef2gYAl+0nZlwdJonDyOz/sE=
+github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0=
+github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.4 h1:6LqS1Bzn5CfDJ4tzvP9uwh42IB7TJLNFJA6dEeGBv84=
+github.com/libp2p/go-libp2p-routing-helpers v0.7.4/go.mod h1:we5WDj9tbolBXOuF1hGOkR+r7Uh1408tQbAKaT5n1LE=
+github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
+github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg=
+github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0=
+github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM=
+github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk=
+github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk=
+github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
+github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
+github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s=
+github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
+github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ=
+github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4=
+github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
+github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
+github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
+github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
+github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
+github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
+github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
+github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
+github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
+github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
+github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
+github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
+github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
+github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU=
+github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc=
+github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s=
+github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
+github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
+github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
+github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
+github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
+github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
+github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
+github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
+github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
+github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
+github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
+github.com/multiformats/go-multiaddr v0.13.0 h1:BCBzs61E3AGHcYYTv8dqRH43ZfyrqM8RXVPT8t13tLQ=
+github.com/multiformats/go-multiaddr v0.13.0/go.mod h1:sBXrNzucqkFJhvKOiwwLyqamGa/P5EIXNPLovyhQCII=
+github.com/multiformats/go-multiaddr-dns v0.4.0 h1:P76EJ3qzBXpUXZ3twdCDx/kvagMsNo0LMFXpyms/zgU=
+github.com/multiformats/go-multiaddr-dns v0.4.0/go.mod h1:7hfthtB4E4pQwirrz+J0CcDUfbWzTqEzVyYKKIKpgkc=
+github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
+github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
+github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
+github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
+github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg=
+github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k=
+github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
+github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
+github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
+github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE=
+github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA=
+github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
+github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
+github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
+github.com/olivere/elastic v6.2.14+incompatible h1:k+KadwNP/dkXE0/eu+T6otk1+5fe0tEpPyQJ4XVm5i8=
+github.com/olivere/elastic v6.2.14+incompatible/go.mod h1:J+q1zQJTgAz9woqsbVRqGeB5G1iqDKVBWLNSYW8yfJ8=
+github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
+github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
+github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
+github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
+github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
+github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
+github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
+github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
+github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
+github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
+github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe h1:vHpqOnPlnkba8iSxU4j/CvDSS9J4+F4473esQsYLGoE=
+github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
+github.com/pion/datachannel v1.5.9 h1:LpIWAOYPyDrXtU+BW7X0Yt/vGtYxtXQ8ql7dFfYUVZA=
+github.com/pion/datachannel v1.5.9/go.mod h1:kDUuk4CU4Uxp82NH4LQZbISULkX/HtzKa4P7ldf9izE=
+github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
+github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=
+github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
+github.com/pion/ice/v2 v2.3.36 h1:SopeXiVbbcooUg2EIR8sq4b13RQ8gzrkkldOVg+bBsc=
+github.com/pion/ice/v2 v2.3.36/go.mod h1:mBF7lnigdqgtB+YHkaY/Y6s6tsyRyo4u4rPGRuOjUBQ=
+github.com/pion/interceptor v0.1.39 h1:Y6k0bN9Y3Lg/Wb21JBWp480tohtns8ybJ037AGr9UuA=
+github.com/pion/interceptor v0.1.39/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic=
+github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
+github.com/pion/logging v0.2.3 h1:gHuf0zpoh1GW67Nr6Gj4cv5Z9ZscU7g/EaoC/Ke/igI=
+github.com/pion/logging v0.2.3/go.mod h1:z8YfknkquMe1csOrxK5kc+5/ZPAzMxbKLX5aXpbpC90=
+github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8=
+github.com/pion/mdns v0.0.12/go.mod h1:VExJjv8to/6Wqm1FXK+Ii/Z9tsVk/F5sD/N70cnYFbk=
+github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
+github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
+github.com/pion/rtcp v1.2.12/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4=
+github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
+github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
+github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
+github.com/pion/rtp v1.8.18 h1:yEAb4+4a8nkPCecWzQB6V/uEU18X1lQCGAQCjP+pyvU=
+github.com/pion/rtp v1.8.18/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk=
+github.com/pion/sctp v1.8.33 h1:dSE4wX6uTJBcNm8+YlMg7lw1wqyKHggsP5uKbdj+NZw=
+github.com/pion/sctp v1.8.33/go.mod h1:beTnqSzewI53KWoG3nqB282oDMGrhNxBdb+JZnkCwRM=
+github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY=
+github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M=
+github.com/pion/srtp/v2 v2.0.20 h1:HNNny4s+OUmG280ETrCdgFndp4ufx3/uy85EawYEhTk=
+github.com/pion/srtp/v2 v2.0.20/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA=
+github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
+github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
+github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
+github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
+github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
+github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
+github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
+github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0=
+github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
+github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
+github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
+github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc=
+github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
+github.com/pion/webrtc/v3 v3.3.4 h1:v2heQVnXTSqNRXcaFQVOhIOYkLMxOu1iJG8uy1djvkk=
+github.com/pion/webrtc/v3 v3.3.4/go.mod h1:liNa+E1iwyzyXqNUwvoMRNQ10x8h8FOeJKL8RkIbamE=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4=
+github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
+github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
+github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
+github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
+github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA=
+github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
+github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
+github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
+github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
+github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
+github.com/quic-go/quic-go v0.49.1 h1:e5JXpUyF0f2uFjckQzD8jTghZrOUK1xxDqqZhlwixo0=
+github.com/quic-go/quic-go v0.49.1/go.mod h1:s2wDnmCdooUQBmQfpUSTCYBl1/D4FcqbULMMkASvR6s=
+github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg=
+github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66/go.mod h1:Vp72IJajgeOL6ddqrAhmp7IM9zbTcgkQxD/YdxrVwMw=
+github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
+github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
+github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
+github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
+github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
+github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
+github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
+github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
+github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
+github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
+github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
+github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
+github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
+github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
+github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
+github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
+github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
+github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
+github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
+github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
+github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
+github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
+github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
+github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.8.3 h1:DBBfY8eMYazKEJHb3JKpSPfpgd2mBCoNFlQx6C5fftU=
+github.com/sirupsen/logrus v1.8.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
+github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
+github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
+github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
+github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
+github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
+github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
+github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
+github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/valyala/gozstd v1.21.2 h1:SBZ6sYA9y+u32XSds1TwOJJatcqmA3TgfLwGtV78Fcw=
+github.com/valyala/gozstd v1.21.2/go.mod h1:y5Ew47GLlP37EkTB+B4s7r6A5rdaeB7ftbl9zoYiIPQ=
+github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
+github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
+github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
+github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
+github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=
+github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
+github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
+github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
+github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
+go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
+go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
+go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
+go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE=
+go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE=
+go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY=
+go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=
+go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/dig v1.18.0 h1:imUL1UiY0Mg4bqbFfsRQO5G4CGRBec/ZujWTvSVp3pw=
+go.uber.org/dig v1.18.0/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE=
+go.uber.org/fx v1.23.0 h1:lIr/gYWQGfTwGcSXWXu4vP5Ws6iqnNEIY+F/aFzCKTg=
+go.uber.org/fx v1.23.0/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU=
+go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
+go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
+go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
+go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
+go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
+golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
+golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+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.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
+golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
+golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
+golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
+golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
+golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
+golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
+golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+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.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
+golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
+golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
+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=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
+golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
+golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/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.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
+golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
+golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU=
+golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
+golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
+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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
+golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
+golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
+golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
+golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
+golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ=
+gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo=
+google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
+google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
+google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
+google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
+google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
+google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/sohlich/elogrus.v3 v3.0.0-20180410122755-1fa29e2f2009 h1:q/fZgS8MMadqFFGa8WL4Oyz+TmjiZfi8UrzWhTl8d5w=
+gopkg.in/sohlich/elogrus.v3 v3.0.0-20180410122755-1fa29e2f2009/go.mod h1:O0bY1e/dSoxMYZYTHP0SWKxG5EWLEvKR9/cOjWPPMKU=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
+honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
+lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
+pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk=
+pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
+sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
+sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
diff --git a/tools/debug/algodump/main.go b/tools/debug/algodump/main.go
index e42b893562..a2c291f63e 100644
--- a/tools/debug/algodump/main.go
+++ b/tools/debug/algodump/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -20,10 +20,16 @@ import (
"flag"
"fmt"
"io"
+ "net/http"
"os"
+ "os/signal"
+ "path/filepath"
"strings"
+ "syscall"
"time"
+ kzstd "github.com/klauspost/compress/zstd"
+
"github.com/algorand/go-deadlock"
"github.com/algorand/go-algorand/agreement"
@@ -37,13 +43,25 @@ import (
)
var serverAddress = flag.String("server", "", "Server address (host:port)")
+var playbackDir = flag.String("playback", "", "Directory to load stored messages from")
+var quiet = flag.Bool("quiet", false, "Suppress printing of individual message details")
var genesisID = flag.String("genesis", "mainnet-v1.0", "Genesis ID")
var networkID = flag.String("network", "mainnet", "Network ID")
var tags = flag.String("tags", "*", "Comma-separated list of tags to dump, or * for all")
var longFlag = flag.Bool("long", false, "Print full-length addresses and digests")
+type StoredMessage struct {
+ Tag protocol.Tag `codec:"t"`
+ Data []byte `codec:"d,allocbound=-"`
+}
+
+// dumpHandler handles dumping network messages to console/files
type dumpHandler struct {
- tags map[protocol.Tag]bool
+ tags map[protocol.Tag]bool
+ storeMutex deadlock.Mutex
+ storeBuffer []StoredMessage
+ storeSize int
+ storeCounter int
}
func shortaddr(addr basics.Address) string {
@@ -60,9 +78,24 @@ func shortdigest(d crypto.Digest) string {
return fmt.Sprintf("%s..", d.String()[0:8])
}
+// fakePeer implements network.DisconnectableAddressablePeer for playback mode
+type fakePeer struct{}
+
+func (fp *fakePeer) GetAddress() string { return "playback-peer" }
+func (fp *fakePeer) GetHTTPClient() *http.Client { return nil }
+func (fp *fakePeer) Disconnect(reason string) error { return nil }
+func (fp *fakePeer) GetNetwork() network.GossipNode { return nil }
+func (fp *fakePeer) RoutingAddr() []byte { return []byte("playback-peer") }
+
+// Handle implements the network.MessageHandler interface for dumpHandler
func (dh *dumpHandler) Handle(msg network.IncomingMessage) network.OutgoingMessage {
var src string
+ // In playback mode, create a fake peer if none exists
+ if msg.Sender == nil && *playbackDir != "" {
+ msg.Sender = &fakePeer{}
+ }
+
hp, ok := msg.Sender.(network.HTTPPeer)
if ok {
a := hp.GetAddress()
@@ -118,13 +151,23 @@ func (dh *dumpHandler) Handle(msg network.IncomingMessage) network.OutgoingMessa
}
print:
- fmt.Printf("%s%s %s [%d bytes] %s\n", ts, src, msg.Tag, len(msg.Data), data)
+ if !*quiet {
+ fmt.Printf("%s%s %s [%d bytes] %s\n", ts, src, msg.Tag, len(msg.Data), data)
+ }
+
+ // Store message if enabled
+ if *storeDir != "" {
+ dh.storeMessages(msg.Tag, msg.Data)
+ }
+
return network.OutgoingMessage{Action: network.Ignore}
}
-func setDumpHandlers(n network.GossipNode) {
+// initDumpHandler initializes a basic dumpHandler
+func initDumpHandler() *dumpHandler {
var dh dumpHandler
+ // Set up tag filtering
if *tags == "*" {
// Dump all tags: nil tags
} else if *tags == "" {
@@ -138,21 +181,186 @@ func setDumpHandlers(n network.GossipNode) {
}
}
+ return &dh
+}
+
+// setDumpHandlers configures and registers message handlers with the network node
+func setDumpHandlers(n network.GossipNode) network.MessageHandler {
+ var dh network.MessageHandler
+
+ // Create store directory if needed (for both handler types)
+ if *storeDir != "" {
+ err := os.MkdirAll(*storeDir, 0755)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error creating store directory: %v\n", err)
+ os.Exit(1)
+ }
+ }
+
+ // Choose handler type based on compression flag
+ if *compress {
+ // Initialize and configure compression handler
+ cdh := initCompressDumpHandler()
+ err := configureCompression(cdh)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%v\n", err)
+ os.Exit(1)
+ }
+ dh = cdh
+ setupCompressSignalHandler(cdh)
+ } else {
+ // Use basic handler
+ ddh := initDumpHandler()
+ dh = ddh
+ setupBasicSignalHandler(ddh)
+ }
+
+ // Register the handler with all tags
h := []network.TaggedMessageHandler{
- {Tag: protocol.AgreementVoteTag, MessageHandler: &dh},
- {Tag: protocol.StateProofSigTag, MessageHandler: &dh},
- {Tag: protocol.MsgOfInterestTag, MessageHandler: &dh},
- {Tag: protocol.MsgDigestSkipTag, MessageHandler: &dh},
- {Tag: protocol.NetPrioResponseTag, MessageHandler: &dh},
- // {Tag: protocol.PingTag, MessageHandler: &dh},
- // {Tag: protocol.PingReplyTag, MessageHandler: &dh},
- {Tag: protocol.ProposalPayloadTag, MessageHandler: &dh},
- {Tag: protocol.TopicMsgRespTag, MessageHandler: &dh},
- {Tag: protocol.TxnTag, MessageHandler: &dh},
- {Tag: protocol.UniEnsBlockReqTag, MessageHandler: &dh},
- {Tag: protocol.VoteBundleTag, MessageHandler: &dh},
+ {Tag: protocol.AgreementVoteTag, MessageHandler: dh},
+ {Tag: protocol.StateProofSigTag, MessageHandler: dh},
+ {Tag: protocol.MsgOfInterestTag, MessageHandler: dh},
+ {Tag: protocol.MsgDigestSkipTag, MessageHandler: dh},
+ {Tag: protocol.NetPrioResponseTag, MessageHandler: dh},
+ // {Tag: protocol.PingTag, MessageHandler: dh},
+ // {Tag: protocol.PingReplyTag, MessageHandler: dh},
+ {Tag: protocol.ProposalPayloadTag, MessageHandler: dh},
+ {Tag: protocol.TopicMsgRespTag, MessageHandler: dh},
+ {Tag: protocol.TxnTag, MessageHandler: dh},
+ {Tag: protocol.UniEnsBlockReqTag, MessageHandler: dh},
+ {Tag: protocol.VoteBundleTag, MessageHandler: dh},
}
n.RegisterHandlers(h)
+
+ return dh
+}
+
+// isPowerOfTwo returns true if n is a power of 2
+func isPowerOfTwo(n int) bool {
+ return n > 0 && (n&(n-1)) == 0
+}
+
+// runPlayback processes stored message files from a directory
+func runPlayback(log logging.Logger) {
+ var handler network.MessageHandler
+
+ // Choose the appropriate handler based on compression flag
+ if *compress {
+ cdh := initCompressDumpHandler()
+
+ // Configure compression for playback mode
+ if *contextConfig != "" {
+ err := configureCompression(cdh)
+ if err != nil {
+ log.Errorf("Error parsing context configuration: %v", err)
+ os.Exit(1)
+ }
+ }
+ handler = cdh
+ } else {
+ handler = initDumpHandler()
+ }
+
+ files, err := os.ReadDir(*playbackDir)
+ if err != nil {
+ log.Errorf("Failed to read playback directory: %v", err)
+ os.Exit(1)
+ }
+
+ for _, file := range files {
+ if !strings.HasSuffix(file.Name(), ".msgp") {
+ continue
+ }
+ data, err := os.ReadFile(filepath.Join(*playbackDir, file.Name()))
+ if err != nil {
+ log.Errorf("Failed to read message file %s: %v", file.Name(), err)
+ continue
+ }
+ var messages []StoredMessage
+ err = protocol.DecodeReflect(data, &messages)
+ if err != nil {
+ log.Errorf("Failed to decode messages from %s: %v", file.Name(), err)
+ continue
+ }
+
+ // Process each message through the appropriate handler
+ for _, msg := range messages {
+ handler.Handle(network.IncomingMessage{Tag: msg.Tag, Data: msg.Data})
+ }
+ }
+
+ // Print stats only if using compression
+ if *compress {
+ cdh := handler.(*compressDumpHandler)
+ cdh.printStats()
+ }
+}
+
+// setupBasicSignalHandler sets up a signal handler for the basic dumpHandler
+func setupBasicSignalHandler(dh *dumpHandler) {
+ c := make(chan os.Signal, 1)
+ signal.Notify(c, os.Interrupt, syscall.SIGTERM)
+ go func() {
+ <-c
+ // Flush any remaining messages
+ if *storeDir != "" {
+ dh.storeFlush()
+ }
+ os.Exit(0)
+ }()
+}
+
+// storeMessages adds a message to the store buffer and flushes if needed
+func (dh *dumpHandler) storeMessages(tag protocol.Tag, data []byte) {
+ dh.storeMutex.Lock()
+ defer dh.storeMutex.Unlock()
+
+ dh.storeBuffer = append(dh.storeBuffer, StoredMessage{Tag: tag, Data: data})
+ dh.storeSize += len(data)
+
+ if dh.storeSize >= *storeBatchSize {
+ err := dh.flushMessages()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error flushing messages: %v\n", err)
+ }
+ }
+}
+
+// storeFlush flushes any remaining messages to disk
+func (dh *dumpHandler) storeFlush() {
+ dh.storeMutex.Lock()
+ defer dh.storeMutex.Unlock()
+
+ err := dh.flushMessages()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error flushing messages: %v\n", err)
+ }
+}
+
+func (dh *dumpHandler) flushMessages() error {
+ if len(dh.storeBuffer) == 0 {
+ return nil
+ }
+
+ // Create timestamped filename
+ timestamp := time.Now().Format("20060102-150405.000")
+ filename := fmt.Sprintf("messages-%s-%d.msgp", timestamp, dh.storeCounter)
+ path := filepath.Join(*storeDir, filename)
+
+ // Encode messages
+ data := protocol.EncodeReflect(&dh.storeBuffer)
+
+ // Write to file
+ err := os.WriteFile(path, data, 0644)
+ if err != nil {
+ return fmt.Errorf("error writing messages to %s: %v", path, err)
+ }
+
+ // Reset buffer
+ dh.storeBuffer = nil
+ dh.storeSize = 0
+ dh.storeCounter++
+ return nil
}
func main() {
@@ -160,32 +368,66 @@ func main() {
log.SetLevel(logging.Debug)
log.SetOutput(os.Stderr)
- if *serverAddress == "" {
- log.Infof("No server address specified; defaulting to DNS bootstrapping")
+ flag.Parse()
+
+ // Validate compression parameters if compress is enabled
+ if *compress {
+ // Validate that window size is a power of 2 and within valid range
+ if !isPowerOfTwo(*compressionWindowSize) {
+ log.Errorf("windowSize must be a power of 2, got %d", *compressionWindowSize)
+ os.Exit(1)
+ }
+ if *compressionWindowSize < kzstd.MinWindowSize || *compressionWindowSize > kzstd.MaxWindowSize {
+ log.Errorf("windowSize must be between %d and %d, got %d",
+ kzstd.MinWindowSize, kzstd.MaxWindowSize, *compressionWindowSize)
+ os.Exit(1)
+ }
+
+ // Parse context configuration if provided - validation only
+ if *contextConfig != "" {
+ _, _, err := parseContextConfig(*contextConfig)
+ if err != nil {
+ log.Errorf("Failed to parse context configuration: %v", err)
+ os.Exit(1)
+ }
+ }
}
- deadlock.Opts.Disable = true
+ if *playbackDir != "" {
+ // Playback mode - process stored messages from a directory
+ runPlayback(log)
+ os.Exit(0)
+ } else {
+ // Live mode - connect to network and process messages in real-time
+ if *serverAddress == "" {
+ log.Infof("No server address specified; defaulting to DNS bootstrapping")
+ }
- flag.Parse()
+ deadlock.Opts.Disable = true
- conf, _ := config.LoadConfigFromDisk("/dev/null")
- if *serverAddress != "" {
- conf.DNSBootstrapID = ""
- }
+ conf, _ := config.LoadConfigFromDisk("/dev/null")
+ if *serverAddress != "" {
+ conf.DNSBootstrapID = ""
+ }
+ conf.GossipFanout = 1
- n, _ := network.NewWebsocketGossipNode(log,
- conf,
- []string{*serverAddress},
- *genesisID,
- protocol.NetworkID(*networkID))
- setDumpHandlers(n)
- err := n.Start()
- if err != nil {
- log.Errorf("Failed to start network: %v", err)
- return
- }
+ n, _ := network.NewWebsocketGossipNode(log,
+ conf,
+ []string{*serverAddress},
+ *genesisID,
+ protocol.NetworkID(*networkID))
+
+ // Set up and register handlers - this detects the -compress flag and sets up the appropriate handler
+ setDumpHandlers(n)
- for {
- time.Sleep(time.Second)
+ err := n.Start()
+ if err != nil {
+ log.Errorf("Failed to start network: %v", err)
+ return
+ }
+
+ for {
+ time.Sleep(time.Second)
+ }
}
}
diff --git a/tools/debug/carpenter/main.go b/tools/debug/carpenter/main.go
index b13bbb9b2b..12dd813b93 100644
--- a/tools/debug/carpenter/main.go
+++ b/tools/debug/carpenter/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/debug/chopper/main.go b/tools/debug/chopper/main.go
index effcf566c2..13f3bff1c0 100644
--- a/tools/debug/chopper/main.go
+++ b/tools/debug/chopper/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/debug/coroner/main.go b/tools/debug/coroner/main.go
index f199a62dea..4388412ce8 100644
--- a/tools/debug/coroner/main.go
+++ b/tools/debug/coroner/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/debug/determaccount/main.go b/tools/debug/determaccount/main.go
index 368c51675c..c68595eda0 100644
--- a/tools/debug/determaccount/main.go
+++ b/tools/debug/determaccount/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/debug/dumpblocks/main.go b/tools/debug/dumpblocks/main.go
index fd634caee3..3f02a7de24 100644
--- a/tools/debug/dumpblocks/main.go
+++ b/tools/debug/dumpblocks/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/debug/genconsensusconfig/main.go b/tools/debug/genconsensusconfig/main.go
deleted file mode 100644
index ec0f0255d4..0000000000
--- a/tools/debug/genconsensusconfig/main.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (C) 2019-2025 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 .
-
-// doberman will tell you when there's something wrong with the system
-package main
-
-import (
- "fmt"
- "os"
-
- "github.com/algorand/go-algorand/config"
-)
-
-func main() {
- path, err := os.Getwd()
- if err != nil {
- fmt.Printf("Unable to retieve current working directory : %v", err)
- os.Exit(1)
- }
- err = config.SaveConfigurableConsensus(path, config.Consensus)
- if err != nil {
- fmt.Printf("Unable to save file : %v", err)
- os.Exit(1)
- }
- os.Exit(0)
-}
diff --git a/tools/debug/logfilter/main.go b/tools/debug/logfilter/main.go
index 12db2dd785..a79f0031bb 100644
--- a/tools/debug/logfilter/main.go
+++ b/tools/debug/logfilter/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/debug/logfilter/main_test.go b/tools/debug/logfilter/main_test.go
index 4386956338..416351e07c 100644
--- a/tools/debug/logfilter/main_test.go
+++ b/tools/debug/logfilter/main_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/debug/transplanter/main.go b/tools/debug/transplanter/main.go
index 5c0de8b0eb..76782d262c 100644
--- a/tools/debug/transplanter/main.go
+++ b/tools/debug/transplanter/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/misc/convertAddress.go b/tools/misc/convertAddress.go
index c72e0a2096..57ac533e1c 100644
--- a/tools/misc/convertAddress.go
+++ b/tools/misc/convertAddress.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/bootstrap.go b/tools/network/bootstrap.go
index b71592ffa6..7119658789 100644
--- a/tools/network/bootstrap.go
+++ b/tools/network/bootstrap.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/bootstrap_test.go b/tools/network/bootstrap_test.go
index a20e493bc3..dee9607a7e 100644
--- a/tools/network/bootstrap_test.go
+++ b/tools/network/bootstrap_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/cloudflare/cloudflare.go b/tools/network/cloudflare/cloudflare.go
index 6d935fe48b..db69c3728f 100644
--- a/tools/network/cloudflare/cloudflare.go
+++ b/tools/network/cloudflare/cloudflare.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/cloudflare/createRecord.go b/tools/network/cloudflare/createRecord.go
index 8b578c8e0f..00ad91bbc8 100644
--- a/tools/network/cloudflare/createRecord.go
+++ b/tools/network/cloudflare/createRecord.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/cloudflare/deleteRecord.go b/tools/network/cloudflare/deleteRecord.go
index 8055c10c76..f4648fbaba 100644
--- a/tools/network/cloudflare/deleteRecord.go
+++ b/tools/network/cloudflare/deleteRecord.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -52,7 +52,7 @@ type DeleteDNSRecordResult struct {
ID string `json:"id"`
}
-// ParseDeleteDNSRecordResponse parses the response that was received as a result of a ListDNSRecordRequest
+// parseDeleteDNSRecordResponse parses the response that was received as a result of a ListDNSRecordRequest
func parseDeleteDNSRecordResponse(response *http.Response) (*DeleteDNSRecordResponse, error) {
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
diff --git a/tools/network/cloudflare/helpers.go b/tools/network/cloudflare/helpers.go
index 282ebf7154..faf12a2eff 100644
--- a/tools/network/cloudflare/helpers.go
+++ b/tools/network/cloudflare/helpers.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/cloudflare/listRecords.go b/tools/network/cloudflare/listRecords.go
index b581edad16..f17ccbd2e3 100644
--- a/tools/network/cloudflare/listRecords.go
+++ b/tools/network/cloudflare/listRecords.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/cloudflare/updateRecord.go b/tools/network/cloudflare/updateRecord.go
index 2d61ceb385..3816d72c3b 100644
--- a/tools/network/cloudflare/updateRecord.go
+++ b/tools/network/cloudflare/updateRecord.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/cloudflare/zones.go b/tools/network/cloudflare/zones.go
index 5d6948c14e..ea9492bc75 100644
--- a/tools/network/cloudflare/zones.go
+++ b/tools/network/cloudflare/zones.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/anchor.go b/tools/network/dnssec/anchor.go
index c35d37c934..7aabfa3df2 100644
--- a/tools/network/dnssec/anchor.go
+++ b/tools/network/dnssec/anchor.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/anchor_test.go b/tools/network/dnssec/anchor_test.go
index 1d3502d732..03b01a20a0 100644
--- a/tools/network/dnssec/anchor_test.go
+++ b/tools/network/dnssec/anchor_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/client.go b/tools/network/dnssec/client.go
index 1caf39d0bd..124ef8bc76 100644
--- a/tools/network/dnssec/client.go
+++ b/tools/network/dnssec/client.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/client_test.go b/tools/network/dnssec/client_test.go
index 82df54c2fd..0a785ba06b 100644
--- a/tools/network/dnssec/client_test.go
+++ b/tools/network/dnssec/client_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/config.go b/tools/network/dnssec/config.go
index 4e314fc29f..ec3d76459b 100644
--- a/tools/network/dnssec/config.go
+++ b/tools/network/dnssec/config.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/config_test.go b/tools/network/dnssec/config_test.go
index b7ed8389d9..f18886a3cb 100644
--- a/tools/network/dnssec/config_test.go
+++ b/tools/network/dnssec/config_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/config_unix.go b/tools/network/dnssec/config_unix.go
index fb72bde3d5..7e4c76f19e 100644
--- a/tools/network/dnssec/config_unix.go
+++ b/tools/network/dnssec/config_unix.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//go:build !windows
-// +build !windows
package dnssec
diff --git a/tools/network/dnssec/config_unix_test.go b/tools/network/dnssec/config_unix_test.go
index b689ff2236..5481766e4f 100644
--- a/tools/network/dnssec/config_unix_test.go
+++ b/tools/network/dnssec/config_unix_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//go:build !windows
-// +build !windows
package dnssec
diff --git a/tools/network/dnssec/config_windows.go b/tools/network/dnssec/config_windows.go
index b1e303d6e3..5215ea69ac 100644
--- a/tools/network/dnssec/config_windows.go
+++ b/tools/network/dnssec/config_windows.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//go:build windows
-// +build windows
package dnssec
diff --git a/tools/network/dnssec/dialer.go b/tools/network/dnssec/dialer.go
index 559605711e..9a8675b1f6 100644
--- a/tools/network/dnssec/dialer.go
+++ b/tools/network/dnssec/dialer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/dnssec_test.go b/tools/network/dnssec/dnssec_test.go
index 590c2e49ad..bd5b913603 100644
--- a/tools/network/dnssec/dnssec_test.go
+++ b/tools/network/dnssec/dnssec_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/relay-check/main.go b/tools/network/dnssec/relay-check/main.go
index ef10b5ced4..6aa4d7ff23 100644
--- a/tools/network/dnssec/relay-check/main.go
+++ b/tools/network/dnssec/relay-check/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/resolver.go b/tools/network/dnssec/resolver.go
index 05324b5fcf..da398173c7 100644
--- a/tools/network/dnssec/resolver.go
+++ b/tools/network/dnssec/resolver.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -169,7 +169,7 @@ func (r *Resolver) lookupCnameAware(ctx context.Context, name string, qt uint16)
return
}
-// LookupIPAddr resolves a given hostname to ipv4 or ipv6 address following CNAME aliaces
+// lookupIPAddr resolves a given hostname to ipv4 or ipv6 address following CNAME aliaces
func (r *Resolver) lookupIPAddr(ctx context.Context, hostname string) (cname string, addrs []net.IPAddr, err error) {
var rrSet []dns.RR
nextName := hostname
diff --git a/tools/network/dnssec/sort.go b/tools/network/dnssec/sort.go
index f76937d00f..b67f2d8a8e 100644
--- a/tools/network/dnssec/sort.go
+++ b/tools/network/dnssec/sort.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/sort_test.go b/tools/network/dnssec/sort_test.go
index 0c987f0eda..a3ef3bfee8 100644
--- a/tools/network/dnssec/sort_test.go
+++ b/tools/network/dnssec/sort_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/testHarness.go b/tools/network/dnssec/testHarness.go
index e65e61d74b..1eb6437336 100644
--- a/tools/network/dnssec/testHarness.go
+++ b/tools/network/dnssec/testHarness.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/trustchain.go b/tools/network/dnssec/trustchain.go
index dc4d8ee54f..8daa1a933c 100644
--- a/tools/network/dnssec/trustchain.go
+++ b/tools/network/dnssec/trustchain.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/trustedchain_test.go b/tools/network/dnssec/trustedchain_test.go
index 8b459669b7..4d7e1b7dfe 100644
--- a/tools/network/dnssec/trustedchain_test.go
+++ b/tools/network/dnssec/trustedchain_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/trustedzone.go b/tools/network/dnssec/trustedzone.go
index 0601d7c2be..a515c735c7 100644
--- a/tools/network/dnssec/trustedzone.go
+++ b/tools/network/dnssec/trustedzone.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/trustedzone_test.go b/tools/network/dnssec/trustedzone_test.go
index 32d91a4b83..9e78fa512c 100644
--- a/tools/network/dnssec/trustedzone_test.go
+++ b/tools/network/dnssec/trustedzone_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/util.go b/tools/network/dnssec/util.go
index f855ec1ef7..9512077688 100644
--- a/tools/network/dnssec/util.go
+++ b/tools/network/dnssec/util.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/dnssec/util_test.go b/tools/network/dnssec/util_test.go
index 22ac880d7a..3c14cc993e 100644
--- a/tools/network/dnssec/util_test.go
+++ b/tools/network/dnssec/util_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/externalIP.go b/tools/network/externalIP.go
index 8dab3f4d60..c452b53328 100644
--- a/tools/network/externalIP.go
+++ b/tools/network/externalIP.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/resolveController.go b/tools/network/resolveController.go
index fc55a7a0f3..0b8557e6f5 100644
--- a/tools/network/resolveController.go
+++ b/tools/network/resolveController.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/resolveController_test.go b/tools/network/resolveController_test.go
index 8dd1496c9f..facd40e5d3 100644
--- a/tools/network/resolveController_test.go
+++ b/tools/network/resolveController_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/resolver.go b/tools/network/resolver.go
index 42716ac5eb..71b541ce01 100644
--- a/tools/network/resolver.go
+++ b/tools/network/resolver.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/resolver_test.go b/tools/network/resolver_test.go
index a414f649f2..78dc8b179d 100644
--- a/tools/network/resolver_test.go
+++ b/tools/network/resolver_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/telemetryURIUpdateService.go b/tools/network/telemetryURIUpdateService.go
index 6175adf3f4..ed95b38690 100644
--- a/tools/network/telemetryURIUpdateService.go
+++ b/tools/network/telemetryURIUpdateService.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/network/telemetryURIUpdateService_test.go b/tools/network/telemetryURIUpdateService_test.go
index 5cb18752f7..07abe3532e 100644
--- a/tools/network/telemetryURIUpdateService_test.go
+++ b/tools/network/telemetryURIUpdateService_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/teal/algotmpl/extract.go b/tools/teal/algotmpl/extract.go
index 69dfb98b2d..1053f9d891 100644
--- a/tools/teal/algotmpl/extract.go
+++ b/tools/teal/algotmpl/extract.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/teal/algotmpl/main.go b/tools/teal/algotmpl/main.go
index 7b82e0a9b5..516cf25a1b 100644
--- a/tools/teal/algotmpl/main.go
+++ b/tools/teal/algotmpl/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/teal/dkey/dsign/main.go b/tools/teal/dkey/dsign/main.go
index 335a310269..f16e37a4f0 100644
--- a/tools/teal/dkey/dsign/main.go
+++ b/tools/teal/dkey/dsign/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/teal/examples/keyreg.sh b/tools/teal/examples/keyreg.sh
index 5740be555f..eeab335919 100755
--- a/tools/teal/examples/keyreg.sh
+++ b/tools/teal/examples/keyreg.sh
@@ -14,7 +14,7 @@ goal account addpartkey -a CI3OPSTHUPJNOYDN2EAQDAOVYZNQNJNS5QJD7WGHCX4O6SZAG7EP4
# > Participation key generation successful
# create the keyreg transaction and sign it with the delegate logic, along with the key
-goal account changeonlinestatus -a CI3OPSTHUPJNOYDN2EAQDAOVYZNQNJNS5QJD7WGHCX4O6SZAG7EP4TNMC4 -x uFVDhjBpkpKQ8sZaau0qsDsf0eW3oXFEn1Ar5o39vkk= --online --firstRound 2600 --validRounds 95 --txfile keyreg.tx -d .
+goal account changeonlinestatus -a CI3OPSTHUPJNOYDN2EAQDAOVYZNQNJNS5QJD7WGHCX4O6SZAG7EP4TNMC4 -x uFVDhjBpkpKQ8sZaau0qsDsf0eW3oXFEn1Ar5o39vkk= --online --firstvalid 2600 --validrounds 95 --txfile keyreg.tx -d .
cat keyreg.tx | dsign delegate.keyregkey kr.lsig > keyreg.stx
# send the keyreg transaction to the network
diff --git a/tools/teal/tealcut/main.go b/tools/teal/tealcut/main.go
deleted file mode 100644
index 1746d04941..0000000000
--- a/tools/teal/tealcut/main.go
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (C) 2019-2025 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 main
-
-import (
- "bytes"
- "crypto/sha512"
- "encoding/base64"
- "encoding/binary"
- "encoding/hex"
- "fmt"
- "os"
- "strconv"
-
- "github.com/algorand/go-algorand/crypto"
- "github.com/algorand/go-algorand/data/basics"
- "github.com/algorand/go-algorand/data/transactions/logic"
-)
-
-// Usage:
-//
-// tealcut 0x
-// Prints the program before and after the number separator,
-// as well as a hash of both these components in base 16.
-//
-// tealcut 0x b64
-// Like the above, but print in base 64 instead of base 16.
-//
-// tealcut 0x 0x
-// In addition to the program before and after the separator,
-// also print the program where the first occurrence of the
-// separator is replaced by the inserted number, along with
-// the program's hash.
-//
-// Note that all command-line number arguments are in base 16.
-
-func main() {
- splitnum, err := strconv.ParseUint(os.Args[2], 0, 64)
- if err != nil {
- panic(err)
- }
- var splitbytes [8]byte
- binary.BigEndian.PutUint64(splitbytes[:], splitnum)
- data, err := os.ReadFile(os.Args[1])
- if err != nil {
- panic(err)
- }
- before, after, found := bytes.Cut(data, splitbytes[:])
- fmt.Println(splitbytes[:])
-
- if !found {
- fmt.Println("split-string not found")
- return
- }
-
- hash0 := sha512.Sum512_256(before)
- hash1 := sha512.Sum512_256(after)
-
- encfn := func(str []byte) string {
- return "0x" + hex.EncodeToString(str)
- }
- if len(os.Args) > 3 {
- if os.Args[3] == "b64" {
- encfn = base64.StdEncoding.EncodeToString
- } else {
- writenum, err := strconv.ParseUint(os.Args[3], 0, 64)
- if err != nil {
- panic(err)
- }
- var writebytes [8]byte
- binary.BigEndian.PutUint64(writebytes[:], writenum)
- // append to empty slice to avoid modifying `data` (which before points to)
- program := append([]byte{}, before...)
- program = append(program, writebytes[:]...)
- program = append(program, after...)
-
- obj := logic.Program(program)
- lhash := crypto.HashObj(&obj)
- fmt.Println("addr:", basics.Address(lhash))
- fmt.Println("mod:", encfn(program))
- }
- }
-
- fmt.Println("hash0:", encfn(hash0[:]))
- fmt.Println("hash1:", encfn(hash1[:]))
- fmt.Println("sub0:", encfn(before))
- fmt.Println("sub1:", encfn(after))
- fmt.Println("data:", encfn(data))
-}
diff --git a/tools/x-repo-types/typeAnalyzer/main.go b/tools/x-repo-types/typeAnalyzer/main.go
index 1f96cfe4b5..a2eec918e1 100644
--- a/tools/x-repo-types/typeAnalyzer/main.go
+++ b/tools/x-repo-types/typeAnalyzer/main.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/x-repo-types/typeAnalyzer/main.tmpl b/tools/x-repo-types/typeAnalyzer/main.tmpl
index d846c443e3..d3d3c9ef56 100644
--- a/tools/x-repo-types/typeAnalyzer/main.tmpl
+++ b/tools/x-repo-types/typeAnalyzer/main.tmpl
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/x-repo-types/typeAnalyzer/typeAnalyzer.go b/tools/x-repo-types/typeAnalyzer/typeAnalyzer.go
index e652166c8e..db0e24c460 100644
--- a/tools/x-repo-types/typeAnalyzer/typeAnalyzer.go
+++ b/tools/x-repo-types/typeAnalyzer/typeAnalyzer.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/x-repo-types/typeAnalyzer/typeAnalyzer_test.go b/tools/x-repo-types/typeAnalyzer/typeAnalyzer_test.go
index 778bdccf53..c51f2709f3 100644
--- a/tools/x-repo-types/typeAnalyzer/typeAnalyzer_test.go
+++ b/tools/x-repo-types/typeAnalyzer/typeAnalyzer_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/x-repo-types/xrt.go b/tools/x-repo-types/xrt.go
index c7ff0e43d9..51b5577afa 100644
--- a/tools/x-repo-types/xrt.go
+++ b/tools/x-repo-types/xrt.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/tools/x-repo-types/xrt_test.go b/tools/x-repo-types/xrt_test.go
index 0e4b895585..19a3c74c7b 100644
--- a/tools/x-repo-types/xrt_test.go
+++ b/tools/x-repo-types/xrt_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/cmdUtils.go b/util/cmdUtils.go
index 32f88a86f9..f590aa7512 100644
--- a/util/cmdUtils.go
+++ b/util/cmdUtils.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/codecs/json.go b/util/codecs/json.go
index 301d542e6e..57468242a0 100644
--- a/util/codecs/json.go
+++ b/util/codecs/json.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/codecs/json_test.go b/util/codecs/json_test.go
index db4dfb105e..298d57d0d3 100644
--- a/util/codecs/json_test.go
+++ b/util/codecs/json_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/condvar/timedwait.go b/util/condvar/timedwait.go
index 08c46b7362..883c3f8be2 100644
--- a/util/condvar/timedwait.go
+++ b/util/condvar/timedwait.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/condvar/timedwait_test.go b/util/condvar/timedwait_test.go
index c9b7dfb567..e0d9393fa5 100644
--- a/util/condvar/timedwait_test.go
+++ b/util/condvar/timedwait_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/db/dbpair.go b/util/db/dbpair.go
index 95a257c2d4..e5b0d9411c 100644
--- a/util/db/dbpair.go
+++ b/util/db/dbpair.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/db/dbutil.go b/util/db/dbutil.go
index 7351927ff9..c456e9eff1 100644
--- a/util/db/dbutil.go
+++ b/util/db/dbutil.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/db/dbutil_test.go b/util/db/dbutil_test.go
index fa559d0750..1e405e9c47 100644
--- a/util/db/dbutil_test.go
+++ b/util/db/dbutil_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/db/fullfsync_darwin.go b/util/db/fullfsync_darwin.go
index 7cb08fe7ef..333c12394c 100644
--- a/util/db/fullfsync_darwin.go
+++ b/util/db/fullfsync_darwin.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/db/initialize.go b/util/db/initialize.go
index 2996b76437..74f313a85d 100644
--- a/util/db/initialize.go
+++ b/util/db/initialize.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/db/initialize_test.go b/util/db/initialize_test.go
index 55ae3db7f8..c368aef57d 100644
--- a/util/db/initialize_test.go
+++ b/util/db/initialize_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/db/interfaces.go b/util/db/interfaces.go
index f88c7ef02b..8ddadf4d25 100644
--- a/util/db/interfaces.go
+++ b/util/db/interfaces.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/db/perf_test.go b/util/db/perf_test.go
index 2e65da7b81..45e6530e9d 100644
--- a/util/db/perf_test.go
+++ b/util/db/perf_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/db/versioning.go b/util/db/versioning.go
index d87d16a8d6..7606dce52b 100644
--- a/util/db/versioning.go
+++ b/util/db/versioning.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/db/versioning_test.go b/util/db/versioning_test.go
index 459a9a6d1a..aa3670fdab 100644
--- a/util/db/versioning_test.go
+++ b/util/db/versioning_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/execpool/backlog.go b/util/execpool/backlog.go
index e3709b345a..3983147c76 100644
--- a/util/execpool/backlog.go
+++ b/util/execpool/backlog.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/execpool/pool.go b/util/execpool/pool.go
index c2f6b84835..b911b994c8 100644
--- a/util/execpool/pool.go
+++ b/util/execpool/pool.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/execpool/stream.go b/util/execpool/stream.go
index 5728ccede7..b0d6ccf560 100644
--- a/util/execpool/stream.go
+++ b/util/execpool/stream.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/execpool/stream_test.go b/util/execpool/stream_test.go
index b311acddd5..3c2c1cfb7f 100644
--- a/util/execpool/stream_test.go
+++ b/util/execpool/stream_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/fn.go b/util/fn.go
index 34372a5cd0..7457d813a2 100644
--- a/util/fn.go
+++ b/util/fn.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/io.go b/util/io.go
index 1244498267..60f32236b7 100644
--- a/util/io.go
+++ b/util/io.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/io_test.go b/util/io_test.go
index 884664c783..54052282cc 100644
--- a/util/io_test.go
+++ b/util/io_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/list.go b/util/list.go
index 9ea19ada14..73b11d4c4e 100644
--- a/util/list.go
+++ b/util/list.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/list_test.go b/util/list_test.go
index 4b7c0359e3..159ce9bc87 100644
--- a/util/list_test.go
+++ b/util/list_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/couge.go b/util/metrics/couge.go
index 3a1003b462..9c3a1d4191 100644
--- a/util/metrics/couge.go
+++ b/util/metrics/couge.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/counter.go b/util/metrics/counter.go
index 1dcd9a1e57..b2bbc951b0 100644
--- a/util/metrics/counter.go
+++ b/util/metrics/counter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -28,14 +28,14 @@ type Counter struct {
// MakeCounter create a new counter with the provided name and description.
func MakeCounter(metric MetricName) *Counter {
- c := makeCounter(metric)
+ c := MakeCounterUnregistered(metric)
c.Register(nil)
return c
}
-// makeCounter create a new counter with the provided name and description
+// MakeCounterUnregistered creates a new counter with the provided name and description
// but does not register it with the default registry.
-func makeCounter(metric MetricName) *Counter {
+func MakeCounterUnregistered(metric MetricName) *Counter {
c := &Counter{c: couge{
values: make([]*cougeValues, 0),
description: metric.Description,
diff --git a/util/metrics/counter_test.go b/util/metrics/counter_test.go
index ab50110e7d..9e28a49bd1 100644
--- a/util/metrics/counter_test.go
+++ b/util/metrics/counter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -38,6 +38,9 @@ func TestMetricCounter(t *testing.T) {
MetricTest: NewMetricTest(),
}
+ // create a non-default registry for the metrics in this test
+ registry := MakeRegistry()
+
// create a http listener.
port := test.createListener("127.0.0.1:0")
@@ -46,10 +49,12 @@ func TestMetricCounter(t *testing.T) {
Labels: map[string]string{
"host_name": "host_one",
"session_id": "AFX-229"},
+ registry: registry,
})
metricService.Start(context.Background())
- counter := MakeCounter(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"})
+ counter := MakeCounterUnregistered(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"})
+ counter.Register(registry)
for i := 0; i < 20; i++ {
counter.Inc(map[string]string{"pid": "123", "data_host": fmt.Sprintf("host%d", i%5)})
@@ -61,7 +66,7 @@ func TestMetricCounter(t *testing.T) {
metricService.Shutdown()
- counter.Deregister(nil)
+ counter.Deregister(registry)
// test the metrics values.
test.Lock()
@@ -84,6 +89,9 @@ func TestMetricCounterFastInts(t *testing.T) {
MetricTest: NewMetricTest(),
}
+ // create a non-default registry for the metrics in this test
+ registry := MakeRegistry()
+
// create a http listener.
port := test.createListener("127.0.0.1:0")
@@ -92,10 +100,12 @@ func TestMetricCounterFastInts(t *testing.T) {
Labels: map[string]string{
"host_name": "host_one",
"session_id": "AFX-229"},
+ registry: registry,
})
metricService.Start(context.Background())
- counter := MakeCounter(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"})
+ counter := MakeCounterUnregistered(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"})
+ counter.Register(registry)
for i := 0; i < 20; i++ {
counter.Inc(nil)
@@ -108,7 +118,7 @@ func TestMetricCounterFastInts(t *testing.T) {
metricService.Shutdown()
- counter.Deregister(nil)
+ counter.Deregister(registry)
// test the metrics values.
test.Lock()
@@ -131,6 +141,9 @@ func TestMetricCounterMixed(t *testing.T) {
MetricTest: NewMetricTest(),
}
+ // create a non-default registry for the metrics in this test
+ registry := MakeRegistry()
+
// create a http listener.
port := test.createListener("127.0.0.1:0")
@@ -139,10 +152,12 @@ func TestMetricCounterMixed(t *testing.T) {
Labels: map[string]string{
"host_name": "host_one",
"session_id": "AFX-229"},
+ registry: registry,
})
metricService.Start(context.Background())
- counter := MakeCounter(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"})
+ counter := MakeCounterUnregistered(MetricName{Name: "metric_test_name1", Description: "this is the metric test for counter object"})
+ counter.Register(registry)
counter.AddUint64(5, nil)
counter.AddUint64(8, map[string]string{})
@@ -157,7 +172,7 @@ func TestMetricCounterMixed(t *testing.T) {
metricService.Shutdown()
- counter.Deregister(nil)
+ counter.Deregister(registry)
// test the metrics values.
test.Lock()
diff --git a/util/metrics/gauge.go b/util/metrics/gauge.go
index 6b200fe0be..bf7d3b6940 100644
--- a/util/metrics/gauge.go
+++ b/util/metrics/gauge.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -27,14 +27,14 @@ type Gauge struct {
// MakeGauge create a new gauge with the provided name and description.
func MakeGauge(metric MetricName) *Gauge {
- c := makeGauge(metric)
+ c := MakeGaugeUnregistered(metric)
c.Register(nil)
return c
}
-// makeGauge create a new gauge with the provided name and description
+// MakeGaugeUnregistered creates a new gauge with the provided name and description
// but does not register it with the default registry.
-func makeGauge(metric MetricName) *Gauge {
+func MakeGaugeUnregistered(metric MetricName) *Gauge {
c := &Gauge{g: couge{
values: make([]*cougeValues, 0),
description: metric.Description,
diff --git a/util/metrics/gauge_test.go b/util/metrics/gauge_test.go
index c6c5c24afc..8410e1f101 100644
--- a/util/metrics/gauge_test.go
+++ b/util/metrics/gauge_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -37,6 +37,10 @@ func TestMetricGauge(t *testing.T) {
test := &GaugeTest{
MetricTest: NewMetricTest(),
}
+
+ // create a non-default registry for the metrics in this test
+ registry := MakeRegistry()
+
// create a http listener.
port := test.createListener("127.0.0.1:0")
@@ -45,11 +49,13 @@ func TestMetricGauge(t *testing.T) {
Labels: map[string]string{
"host_name": "host_one",
"session_id": "AFX-229"},
+ registry: registry,
})
metricService.Start(context.Background())
gauges := make([]*Gauge, 3)
for i := 0; i < 3; i++ {
- gauges[i] = MakeGauge(MetricName{Name: fmt.Sprintf("gauge_%d", i), Description: "this is the metric test for gauge object"})
+ gauges[i] = MakeGaugeUnregistered(MetricName{Name: fmt.Sprintf("gauge_%d", i), Description: "this is the metric test for gauge object"})
+ gauges[i].Register(registry)
}
for i := 0; i < 9; i++ {
gauges[i%3].Set(uint64(i*100 + i))
@@ -62,7 +68,7 @@ func TestMetricGauge(t *testing.T) {
metricService.Shutdown()
for _, gauge := range gauges {
- gauge.Deregister(nil)
+ gauge.Deregister(registry)
}
// test the metrics values.
diff --git a/util/metrics/metrics.go b/util/metrics/metrics.go
index 6c92b2e21f..fce59c9eda 100644
--- a/util/metrics/metrics.go
+++ b/util/metrics/metrics.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/metrics_test.go b/util/metrics/metrics_test.go
index 3f782d242f..c382b8e8cf 100644
--- a/util/metrics/metrics_test.go
+++ b/util/metrics/metrics_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/netdev_common.go b/util/metrics/netdev_common.go
index 8c644af842..60dea40eef 100644
--- a/util/metrics/netdev_common.go
+++ b/util/metrics/netdev_common.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/netdev_darwin.go b/util/metrics/netdev_darwin.go
index 0a629d1360..ce596cfc73 100644
--- a/util/metrics/netdev_darwin.go
+++ b/util/metrics/netdev_darwin.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/netdev_linux.go b/util/metrics/netdev_linux.go
index 7b12f15102..8b0c931c50 100644
--- a/util/metrics/netdev_linux.go
+++ b/util/metrics/netdev_linux.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/netdev_noop.go b/util/metrics/netdev_noop.go
index 74e8b83fb4..ba7292e444 100644
--- a/util/metrics/netdev_noop.go
+++ b/util/metrics/netdev_noop.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/opencensus.go b/util/metrics/opencensus.go
index bf8eb64e72..a15136937f 100644
--- a/util/metrics/opencensus.go
+++ b/util/metrics/opencensus.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -78,7 +78,7 @@ type statCounter struct {
// WriteMetric outputs Prometheus metrics for all labels/values in statCounter
func (st *statCounter) WriteMetric(buf *strings.Builder, parentLabels string) {
name := sanitizePrometheusName(st.name)
- counter := makeCounter(MetricName{name, st.description})
+ counter := MakeCounterUnregistered(MetricName{name, st.description})
for i := 0; i < len(st.labels); i++ {
counter.AddUint64(uint64(st.values[i]), st.labels[i])
}
@@ -87,14 +87,14 @@ func (st *statCounter) WriteMetric(buf *strings.Builder, parentLabels string) {
// AddMetric outputs all statCounter's labels/values into a map
func (st *statCounter) AddMetric(values map[string]float64) {
- counter := makeCounter(MetricName{st.name, st.description})
+ counter := MakeCounterUnregistered(MetricName{st.name, st.description})
for i := 0; i < len(st.labels); i++ {
counter.AddUint64(uint64(st.values[i]), st.labels[i])
}
counter.AddMetric(values)
}
-// statCounter stores single float64 sun value per stat with labels
+// statDistribution stores single float64 sun value per stat with labels
type statDistribution struct {
name string
description string
@@ -105,7 +105,7 @@ type statDistribution struct {
// WriteMetric outputs Prometheus metrics for all labels/values in statCounter
func (st *statDistribution) WriteMetric(buf *strings.Builder, parentLabels string) {
name := sanitizePrometheusName(st.name)
- gauge := makeGauge(MetricName{name, st.description})
+ gauge := MakeGaugeUnregistered(MetricName{name, st.description})
for i := 0; i < len(st.labels); i++ {
gauge.SetLabels(uint64(st.values[i]), st.labels[i])
}
@@ -114,7 +114,7 @@ func (st *statDistribution) WriteMetric(buf *strings.Builder, parentLabels strin
// AddMetric outputs all statCounter's labels/values into a map
func (st *statDistribution) AddMetric(values map[string]float64) {
- gauge := makeGauge(MetricName{st.name, st.description})
+ gauge := MakeGaugeUnregistered(MetricName{st.name, st.description})
for i := 0; i < len(st.labels); i++ {
gauge.SetLabels(uint64(st.values[i]), st.labels[i])
}
diff --git a/util/metrics/opencensus_test.go b/util/metrics/opencensus_test.go
index 74aa9a05cc..849aa5f076 100644
--- a/util/metrics/opencensus_test.go
+++ b/util/metrics/opencensus_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/prometheus.go b/util/metrics/prometheus.go
index 88d195d8b9..d6fa5bae33 100644
--- a/util/metrics/prometheus.go
+++ b/util/metrics/prometheus.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -75,7 +75,7 @@ func collectPrometheusMetrics(names []string) []Metric {
}
if _, ok := namesMap[metric.GetName()]; len(namesMap) > 0 && ok || len(namesMap) == 0 {
if metric.GetType() == iopc.MetricType_COUNTER && metric.GetMetric() != nil {
- counter := makeCounter(MetricName{metric.GetName(), metric.GetHelp()})
+ counter := MakeCounterUnregistered(MetricName{metric.GetName(), metric.GetHelp()})
ma := metric.GetMetric()
for _, m := range ma {
if m.GetCounter() == nil {
@@ -87,7 +87,7 @@ func collectPrometheusMetrics(names []string) []Metric {
}
result = append(result, counter)
} else if metric.GetType() == iopc.MetricType_GAUGE && metric.GetMetric() != nil {
- gauge := makeGauge(MetricName{metric.GetName(), metric.GetHelp()})
+ gauge := MakeGaugeUnregistered(MetricName{metric.GetName(), metric.GetHelp()})
ma := metric.GetMetric()
for _, m := range ma {
diff --git a/util/metrics/prometheus_test.go b/util/metrics/prometheus_test.go
index d186c1b79e..1eded61598 100644
--- a/util/metrics/prometheus_test.go
+++ b/util/metrics/prometheus_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/registry.go b/util/metrics/registry.go
index 5757455412..5b04ed1463 100644
--- a/util/metrics/registry.go
+++ b/util/metrics/registry.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/registryCommon.go b/util/metrics/registryCommon.go
index 752cc6e36b..c8a7538d99 100644
--- a/util/metrics/registryCommon.go
+++ b/util/metrics/registryCommon.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/registry_test.go b/util/metrics/registry_test.go
index 963365096d..b8f91a67ed 100644
--- a/util/metrics/registry_test.go
+++ b/util/metrics/registry_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -27,15 +27,22 @@ import (
func TestWriteAdd(t *testing.T) {
partitiontest.PartitionTest(t)
+ // create a non-default registry for the metrics in this test
+ registry := MakeRegistry()
+
// Test AddMetrics and WriteMetrics with a counter
- counter := MakeCounter(MetricName{Name: "gauge-name", Description: "gauge description"})
+ counter := MakeCounterUnregistered(MetricName{Name: "gauge-name", Description: "gauge description"})
+ counter.Register(registry)
+
counter.AddUint64(12, nil)
- labelCounter := MakeCounter(MetricName{Name: "label-counter", Description: "counter with labels"})
+ labelCounter := MakeCounterUnregistered(MetricName{Name: "label-counter", Description: "counter with labels"})
+ labelCounter.Register(registry)
+
labelCounter.AddUint64(5, map[string]string{"label": "a label value"})
results := make(map[string]float64)
- DefaultRegistry().AddMetrics(results)
+ registry.AddMetrics(results)
require.Equal(t, 2, len(results), "results", results)
require.Contains(t, results, "gauge-name")
@@ -44,19 +51,19 @@ func TestWriteAdd(t *testing.T) {
require.InDelta(t, 5, results["label-counter_label__a_label_value_"], 0.01)
bufBefore := strings.Builder{}
- DefaultRegistry().WriteMetrics(&bufBefore, "label")
+ registry.WriteMetrics(&bufBefore, "label")
require.True(t, bufBefore.Len() > 0)
- DefaultRegistry().AddMetrics(results)
+ registry.AddMetrics(results)
require.Contains(t, results, "gauge-name")
require.InDelta(t, 12, results["gauge-name"], 0.01)
// not included in string builder
bufAfter := strings.Builder{}
- DefaultRegistry().WriteMetrics(&bufAfter, "label")
+ registry.WriteMetrics(&bufAfter, "label")
require.Equal(t, bufBefore.String(), bufAfter.String())
- counter.Deregister(nil)
- labelCounter.Deregister(nil)
+ counter.Deregister(registry)
+ labelCounter.Deregister(registry)
}
diff --git a/util/metrics/reporter.go b/util/metrics/reporter.go
index 5eeeb55c59..65423691e0 100644
--- a/util/metrics/reporter.go
+++ b/util/metrics/reporter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -121,7 +121,11 @@ func (reporter *MetricReporter) waitForTimeStamp(ctx context.Context) bool {
func (reporter *MetricReporter) gatherMetrics() {
var buf strings.Builder
- DefaultRegistry().WriteMetrics(&buf, reporter.formattedLabels)
+ if reporter.serviceConfig.registry != nil {
+ reporter.serviceConfig.registry.WriteMetrics(&buf, reporter.formattedLabels)
+ } else {
+ DefaultRegistry().WriteMetrics(&buf, reporter.formattedLabels)
+ }
reporter.lastMetricsBuffer = buf
}
diff --git a/util/metrics/reporter_test.go b/util/metrics/reporter_test.go
index 2709a9413d..add4e1e781 100755
--- a/util/metrics/reporter_test.go
+++ b/util/metrics/reporter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/runtime.go b/util/metrics/runtime.go
index 9ea1833268..67b5c5ec9f 100644
--- a/util/metrics/runtime.go
+++ b/util/metrics/runtime.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/runtime_test.go b/util/metrics/runtime_test.go
index b451a88019..5949de2853 100644
--- a/util/metrics/runtime_test.go
+++ b/util/metrics/runtime_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/service.go b/util/metrics/service.go
index 919df94c03..03f1de3b28 100644
--- a/util/metrics/service.go
+++ b/util/metrics/service.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/serviceCommon.go b/util/metrics/serviceCommon.go
index 6c769f7fc1..fb7e800599 100644
--- a/util/metrics/serviceCommon.go
+++ b/util/metrics/serviceCommon.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -30,6 +30,7 @@ type ServiceConfig struct {
NodeExporterListenAddress string
Labels map[string]string
NodeExporterPath string
+ registry *Registry // if nil, will use DefaultRegistry(). Used for testing
}
// MetricService represent a single running metric server instance
diff --git a/util/metrics/tagcounter.go b/util/metrics/tagcounter.go
index 6ee08d6dff..0b427b0007 100644
--- a/util/metrics/tagcounter.go
+++ b/util/metrics/tagcounter.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/metrics/tagcounter_test.go b/util/metrics/tagcounter_test.go
index 8eafdca48d..12dec38933 100644
--- a/util/metrics/tagcounter_test.go
+++ b/util/metrics/tagcounter_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/process.go b/util/process.go
index 5b6c43574d..ecc06c5286 100644
--- a/util/process.go
+++ b/util/process.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/process_common.go b/util/process_common.go
index 6b58da56f1..d51a323cd7 100644
--- a/util/process_common.go
+++ b/util/process_common.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//go:build !windows
-// +build !windows
package util
diff --git a/util/process_windows.go b/util/process_windows.go
index a134e38e93..963f0e39a0 100644
--- a/util/process_windows.go
+++ b/util/process_windows.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//go:build windows
-// +build windows
package util
diff --git a/util/rateLimit.go b/util/rateLimit.go
index 3b089e4a1b..2bb13af97c 100644
--- a/util/rateLimit.go
+++ b/util/rateLimit.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -59,7 +59,7 @@ type ErlClient interface {
type capacity struct {
}
-// Capacity Queue wraps and maintains a channel of opaque capacity structs
+// capacityQueue wraps and maintains a channel of opaque capacity structs
type capacityQueue chan capacity
// ErlCapacityGuard is the structure returned to clients so they can release the capacity when needed
diff --git a/util/rateLimit_test.go b/util/rateLimit_test.go
index 5a62cac5b5..16d28ff020 100644
--- a/util/rateLimit_test.go
+++ b/util/rateLimit_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/s3/fileIterator.go b/util/s3/fileIterator.go
index d293c2e4f6..0e4a4b9462 100644
--- a/util/s3/fileIterator.go
+++ b/util/s3/fileIterator.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/s3/s3Helper.go b/util/s3/s3Helper.go
index 45da896659..923dc6cbb8 100644
--- a/util/s3/s3Helper.go
+++ b/util/s3/s3Helper.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/s3/s3Helper_test.go b/util/s3/s3Helper_test.go
index 32e4c58f8a..5303f6628b 100644
--- a/util/s3/s3Helper_test.go
+++ b/util/s3/s3Helper_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/set.go b/util/set.go
index e6ea6a6927..655f0ca1d0 100644
--- a/util/set.go
+++ b/util/set.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/set_test.go b/util/set_test.go
index 34e9e48994..03da2c912e 100644
--- a/util/set_test.go
+++ b/util/set_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/sleep.go b/util/sleep.go
index 9059025f04..9290b43be5 100644
--- a/util/sleep.go
+++ b/util/sleep.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//go:build !linux
-// +build !linux
package util
diff --git a/util/sleep_linux.go b/util/sleep_linux.go
index 8f7f188e8b..009672dcf1 100644
--- a/util/sleep_linux.go
+++ b/util/sleep_linux.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/sleep_linux_32.go b/util/sleep_linux_32.go
index cd8156371e..408b20c169 100644
--- a/util/sleep_linux_32.go
+++ b/util/sleep_linux_32.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,8 +15,6 @@
// along with go-algorand. If not, see .
//go:build linux && (arm || 386)
-// +build linux
-// +build arm 386
package util
diff --git a/util/sleep_linux_64.go b/util/sleep_linux_64.go
index 6a2c90fec8..1d9eeb6e2a 100644
--- a/util/sleep_linux_64.go
+++ b/util/sleep_linux_64.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//go:build linux && !(arm || 386)
-// +build linux,!arm,!386
package util
diff --git a/util/tcpinfo.go b/util/tcpinfo.go
index 5771278ccd..f91910edcf 100644
--- a/util/tcpinfo.go
+++ b/util/tcpinfo.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/tcpinfo_darwin.go b/util/tcpinfo_darwin.go
index fb7dc93b86..7968616cc5 100644
--- a/util/tcpinfo_darwin.go
+++ b/util/tcpinfo_darwin.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/tcpinfo_linux.go b/util/tcpinfo_linux.go
index 31323e6dcc..7b79114f71 100644
--- a/util/tcpinfo_linux.go
+++ b/util/tcpinfo_linux.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/tcpinfo_noop.go b/util/tcpinfo_noop.go
index 6576a7f20f..705c82ff5d 100644
--- a/util/tcpinfo_noop.go
+++ b/util/tcpinfo_noop.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//go:build !linux && !darwin
-// +build !linux,!darwin
package util
diff --git a/util/timers/frozen.go b/util/timers/frozen.go
index 671d8e0a9b..168ab24c0a 100644
--- a/util/timers/frozen.go
+++ b/util/timers/frozen.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/timers/interface.go b/util/timers/interface.go
index d3cbebe62f..31b809fb27 100644
--- a/util/timers/interface.go
+++ b/util/timers/interface.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/timers/monotonic.go b/util/timers/monotonic.go
index 0ea4f7ec04..9dfd4323ab 100644
--- a/util/timers/monotonic.go
+++ b/util/timers/monotonic.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/timers/monotonic_test.go b/util/timers/monotonic_test.go
index 5a89c5cdee..e7871493c9 100644
--- a/util/timers/monotonic_test.go
+++ b/util/timers/monotonic_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/tokens/tokens.go b/util/tokens/tokens.go
index f71a3750cd..2a7f409182 100644
--- a/util/tokens/tokens.go
+++ b/util/tokens/tokens.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/util.go b/util/util.go
index 74c8d2e219..d383d4c7db 100644
--- a/util/util.go
+++ b/util/util.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
@@ -15,7 +15,6 @@
// along with go-algorand. If not, see .
//go:build !windows
-// +build !windows
package util
diff --git a/util/util_darwin.go b/util/util_darwin.go
index 7c08acdefe..4d0c901618 100644
--- a/util/util_darwin.go
+++ b/util/util_darwin.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/util_linux.go b/util/util_linux.go
index f958ebdf5c..d8d5fbc63f 100644
--- a/util/util_linux.go
+++ b/util/util_linux.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/util_test.go b/util/util_test.go
index f33b5c5f95..1ad4cbcd67 100644
--- a/util/util_test.go
+++ b/util/util_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/util_windows.go b/util/util_windows.go
index 392a5698e5..658e2e448b 100644
--- a/util/util_windows.go
+++ b/util/util_windows.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/uuid/uuid.go b/util/uuid/uuid.go
index 3ec271518c..28d8af4ac0 100644
--- a/util/uuid/uuid.go
+++ b/util/uuid/uuid.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/uuid/uuid_test.go b/util/uuid/uuid_test.go
index aa7cd8a3ca..4ac3667cdb 100644
--- a/util/uuid/uuid_test.go
+++ b/util/uuid/uuid_test.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
diff --git a/util/watchdogStreamReader.go b/util/watchdogStreamReader.go
index 0d60a95580..95217dc3e9 100644
--- a/util/watchdogStreamReader.go
+++ b/util/watchdogStreamReader.go
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2025 Algorand, Inc.
+// Copyright (C) 2019-2026 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify