diff --git a/.golangci.yml b/.golangci.yml index 44fba83682..40299509bf 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -31,11 +31,6 @@ linters-settings: require-explanation: true errcheck: exclude-functions: - # data/transactions/logic/assembler.go uses ops.error, warn, to append log messages: OK to ignore for this case - - (*github.com/algorand/go-algorand/data/transactions/logic.OpStream).errorf - - (*github.com/algorand/go-algorand/data/transactions/logic.OpStream).error - - (*github.com/algorand/go-algorand/data/transactions/logic.OpStream).warnf - - (*github.com/algorand/go-algorand/data/transactions/logic.OpStream).warn # We do this 121 times and never check the error. - (*github.com/spf13/cobra.Command).MarkFlagRequired govet: @@ -62,9 +57,6 @@ linters-settings: - (github.com/algorand/go-algorand/logging.Logger).Error - (github.com/algorand/go-algorand/logging.Logger).Fatal - (github.com/algorand/go-algorand/logging.Logger).Panic - - (github.com/algorand/go-algorand/data/transactions/logic.OpStream).warnf - - (github.com/algorand/go-algorand/data/transactions/logic.OpStream).errorf - - (github.com/algorand/go-algorand/data/transactions/logic.OpStream).lineErrorf - (github.com/algorand/go-algorand/cmd/goal/main).reportInfof - (github.com/algorand/go-algorand/cmd/goal/main).reportInfoln - (github.com/algorand/go-algorand/cmd/goal/main).reportWarnf diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..966aa2cf9a --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +conduct@algorand.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/Makefile b/Makefile index d17855e6dc..450ab6999c 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,13 @@ ARCH := $(shell ./scripts/archtype.sh) OS_TYPE := $(shell ./scripts/ostype.sh) S3_RELEASE_BUCKET = $$S3_RELEASE_BUCKET +GOLANG_VERSIONS := $(shell ./scripts/get_golang_version.sh all) +GOLANG_VERSION_BUILD := $(firstword $(GOLANG_VERSIONS)) +GOLANG_VERSION_SUPPORT := $(lastword $(GOLANG_VERSIONS)) +GOLANG_VERSION_BUILD_MAJOR := $(shell echo $(GOLANG_VERSION_BUILD) | cut -d'.' -f1,2) +CURRENT_GO_VERSION := $(shell go version | cut -d " " -f 3 | tr -d 'go') +CURRENT_GO_VERSION_MAJOR := $(shell echo $(CURRENT_GO_VERSION) | cut -d'.' -f1,2) + # If build number already set, use it - to ensure same build number across multiple platforms being built BUILDNUMBER ?= $(shell ./scripts/compute_build_number.sh) FULLBUILDNUMBER ?= $(shell ./scripts/compute_build_number.sh -f) @@ -101,10 +108,19 @@ fix: build lint: deps $(GOPATH1)/bin/golangci-lint run -c .golangci.yml +check_go_version: + @if [ $(CURRENT_GO_VERSION_MAJOR) != $(GOLANG_VERSION_BUILD_MAJOR) ]; then \ + echo "Wrong major version of Go installed ($(CURRENT_GO_VERSION_MAJOR)). Please use $(GOLANG_VERSION_BUILD_MAJOR)"; \ + exit 1; \ + fi + +tidy: check_go_version + go mod tidy -compat=$(GOLANG_VERSION_SUPPORT) + check_shell: find . -type f -name "*.sh" -exec shellcheck {} + -sanity: fix lint fmt +sanity: fix lint fmt tidy cover: go test $(GOTAGS) -coverprofile=cover.out $(UNIT_TEST_SOURCES) @@ -186,7 +202,7 @@ rebuild_kmd_swagger: deps # develop -build: buildsrc +build: buildsrc buildsrc-special # We're making an empty file in the go-cache dir to # get around a bug in go build where it will fail @@ -197,6 +213,10 @@ buildsrc: check-go-version crypto/libs/$(OS_TYPE)/$(ARCH)/lib/libsodium.a node_e touch "${GOCACHE}"/file.txt && \ go install $(GOTRIMPATH) $(GOTAGS) $(GOBUILDMODE) -ldflags="$(GOLDFLAGS)" ./... +buildsrc-special: + cd tools/block-generator && \ + go install $(GOTRIMPATH) $(GOTAGS) $(GOBUILDMODE) -ldflags="$(GOLDFLAGS)" ./... + check-go-version: ./scripts/check_golang_version.sh build diff --git a/cmd/opdoc/opdoc.go b/cmd/opdoc/opdoc.go index acd110d36f..b5e039a2b8 100644 --- a/cmd/opdoc/opdoc.go +++ b/cmd/opdoc/opdoc.go @@ -91,7 +91,7 @@ func namedStackTypesMarkdown(out io.Writer, stackTypes []namedType) { for _, st := range stackTypes { fmt.Fprintf(out, "| %s | %s | %s |\n", st.Name, st.boundString(), st.AVMType) } - out.Write([]byte("\n")) + fmt.Fprintf(out, "\n") } func integerConstantsTableMarkdown(out io.Writer) { diff --git a/config/consensus.go b/config/consensus.go index d4e1890a8a..4f4680c5e6 100644 --- a/config/consensus.go +++ b/config/consensus.go @@ -679,7 +679,7 @@ func (cp ConsensusProtocols) Merge(configurableConsensus ConsensusProtocols) Con for cVer, cParam := range staticConsensus { if cVer == consensusVersion { delete(staticConsensus, cVer) - } else if _, has := cParam.ApprovedUpgrades[consensusVersion]; has { + } else { // delete upgrade to deleted version delete(cParam.ApprovedUpgrades, consensusVersion) } diff --git a/config/migrate.go b/config/migrate.go index 35b4ec82fb..11c8aa108a 100644 --- a/config/migrate.go +++ b/config/migrate.go @@ -128,9 +128,6 @@ func getLatestConfigVersion() uint32 { } func getVersionedDefaultLocalConfig(version uint32) (local Local) { - if version < 0 { - return - } if version > 0 { local = getVersionedDefaultLocalConfig(version - 1) } diff --git a/daemon/algod/api/algod.oas2.json b/daemon/algod/api/algod.oas2.json index 0adcc18c8b..dfeaaa01b6 100644 --- a/daemon/algod/api/algod.oas2.json +++ b/daemon/algod/api/algod.oas2.json @@ -2661,14 +2661,14 @@ "description": "Contains a ledger delta for a single transaction group", "type": "object", "required": [ - "delta", - "ids" + "Delta", + "Ids" ], "properties": { - "delta": { + "Delta": { "$ref": "#/definitions/LedgerStateDelta" }, - "ids": { + "Ids": { "type": "array", "items": { "type": "string" @@ -4045,10 +4045,10 @@ "schema": { "type": "object", "required": [ - "deltas" + "Deltas" ], "properties": { - "deltas": { + "Deltas": { "type": "array", "items": { "$ref": "#/definitions/LedgerStateDeltaForTransactionGroup" diff --git a/daemon/algod/api/algod.oas3.yml b/daemon/algod/api/algod.oas3.yml index 1acacc4daa..2c65bdde11 100644 --- a/daemon/algod/api/algod.oas3.yml +++ b/daemon/algod/api/algod.oas3.yml @@ -862,7 +862,7 @@ "application/json": { "schema": { "properties": { - "deltas": { + "Deltas": { "items": { "$ref": "#/components/schemas/LedgerStateDeltaForTransactionGroup" }, @@ -870,7 +870,7 @@ } }, "required": [ - "deltas" + "Deltas" ], "type": "object" } @@ -1743,10 +1743,10 @@ "LedgerStateDeltaForTransactionGroup": { "description": "Contains a ledger delta for a single transaction group", "properties": { - "delta": { + "Delta": { "$ref": "#/components/schemas/LedgerStateDelta" }, - "ids": { + "Ids": { "items": { "type": "string" }, @@ -1754,8 +1754,8 @@ } }, "required": [ - "delta", - "ids" + "Delta", + "Ids" ], "type": "object" }, @@ -4152,7 +4152,7 @@ "application/json": { "schema": { "properties": { - "deltas": { + "Deltas": { "items": { "$ref": "#/components/schemas/LedgerStateDeltaForTransactionGroup" }, @@ -4160,7 +4160,7 @@ } }, "required": [ - "deltas" + "Deltas" ], "type": "object" } @@ -4168,7 +4168,7 @@ "application/msgpack": { "schema": { "properties": { - "deltas": { + "Deltas": { "items": { "$ref": "#/components/schemas/LedgerStateDeltaForTransactionGroup" }, @@ -4176,7 +4176,7 @@ } }, "required": [ - "deltas" + "Deltas" ], "type": "object" } diff --git a/daemon/algod/api/server/v2/generated/data/routes.go b/daemon/algod/api/server/v2/generated/data/routes.go index 03aa23d8c8..7d29827051 100644 --- a/daemon/algod/api/server/v2/generated/data/routes.go +++ b/daemon/algod/api/server/v2/generated/data/routes.go @@ -172,122 +172,122 @@ var swaggerSpec = []string{ "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", - "AAD//yvhnHBdywAA", + "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", + "AQAA//+92+QcXcsAAA==", } // 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 0d4e810054..e253331bf2 100644 --- a/daemon/algod/api/server/v2/generated/experimental/routes.go +++ b/daemon/algod/api/server/v2/generated/experimental/routes.go @@ -133,117 +133,117 @@ var swaggerSpec = []string{ "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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 50fe884e3c..3589e9e117 100644 --- a/daemon/algod/api/server/v2/generated/model/types.go +++ b/daemon/algod/api/server/v2/generated/model/types.go @@ -542,8 +542,8 @@ type LedgerStateDelta = map[string]interface{} // LedgerStateDeltaForTransactionGroup Contains a ledger delta for a single transaction group type LedgerStateDeltaForTransactionGroup struct { // Delta Ledger StateDelta object - Delta LedgerStateDelta `json:"delta"` - Ids []string `json:"ids"` + Delta LedgerStateDelta `json:"Delta"` + Ids []string `json:"Ids"` } // LightBlockHeaderProof Proof of membership and position of a light block header. @@ -1090,7 +1090,7 @@ type SupplyResponse struct { // TransactionGroupLedgerStateDeltasForRoundResponse defines model for TransactionGroupLedgerStateDeltasForRoundResponse. type TransactionGroupLedgerStateDeltasForRoundResponse struct { - Deltas []LedgerStateDeltaForTransactionGroup `json:"deltas"` + Deltas []LedgerStateDeltaForTransactionGroup `json:"Deltas"` } // TransactionParametersResponse TransactionParams contains the parameters that help a client construct 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 e4ec6dd160..41fef3739d 100644 --- a/daemon/algod/api/server/v2/generated/nonparticipating/private/routes.go +++ b/daemon/algod/api/server/v2/generated/nonparticipating/private/routes.go @@ -188,123 +188,123 @@ var swaggerSpec = []string{ "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", - "b43ZywAA", + "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", + "Qz/sGdnLAAA=", } // 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 6c99f788e9..8eb9f99c11 100644 --- a/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go +++ b/daemon/algod/api/server/v2/generated/nonparticipating/public/routes.go @@ -760,195 +760,195 @@ var swaggerSpec = []string{ "auwJsXF76YLyOUroUpRzFzhmx0EOWyprC5El7wwRlWL0midoVY5xXBcs7BM0jPwC1OhQbZO01RguaDWf", "y8kZchX6nYuY6KNeqfGoV8U0SF3VKqZFTjPLZAD3bQhYAX7qiQf6LhB1Rtjo4ivcFkO9ZnOvx0ZeDx2D", "sjtxEMpWP+yLZjP6bb45gJRhByISCgkK74TQLqTsUzELM8rcpaE2SsOyazq3n/7Wc/xe9ypogueMQ7IU", - "HDbRJGrG4Ud8GD1OeC/1fIwSQt+3baG/AX8LrOY8Q6jxqvjF3W6f0LaLSH0r5KF8kM6VNFSeHuDy2+nf", - "dlNe1jFJ8zziy3P5Jm0GoMZVfjuThColUoZC0mmmxvagOfefS05pov9VFUV7gLPXHrfltApTGdEoC3lB", - "KElzhiZbwZWWZarfcopGoWCpkWgjr/32mwmf+VfidsmI2dAN9ZZTjDSrTEXRCIkZROwi3wJ4a6Eq53NQ", - "uqVczADecvcW46TkTONcS3NcEnteCpAY8jOxby7phswMTWhB/gApyLTUTXEb06mUZnnuPGhmGiJmbznV", - "JAeqNPmR8bM1Due97P7IctAXQp5XWIjf7nPgoJhK4lFR39mnGLDqlr9wwauY/m4fW5+LGb/OudqgzahO", - "6f6/d//r+NeT5H9p8seD5Mv/OHr3/smHe/c7Pz768NVX/6/50+MPX937r3+P7ZSHPZbs4yA/fe5U0dPn", - "qG/UTpcO7DdmcF8ynkSJLAyfaNEWuYuJrY6A7jWtUXoBb7lec0NIK5qzzPCWy5BD+4bpnEV7OlpU09iI", - "lvXJr3VPKf4KXIZEmEyLNV5aiuoGEsbT6tAL6DLl8LzMSm630kvfNmvEB3SJ2bhKnbRVVY4J5tUtqI9G", - "dH8+evrFaFznw1XPR+ORe/ouQsksW8eyHjNYx5Qzd0DwYNxRpKAbBTrOPRD2aOyaDaYIh12C0erVghU3", - "zymUZtM4h/Ox+M7Is+an3AbJm/ODPsWNc1WI2c3DrSVABoVexKotNAQ1fKveTYBWnEchxQr4mLAJTNpG", - "lszoiy6KLgc6w6x/1D7FEG2oOgeW0DxVBFgPFzLIkhGjHxR5HLf+MB65y18dXB1yA8fgas9ZORD931qQ", - "O999c0aOHMNUd2wCrh06SJmMqNIuK6gRAWS4ma0xY4W8t/wtfw4zxpl5fvyWZ1TToylVLFVHpQL5Nc0p", - "T2EyF+TYJxo9p5q+5R1Jq7cMVJDiRYpymrOUnIcKSU2etrRHd4S3b3+l+Vy8ffuuEwzRVR/cVFH+YidI", - "jCAsSp24wgSJhAsqY84mVSWm48i28si2Wa2QLUprkfSFD9z4cZ5Hi0K1E1S7yy+K3Cw/IEPl0i/NlhGl", - "hfSyiBFQLDS4vy+FuxgkvfB2lVKBIr8vafEr4/odSd6WDx48BtLI2PzdXfmGJjcFDLau9CbQto0quHCr", - "VsJaS5oUdB7zab19+6sGWuDuo7y8RBtHnhP8rJEp6iPhcah6AR4f/Rtg4dg76w0X98Z+5YtQxZeAj3AL", - "8R0jbtSe9svuV5A7euntauWfdnap1IvEnO3oqpQhcb8zVW2auRGyfPiDYnPUVl0ZnymQdAHpuauvAstC", - "b8aNz32EjRM0PetgylbesZlfWPsBPQJTIGWRUSeKU75pJ+Er0NrH8b6Gc9icibp0xD5Z980kcNV3UJFS", - "A+nSEGt4bN0Y7c13YVyo2BeFz6XGpDpPFscVXfhv+g+yFXkPcIhjRNFIUu5DBJURRFji70HBJRZqxrsS", - "6ceWZ7SMqb35IlV4PO8n7pVaeXIRV+Fq0Opuny8By3iJC0Wm1MjtwlWgsonOARcrFZ1Dj4QcOmUGphM3", - "HDk4yK57L3rTiVn7QuvcN1GQ7cuJWXOUUsA8MaSCykwrzs7PZP1+zjOBhSUdwqY5iklVQKJlOlQ2nGO2", - "Ul4faHECBslrgcOD0cRIKNksqPLFsbCGmD/Lg2SAa0zc31au5TQIEQsKhVXFWDzPbZ/Tjnbpirb4Si2+", - "PEuoWg4otWIkfIxKj22H4CgAZZDD3C7cvuwJpS4iUG+QgeOn2SxnHEgSizYLzKDBNePmACMf3yfEWuDJ", - "4BFiZByAjf5sHJi8FOHZ5PN9gOSuCAL1Y6MnPPgb4vlaNv7aiDyiMCyc9Xi1Us8BqAtRrO6vVqAsDkMY", - "HxPD5lY0N2zOaXz1IJ2qISi2tmqEuIiKe33i7BYHiL1Y9lqTvYous5pQZvJAxwW6LRBPxTqxCZtRiXe6", - "nhp6j4akY/po7GDa+ix3FJmKNUbp4NViQ6B3wNIPhwcj0PDXTCG94nd9t7kFZtu026WpGBUqJBlnzqvI", - "pU+cGDJ1jwTTRy53g5IrlwKgZeyo6xc75XenktoUT7qXeX2rjetSYj7bJ3b8+45QdJd68Ne1wlRFUl61", - "JZaonaIZbNKsDxOIkDGiN2yi66TpuoIU5IBKQdIQopLzmOfU6DaAN84b/1lgvMAqNJRv7gURTBLmTGmo", - "jeg+TuJjmCcpFr8TYta/Ol3ImVnfayGqa8q6EfHDxjJvfAUYAjxjUukEPRDRJZiXvlWoVH9rXo3LSs0Y", - "KVsqlmVx3oDTnsMmyVhexunVzfvDczPty4olqnKK/JZxG7AyxdLG0cjJLVPb4NqtC35hF/yCHmy9w06D", - "edVMLA25NOf4TM5Fi/NuYwcRAowRR3fXelG6hUEGGa9d7hjITYGPf7LN+to5TJkfe2fUjs+77buj7EjR", - "tQQGg62rYOgmMmIJ00Fl4G4qas8ZoEXBsnXLFmpH7dWY6V4GD19PrYUF3F032A4MBHbPWDaMBNUsnVcL", - "+LbGc6NyzWQQZs6aBe5ChhBOxZTvUNBFVJUttwtXZ0DzH2Dzi3kXlzP6MB5dzXQaw7UbcQeuX1XbG8Uz", - "uuatKa3hCdkT5bQopFjRPHEG5j7SlGLlSBNf9/boG2Z1cTPm2TcnL1458D+MR2kOVCaVqNC7Knyv+GxW", - "Zav09RwQXwHd6HxeZreiZLD5VWmx0Ch9sQBXSjqQRjs1L2uHQ3AUnZF6Fo8Q2mlydr4Ru8QtPhIoKhdJ", - "bb6zHpKmV4SuKMu93cxD2xPNg4sbVjg1yhXCAa7sXQmcZMlB2U3ndMdPR01dO3hSONeWYtdLW89dEcHb", - "LnSMed4Uzuu+pFix0lpFusyJl0u0JCQqZ2ncxsqnyhAHt74z8zLBl3uEUTNiyXpcsbxkwVjmtSE1aVpA", - "BnNEkamiZXFq3E2F69VTcvavEgjLgGvzSOKpbB1ULG/irO3d69TIDt253MDWQl8PfxUZI6zW2r7xEIjt", - "AkboqeuA+7xSmf1CK4uU+SFwSezh8A9n7FyJW5z1jj4cNdvgxUXT4xa21unyP0MYtsb67r4+Xnl1ZWN7", - "5oj26WEqmUnxB8T1PFSPI4lGvj4twyiXPyBMdAi7UzRYTGXdqdsN1bP3bnefdBNaoZpBCj1UjzsfuOWw", - "UKa3UFNut9q2zWjEusUJJowqPbLj1wTjYO5E4ub0YkpjVUSNkGFgOqkdwA1buhbEf+xxr6psCzs7CXzJ", - "1bvMJpEXIOscwG5BmksKDHbawaJCLRkg1YYywdj6/3IlIsOU/IJy233FfGePkvtagTV+ma8uhMQSECpu", - "9s8gZUuaxyWHLO2aeDM2Z7axSKkg6FzhBrJNmywVue4fVQ6RQ83pjDwYB+1z3G5kbMUUm+aAbzy0b0yp", - "Qk5eGaKqT8zygOuFwtcfDXh9UfJMQqYXyiJWCVIJdajeVM6rKegLAE4e4HsPvyR30W2n2AruGSy6+3l0", - "/PBLNLraPx7ELgDXGGYbN8mQnfzdsZM4HaPf0o5hGLcbdRLNlred4foZ15bTZD8dcpbwTcfrdp+lJeV0", - "DvFIkeUOmOy3uJtoSGvhhWe2rZHSUmwI0/H5QVPDn3qizw37s2CQVCyXTC+dc0eJpaGnui2FndQPZ3sk", - "uYrCHi7/EH2khXcRtZTImzWa2vsttmr0ZL+kS2iidUyorfuRszp6wdc5J6e+rBCWWK4qK1vcmLnM0lHM", - "wWCGGSkk4xoVi1LPkr+RdEElTQ37m/SBm0y/eBIpK90sb8r3A/zG8S5BgVzFUS97yN7LEO5bcpcLniwN", - "R8nu1dkewansdebG3XZ9vsPtQw8VyswoSS+5lQ1yowGnvhLh8S0DXpEUq/XsRY97r+zGKbOUcfKgpdmh", - "n1+/cFLGUshYrcD6uDuJQ4KWDFYYuxffJDPmFfdC5oN24SrQf1zPgxc5A7HMn+WYIvC1iGinvtR5ZUl3", - "seoR60DfMTUPDBlM3VBj0iwrffN89DBRUHFPlzdsdx1b5onHA/7RRsRHJhfcwNqXb1fSQyhBWf0oyWTV", - "88DHTsnXYj2UcFqn0BPPJ4CiKEpKlme/1Jmfra4FkvJ0EfWZTc2Hv9X91arF2TswWvZvQTmHPDqclTd/", - "83JpRHL+pxg6z5Lxge+2GynY5bYWVwPeBNMD5Sc06GU6NxOEWG0m1VVB2/lcZATnqWvM1ce124AjKJP+", - "rxKUjiUo4QMbOIa2UcMObJVuAjxDjXRCvrMtlBdAGgWEUBP0lSKaWdNlkQuajbGCxdk3Jy+IndV+Y7sE", - "2Srhc1SEmqto2cSC8pnDQpB9w594esTwcbbHa5tVK51URb1jCajmjbrsOGv5CVBFCrEzIc+DZqg2V9UM", - "YehhxuTSaHXVaFY+Qpow/9GapgtU+xqstZ/kh5e391SpgpaSVWuoqqYknjsDt6twbwvcj4kwuvkFU7Zz", - "LqygmfNaJYA7s4PPgW0uT5acW0qZ7HHLVRUk90W7B85ekd6VEIWshfg9hX7bHWLfav9v8Ktoiat264BO", - "L0mbQVm1/PEd0VPKBWcpFpiKXdGuxe4QP9uAWlxtQ64/4u6ERg5XtGFBFYrnsNjbwsAzQoe4rqE/eGo2", - "1VKH/VNjL9cF1WQOWjnOBtnY991wtkbGFbgaodiQOeCTQjZ8l8gho+7wpHKb7ElGmHrTozx+a569dKYF", - "jEk/ZxyVCIc2J/hZayB2ANVG82CazAUot55m/rH61XwzwVTcDNbvJr5jKI5hXX9m2dbP3R3qxHu9nZfZ", - "vPvMvOsKJFU/N6Kc7aQnReEm7e/KEpUH9Jr3IjjivUy8+yhAbjV+ONoWctsaroL3qSE0WKGzGwq8hzuE", - "UXUoaXW/MkKrpSh8g9gwsWiVBMYjYLxgHOp+tpELIo1eCbgxeF57vlOppNqKgIN42hnQHD3cMYamtHNv", - "XHWodnkogxJco5+jfxvr5io9jKN6oRbcKN9UbXQNdQfCxDPs3+0Q2W2VglKVE6IyzFpoNU+JMQ7DuH17", - "puYF0D0GXZnIfq4ltSdnn5uoLxF1WmZz0AnNsljJ1q/xKcGnJCtRcoA1pGVV2rMoSIp1V5qFaLrU5iZK", - "BVflcstc/oUrThd0I4pQQ9gRye8wJrpMN/hvrK5l/864QI+9Qw19VMee1Ze6oZMxqdfQdKLYPBmOCbxT", - "ro6OeurLEXr9/UEpPRfzJiA3XH5iazGsYI9i/O0bc3GE1Rk6xVrt1VIVT8DAPuF7SKLaWKX9tkp/UU27", - "1VvRoVT1qNtugOjvNjfGy68nvDcoukHt/Wo9lH1BvmlvTDrVLjtOU7KVBfVmHNkIIZtbhFDErbN9UUE2", - "KMg87nw9TDLsyNk6XvgwQKgPN+sC9IOPZSUFZc79XjOLLmZd1Hs3D2FIPGy9we1FuFjyXovdD6u+uG9f", - "jA2ft7tRnYNLmS8krJgovWPbRz55ldD+2ujtVEXeR9ffNbziVB/XHNprvD1zXQHsMp1O/sMvNk6OANdy", - "8wmYcjub3ulz1ZV2rXmqfoVUBaUHFZhu3IpDChXGauI52bDRaWtHn7AuYx0iDnT7fo1HLNvrwozVVRzZ", - "UWLHLt7Fq7/sVF1qCo9YIRSr67rH2nsNDDE8ww5dQdms7lg+vmcFqcZi/nXcggTYp4iWmSxoGHpbfqpH", - "na4iMV3VqW2lproV/Hfc8Z1ssCCj0VY/nwwvrHRSRachn8ZqyHPgrmdnM89jcLT5bAapZqsd2Xd/XwAP", - "MrvG3i5je28HyXisil7G4i37Wx1rgLYlx22FJyiieGVw+nJvzmFzR5EGNUTLsY/9VXuZuh2IAeQOiSER", - "oWLRH9aQ7BzyTFWUgVjw0Vb2c6groPV2cgpySS85lydJc3HU+aVbpoy3khk0l/l0r6xrDMTtS9DrdqLo", - "1z+eY+MPVXVZ9HU/Qi2dnHarI164uiGYK1n5TnwFEVD+N58YbWfJ2TmEvabQU3VBZebfiJpevFUn2XIf", - "dbLqfBeFNtCzamZWx8Z286gi9bYwAjrNhREjkr4w8mY4ahXLcUfZoBtb/h0DbQ1cM5CuJx/Kv7lQkGjh", - "Y2m3wbENFTay6FJIUL01Li1wvZVnXteldbDWL8VKM9QFFIULJBKW1EAngwI4/XNuQ/Yz+9wnDvlarzst", - "TBW97m464KOimeogMaT6GXG35e6EpMsYmxjntu+zilXD4SCb3pBCiqxM7QUdHozKIDe41tQWVhK106Td", - "VbZ0hCCr8xw2R1YJ8t0a/A6GQFvJyYIeVFFobfJBzW8qBvf8IOB9TMvVeFQIkSc9zo7TbgmfNsWfs/Qc", - "MmJuCh892NP5htxFG3vlzb5YbHzJmqIADtm9CSEn3MZre8d2s4Z0a3J+R2+bf42zZqWtquWMapO3PB74", - "ivWu5BW5mR9mOw9TYFjdFaeyg+woELPuKR8k6UWkD9RkqFbedTW3e/PURGWhiMkkdduZHXEyVYhM3fmj", - "DpPpSgd5Li4SpKKkqv8V0znMe00m6Sue1p8ZbE8hiLehyl2gG7KgGUmFlJCGX8RTHCxQSyEhyQWG38Q8", - "gzNt5KElxjVzkos5EYVRc20ZPe9DibalCeayabb2y8Q6anoKGYByabVuGvtyd54t3Wv274xztojYWxDR", - "Hst7t79xhLJ314oAzAEEutvWdBLr7tNcV7s/VF+3Ni2WLI2j+/OKMumNDdnRuyiyvoocXWslnxXYg6uo", - "y3a7h9T2oZsO9ZNWNZMHHosAgH7PaQOGQf7TfcGYYV/HhEaQfFpJreNG213WOvu+np2l8ZRarXUBxIxd", - "SnBZarYBXatzTkH1wt9i5vWubmn0FFCYQmbbf1BlLSHeIuO637XFA1EkOayg4VB2qXNlmoJSbAVh5zz7", - "MckACrRPtqXmmKc05HItUcqtPQl8bUOwG5WtLGLtTpEdglNUzFvzxB4TNfQoGYhWLCtpA3/qCr3I+tqQ", - "Rdiwh3Ugp9ibScQXt41F7IxtQJqPnkseD20IMzcrowjOllXGU0uE9clWBb3g/UpExO5U+duvvg6CgxHV", - "yqTuvfJltSuXVSB7KWMbYXT6B0ZlDgW+/2tY9MSLW+7biIxlTV1MRQZgqj7PGL0HdXRY8NqSbkjGZjOQ", - "1pivNOUZlVn4OuMkBakpM5rNRl1erDXQyhLGOyVbw11xUM9gYjIu2qUsIPnGqQxXkDrRcxOROO1Vq0Vf", - "i8TOrsTTCejaSNcYV9VDBC4RGmVre8AERwGJLOk57DmPYn/A9mmwPImz/WmBsw6ZIuZrvWRttUGsuxuG", - "ELndgmaI2z1DYenFOqdL2mgWtCT7C7JN4z/WF+ewtoz+gx3ghQ7DoDGjt904cD5yctSPFVKCpbzro4TG", - "8nf5IN0Ca0kj2CLHCLQGWwjXBtQ39yVwMKtnld+2r4do272LdRYFt03+Om5hy5ts176AcMxZkCua37xr", - "FwtwniA+IHvdbwwOfYMhki0q1eUyE17QQXMHfsDDTc1foSv672D2KKqVuqGcCFOJ9T6YB28WmlvDxcy3", - "8FoBJxc4po1je/gFmbrM7UJCylRbNLrw3TUqVxg2m3LZIGu9w/e2a52/CH0FMp55TYO8rCv1o44/5zWE", - "9RH9yEyl5+RGqTxGfR2yiOAvxqPCEmo7rovzRoCb7XzSytwQEg4c6BaErO8Z6NYtDjd0eTaYy1w6pYLu", - "Ogff1g3cRi7qem1DozS7yN1Wzn1IcGW8S4P5HKM7LUKwxQlBUMnvD38nEmbYw1CQ+/dxgvv3x+7V3x81", - "H5vjfP9+VDq7sbhOiyM3hps3RjG/9GX62Wy2nqTS1n6ULM92EUYjRbjuAopJsL+5QgQfpQ/pbzbWpHtU", - "XS+4KwTIWcRE1tqYPJgqSP4dkPfrPotk+aIfJy0l0xusj+jtB+y3aATqd1U0k4uGq/RDd/dpcQ5Vhc06", - "9qlU/nb9TtAc7yOrtnJzC4l8Qr5Z02WRgzsoX92Z/ic8/tuT7MHjh/85/duDpw9SePL0ywcP6JdP6MMv", - "Hz+ER397+uQBPJx98eX0UfboyaPpk0dPvnj6Zfr4ycPpky++/M87hg8ZkC2gI1+NZ/Q/2Kw3OXl1mpwZ", - "YGuc0IL9ABvbF9CQse84SFM8ibCkLB8d+5/+jz9hk1Qs6+H9ryNX7GO00LpQx0dHFxcXk/CTozkGOyRa", - "lOniyM/TaUl48uq08hJZKxDuqM2T9dY9Twon+Oz1N2/OyMmr00nQr/549GDyYPIQ25sXwGnBRsejx/gT", - "np4F7vuRI7bR8fsP49HRAmiOsYHmjyVoyVL/SALNNu7/6oLO5yAnrg2j+Wn16MiLFUfvXdDHBzNDVJ+2", - "KeJBXnC3O6ELIENjlE0Bb3T7Ua75zLjqAeWMjTzDzF0bR2HYXIW406xudnBaMy1f8tHWwD7+NRKIO2Nz", - "ND34SoSNDpGuQRxT5L/f/PSSCEmcevOKpueV34Kczmz5LilWDBNCsyCL2Hw58fT7rxLkpqYvx/nC+s6+", - "pY9zgCzVvGjmpNVSVcxHE+sEiTMbsggIuwrRqhkXmmjC/rkVGzas9UHy5bv3T//2YTQAEIwXVIDVv36n", - "ef47uWDYUBDti75+pquPNo60r0FpelyH/OAH9U6OMamuehp2KKzeaaZy/84Fh9/7tsEBFt0HmufmRcEh", - "tgfvsD4VEgueuUcPHhystWlVvcB6aapRPElcYqAuQ7KPqhapF5IW9iz6Dqfo6EZV2C8UG7o+OeBCm7lH", - "V15ue7jOor+mGXaNA6XtUh5+tks55Riyay4IYi/AD+PR0894b0654Tk0J/hmUPyxe9H8zM+5uOD+TSP8", - "lMsllRsUbYLWlq3KKHSuMB4EWaQ9241mdqN3H3pvvaOwV9fR+0bUZ3alO7HTpvD0+Y5r8o7q45zd0umt", - "VmDmedXpCeMCXb8z7D2l7k3Id+HXyL2xEpmt81VKDpkP2vS3XlVa1RdsrWG7o8IibdFLOzAX397fH/v+", - "PmkaOxrluWPANE7BVpg6XoWrXqBdV2mr2fOlmikHTbku0drkWjtOtnRNO9O7mCq4k1Hf4q4Hd31iUgBv", - "JTE1m6ldP2v2SYLVTdK4Mq6RcX/mQt+PNDd0Eiy3VYzH1qy/FQb/MsJglUw0t9KZa9NyNfEQGzYevfd9", - "CA4gEro+DAOEwVCtDr4Noj7uttjJvYltKhC+czme4bKHdop52B3iVsD7BAS8bueVGBh1P42PJ9QhDIu6", - "NcvOLjC+qUq7l/5eLWQ+UynuL4ysXrHNQLpbYLsE++wIY45ZXxtb/VMKYQ5pt+LXX1r8qnJ6rySANXon", - "uSzxwI11Jetd2zrHdCWJNfO6A86GIdWGobgjPK77PBoWg2UxfUU0NfaaIbpTrdJoN2vc0Ru7ItZ3ECqo", - "X29On++Srj4jO8/g8syRWyC+N9fNS6Nuh9c343YYxpuePHhycxCEu/BSaPIt3uLXzCGvlaXFyWpfFraN", - "Ix1NbXOKbVyJt9gSMoq66UTAo6qCFuPguXnbRmncdZ3Vw4Je9ybEt8JQVWMvl9g1F4ZR+ZwSKuf2I8Pr", - "DDLIHf/nMY5/Z0K+xYQercYYbKZd1ydyh3F9/PDR4yfuFUkvbCxX+73pF0+OT776yr1WNz6xek7ndaXl", - "8QLyXLgP3B3RHdc8OP6ff/zvZDK5s5OtivXXm5e2AvCnwlu76l1IAH279ZlvUkxb9708dqHuRtz3X4t1", - "9BYQ69tb6KPdQgb7f4rbZ9okI6eIVpbMRo2gA95G9pjscx+NfZMPw3eqy2RCXgpXrq3MqSRCZiBdJ8R5", - "SSXlGiCbeErFpFNly1OlOQOujeKIvd1kolgGtsrNvJRQpc8VElYYI4/To07fgGA3o8dI2k+Wyf9I10EJ", - "p2l1TWvhloxmzyVd++6S2D9NSPzpq6/Ig3GtveS5GSCpEBNjrku6Ht2g1a8itkHx583mTDsDdHHsIRak", - "WvqpcmjDTjB/bc792Urultzdxh6Ic+7t+KkdO6EdwRVF22pBsIKd7T2JzRA3dTa+kfK8CBVncWaGocaB", - "T9hHsNM0HVVC2+i9PcS3RoArsZI2Qe3JNjDrVB29R7085Bmdc4tZc38td2ngO5Ji6Z1HgsxApwuXsNtC", - "fYQ9+dZQ/bxpW/PxQ0s1uIvdqhdhTWpsij2w7FmQS4kOPJARIv7Jd2kwj9nMFpjxBZl8j310TTHfdrbq", - "OOv6crtSE1pUeb1mF/eC8lk9eVcgQ7Qcwv95i+D9ENxhjt/41qOIMbeIP0PEv1clE/JS1GnjruvVn9H1", - "eJ03+3Uv6KXgYH3sRvK1tHjrTq3EDsM4LFJ8vRCrv1T9Ry4tghz5Jrpb5ZDvbQvbrbLIkNvbTPZZXuHf", - "OyxtuWXM2iY7iyHUow1hzuZFWwWr2RHjI2oxH4WffoKqzcfgWDfDYvCQej7jxAJ+WKaDJXgsMR9VzRD6", - "OFC8v8xgbqRFFYYWbQkzhVzwufo0WdHWTj9RvESopOq8E2+v89c7u8+wuo9ReW0EpKv3pBhPwTaJxv52", - "TJElU8oFSz558Lebg1Czpa8ozsPc1Y/MXZ4+eHxz078BuWIpkDNYFkJSyfIN+ZlXDb2vwu2weVBVf81b", - "g6P9otDb1KwLloZFjC7PBBuha+/1mmUfdjPDoGLlnnyQ8YAPhuUNaVEAlZdngLtdV+1y26fPw+jgRk+b", - "qqJWBBSDoj0D5P9jNNDuhGnvYuYuv5JbQH31L8cmXOiumI2r4BgjBYjZMXnL7xO1oE8fPvrt0dMv/J+P", - "nn7RYzkz87iiPV3bWT2QeWyHGWJA+6zNgYeV2iv8Ht/0bu+3ieMRy9bRrhd1H7tO0Wsnlt1RpKCb3tY4", - "xY4+fOGwdU++my92qDSbLqL6lVd/qrLyp/zrSgu2Fflc+7rb/ns9yRMBnzGEVjfiq7C+vSffFmmyRZZV", - "87ObVk7rJAN70Xnkydad81EFXf2xlNQEdVTgXrBpouXjyZTYmWUcuLsLKbRIRW5jV8qiEFJXp1tNBol7", - "0Oe2a0h7fYS7lzCXUp0uyuLoPf4HK3x9qBMPbAP2I73mR1g9+uj91hABBDHSGtbKpdGWCl01eUBn2l0h", - "AK0TM24fIlsJG2MJIvLZ9Uhnf2mhZr9Ov1c1aUdG7BzgKq8u6KJd0W5Q+HtHc+PJrQvmE1tQbRSZMZ4R", - "GmxjS3cTsmYE12wYue5Ffww7y837nZ5+xufspdDkdFnYhjmQXS16h7Q5nL89tl63+wkG7urvhvh07/zw", - "xveBiZV1fecFv4dDLkjFBj8dlZgbbe7q67F9397kn/ZN/syXHG6Q4e29/Pncy9KHU95ewZ/+Ffz4s13N", - "NTpiBl7J/ia69DVca+J7XsiRLqFoMmi5wrf5aVD1bq9SfSukb29xe4t/pk4Gd2MOTVoaYqHZlcrkpjxE", - "6OwnBf0wO0OeRywNfQd1bHv96AUwLDojUob1w08zNbaH2Bkn3Cm+FXw+acEn2OtbuefW9PCZmR56pByn", - "9TebtPYJGvsKQKulyMBHnYjZzBV565N+mr1nDHkqTZcFsV9GpRz0xp6xJbwxb/5kpzjoFVuD3RKLWuAZ", - "ZClIBc/UAK+oG/Wy9xC6cfsBuHEPaLUDHhaX/j25NMm+DmrIdCiBtJGvsGeQL3bnkJHBihgCnByAbI/e", - "23/RnFYIFeu67Am4szF33bbY6n123AaA5BUKobYMoP9KzMgDW8Sv5JipUzcHpDwjWm6MoOprlkigOUkb", - "EfoVHN2T86b35OxUBTqr61lTXBcQ9Qk9ZDhrKzvqhxs/AM8odyTfRZAWhBIOc6rZCnzc+uQ2o/7St5nL", - "Z9/CAMeEZpk9jfUmwArkhqhyqoysw5uBlndU87zswTBgXYBk5oqmee2At2rCkU2X3xZQ+ca+ccVLq8WL", - "bJK+bEYB+ZvVpfCLGfmRpVKc5HOhfFyX2igNy07rPffpbz1FV70hoRsDJnjOOCRLwWMN4X7Cpz/iw2g/", - "daFp3vfxmXnY923rvm3C3wKrOc+QO/mq+P1ETv+VcjVaq5VQCKl9k35wavKeR8kfmg1Puydpw9PAqeUe", - "BgOF7eMaPx+9b/zpimW4N9Wi1Jm4CL5Fzd4G/QzJkw8aVV/CktZq+Kyu15Z2nT6kAA+xE1M9jbT+CtqR", - "93b/+ovmhziXS0gkGLqZihVI1VLPbpNE/lRJIoP3fS8ea1td7uJopTqsRPJSZGDHbXaajdVn5iID15Gz", - "K4hUwY7xwHp/K9XvtUKdU1rOF5qUBdEiFlRdf5jQ1DLZxKo38QmDimhWCcLpFnQFhObY55RMATgRU7Po", - "+n7ERVKFNel8ZLYL6YyKQgFchRQpKAVZ4utR7wKt6nOKcdx6C54QcAS4moUoQWZUXhnY89VOOKs+4Yrc", - "/eEXozDfOLxWFNyOWFsJK4LeqtqGk/a6UA+bfhvBtScPyY5KIF40wEQSsSxycKkkERTuhZPe/WtD1NnF", - "q6MFcy3YNVO8n+RqBFSBes30flVoyyIx93cXxGf26RlboiTGKRferhgbLKdKJ7vYsnkpXIsyKwg4YYwT", - "48A9CucLqvRrl1WYYQUae53gPFbGNlP0A7zq60dvRv6l6kbfGTs19yFXpapa1rtMAchia+Cw3jLXS1hX", - "c2Fapx+7SkWwFr5dI/dhKRjfISsoyk2oDrz5ZrjI4tD+SJ2BoovKBhA1IrYB8sa/FWA3dOP3AMJUjWhL", - "OFhkNKScqRA5UG4zukRRGG6hk5JX3/Wh6Y19+0T/XL/bJS6q63s7E6DCNBEH+YXFrEID7YIq4uAgS3ru", - "MknmrslSF2ZzGBPMAE+2UT6abM1b4RHYeUjLYi5pBkkGOY2YUn62j4l9vG0A3HFPnslKaEimMBMS4pte", - "U7LsNRFVQwscT8WER4JPSGqOoFGeawJxX+8YOQMcO8acHB3dqYbCuaJb5MfDZdut7jFLmTHMjjt6QJAd", - "Rx8CcA8eqqEvjwr8OKnNB+0p/gHKTVDJEftPsgHVt4R6/L0W0DbnhRdY46ZosfcWB46yzV42toOP9B3Z", - "mAHxszT2t2OXrrH6S9OAGiiAk8sot0cXlOlkJqQVpBM60yB3BsT/nTLvDneuAS1cbQKCI7h7042DTD5s", - "deG4iAWBuOvCkEjX/2am+lbIQSU2m4VkKNOk5JrlQZnxSlX+9AyGt0aAWyPArRHg1ghwawS4NQLcGgFu", - "jQC3RoBbI8CtEeDWCPDXNQJ8rKK5iZc4fCkxLnjSjkokt1GJf6oik9Vd5Y0SaMa4oEy7rpk+3989uVqN", - "XQ00RxywHPrjpG345tk3Jy+IEqVMgaQGQsZJkVOjG8BaVz3cmt1Bfd9i2wjSNh6lCh4/Im++P/G18Bau", - "Zlvz3bsnrv+30psc7rkuCcAzK4r6dgnADdJdtwTq7wTf6811vmM5xpgr8g2+/RxWkIsCpC2zRbQsIyaf", - "M6D5M4ebHRafv5vJXdDq72a038cNQ5ND25IWXs73a6WKUJu7SJ4H2Yy/z2iu4Pe+hEY73pIWsXZr1c1n", - "bUHITb4W2aZ1QsyuHeEGNs9GXRGPcSo3kXpL3WSCNmloYfiVI6yuMevDwes2dom2S2a7KCwmrktQ0XO8", - "jcqjBQurDesMZVNeZy06GcWyNdtV+kYVgENCYM8w4cDuCXltv/u4VeERInfEamb+yUQONt+smAa+a7QI", - "x3o+16h8j/jo6cWzPzaEnZUpEKYV8aUfd18v49E6MSPNgSeOASVTkW2SBvsaNW6hjCmqFCynu2+ikH+6", - "BsPu8jFPtt9TH+caeR4sbhtPDolmnTgG3MOdNxoG8+YKWziiY88Bxq+bRfex0RAE4vhTzKrU4n37Mr16", - "ms0t47tlfMFpbEkEjLtSuW0mMrlGxic3suT9PO+bNaSlAS48yXfRPI8+OVjrhmMzg2k5n2Oj5I6TziwN", - "cDwm+EdihXa5Q7ngfhRkB6+aZ1413bs9XJe7BBnYd32Nw3u4HZRv0JuxLCjfeJ8vJIoty9zi0PaYOyyj", - "tdVsu5EA6I91xr8+s/Yrb/MLjLfuqm3+btFCLqgidn8hIyXPXO5Qp+b1mg+vGGKHPlvzmk1vrQ5i1xtZ", - "nZt3yBXhd7mZtK1IATLRa24PVLOTuq2tbU/u5LZB7F/j2rAp39DDYLt1omuGcKDbQwZ8Da+PoBtInQzX", - "6BGCVov+1JGwNYh986DRI53hm0EktUnFOUkhLwj13ftTwZWWZarfcopOmmBhk26AibdG9/O3Z/6VuJ8w", - "4sZzQ73lFJu7V66bKJ+bQcRP8S2AZ6OqnM9BGV4ZEskM4C13bzFOSm40LTEjS5ZKkdhEVHOGjHwysW8u", - "6YbMsP6HIH+AFGRqbvZg163BWGmW5y6ixUxDxOwtp5rkQJUmPzLDZc1wvvhAFcoF+kLI8woL8U4Rc+Cg", - "mErixpfv7FNsxuCW7418aLC0j+si6jfbhcHDzrJeyE+fG7gp1i7OmdJ1EEQH9htzgC8ZT6JEdrYA4mLC", - "2rRF7mLFNEdA95reIb2At9zccFoQ5OpUX44c2m6ezlm0p6NFNY2NaHmD/FoHqXgH4TIkwmRuXSt/otTM", - "gA68+xI33lajb+39nm6UxpULPDNPey5k+9Q17+p5ySkJDUNYqxyMe+OsAfKft/H7u+vRFz0aD6Yxdgfs", - "sqtmeybEm9/wMaG54HNbhdBokAL3ifGi1BhYfZ1GOljRPBErkJJloAaulAn+zYrmP1Wf7bgAg+ZyyyVk", - "jGrIN6SQkEJm62QxRWoleWIrDZB0Qfkc70opyvnCvmbHuQAJVR8uo5e2h4jXKVnzxNZM68J4QqyBMSwr", - "CzRdRPqa4I1iFGG/g7YMxBBVN3KEsSJmn+Y7HvVKtgapqzogzSKnea4HXNuNCzjATz3xIUqI3lLZLZXt", - "TWWxEnuIullL57b4Crflmo0z111Q8gZtPR+l2uxtyfY/e8l2z4EUoUTShpQd7xVGFWGaXGBBnSkQc2GU", - "aGN2LcWdRjohhiEF9nRbeVG5TpfpgjLuqrFU4fkIh3bdeLVv/3ct5jnLzNAuZ9ABaSmZ3qBcTgv22zmY", - "/78zgq0CufIieynz0fFooXVxfHSUi5TmC6H00ejDOHymWg/fVfC/99J2IdnKaBAf3n34/wEAAP//VHyg", - "HOZ0AQA=", + "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", + "ReZ0AQA=", } // 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 15b8e7e02d..1e585cd015 100644 --- a/daemon/algod/api/server/v2/generated/participating/private/routes.go +++ b/daemon/algod/api/server/v2/generated/participating/private/routes.go @@ -216,125 +216,125 @@ var swaggerSpec = []string{ "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", - "wpHC9Yfr/wkAAP//n/TLvvHVAAA=", + "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", + "XeFI4frD9f8EAAD//4XxG93x1QAA", } // 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 14745a0baf..ade11ffe95 100644 --- a/daemon/algod/api/server/v2/generated/participating/public/routes.go +++ b/daemon/algod/api/server/v2/generated/participating/public/routes.go @@ -235,134 +235,134 @@ var swaggerSpec = []string{ "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", - "AAA=", + "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", + "5AAA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/data/transactions/logic/assembler.go b/data/transactions/logic/assembler.go index 65f9f1dfb4..86719cb6b7 100644 --- a/data/transactions/logic/assembler.go +++ b/data/transactions/logic/assembler.go @@ -48,14 +48,13 @@ type Writer interface { } type labelReference struct { - sourceLine int - - // position of the label reference + // position (PC) of the label reference position int - label string + // token holding the label name (and line, column) + label token - // ending positions of the opcode containing the label reference. + // ending position of the opcode containing the label reference. offsetPosition int } @@ -108,7 +107,7 @@ func (ref intReference) length(ops *OpStream, assembled []byte) (int, error) { case opIntc: return 2, nil default: - return 0, ops.lineErrorf(ops.OffsetToLine[ref.position], "Unexpected op at intReference: %d", assembled[ref.position]) + return 0, errorLinef(ops.OffsetToLine[ref.position], "unexpected op at intReference: %d", assembled[ref.position]) } } @@ -177,7 +176,7 @@ func (ref byteReference) length(ops *OpStream, assembled []byte) (int, error) { case opBytec: return 2, nil default: - return 0, ops.lineErrorf(ops.OffsetToLine[ref.position], "Unexpected op at byteReference: %d", assembled[ref.position]) + return 0, errorLinef(ops.OffsetToLine[ref.position], "unexpected op at byteReference: %d", assembled[ref.position]) } } @@ -219,9 +218,9 @@ func (ref byteReference) makeNewReference(ops *OpStream, singleton bool, newInde type OpStream struct { Version uint64 Trace *strings.Builder - Warnings []error // informational warnings, shouldn't stop assembly - Errors []lineError // errors that should prevent final assembly - Program []byte // Final program bytes. Will stay nil if any errors + Warnings []error // informational warnings, shouldn't stop assembly + Errors []sourceError // errors that should prevent final assembly + Program []byte // Final program bytes. Will stay nil if any errors // Running bytes as they are assembled. jumps must be resolved // and cblocks added before these bytes become a legal program. @@ -258,7 +257,7 @@ type OpStream struct { // Need new copy for each opstream versionedPseudoOps map[string]map[int]OpSpec - macros map[string][]string + macros map[string][]token } // newOpStream constructs OpStream instances ready to invoke assemble. A new @@ -269,7 +268,7 @@ func newOpStream(version uint64) OpStream { OffsetToLine: make(map[int]int), typeTracking: true, Version: version, - macros: make(map[string][]string), + macros: make(map[string][]token), known: ProgramKnowledge{fp: -1}, } @@ -357,9 +356,10 @@ func (pgm *ProgramKnowledge) reset() { // createLabel inserts a label to point to the next instruction, reporting an // error for a duplicate. -func (ops *OpStream) createLabel(label string) { +func (ops *OpStream) createLabel(withColon token) { + label := strings.TrimSuffix(withColon.str, ":") if _, ok := ops.labels[label]; ok { - ops.errorf("duplicate label %#v", label) + ops.record(withColon.errorf("duplicate label %#v", label)) } ops.labels[label] = ops.pending.Len() ops.known.label() @@ -371,11 +371,11 @@ func (ops *OpStream) recordSourceLine() { } // referToLabel records an opcode label reference to resolve later -func (ops *OpStream) referToLabel(pc int, label string, offsetPosition int) { - ops.labelReferences = append(ops.labelReferences, labelReference{ops.sourceLine, pc, label, offsetPosition}) +func (ops *OpStream) referToLabel(pc int, label token, offsetPosition int) { + ops.labelReferences = append(ops.labelReferences, labelReference{pc, label, offsetPosition}) } -type refineFunc func(pgm *ProgramKnowledge, immediates []string) (StackTypes, StackTypes, error) +type refineFunc func(pgm *ProgramKnowledge, immediates []token) (StackTypes, StackTypes, error) // returns allows opcodes like `txn` to be specific about their return value // types, based on the field requested, rather than use Any as specified by @@ -396,8 +396,8 @@ func (ops *OpStream) returns(spec *OpSpec, replacement StackType) { panic(fmt.Sprintf("%+v", spec)) } -// Intc writes opcodes for loading a uint64 constant onto the stack. -func (ops *OpStream) Intc(constIndex uint) { +// writeIntc writes opcodes for loading a uint64 constant onto the stack. +func (ops *OpStream) writeIntc(constIndex uint) error { switch constIndex { case 0: ops.pending.WriteByte(OpsByName[ops.Version]["intc_0"].Opcode) @@ -409,20 +409,20 @@ func (ops *OpStream) Intc(constIndex uint) { ops.pending.WriteByte(OpsByName[ops.Version]["intc_3"].Opcode) default: if constIndex > 0xff { - ops.error("cannot have more than 256 int constants") + return errors.New("cannot have more than 256 int constants") } ops.pending.WriteByte(OpsByName[ops.Version]["intc"].Opcode) ops.pending.WriteByte(uint8(constIndex)) } if constIndex >= uint(len(ops.intc)) { - ops.errorf("intc %d is not defined", constIndex) - } else { - ops.trace("intc %d: %d", constIndex, ops.intc[constIndex]) + return fmt.Errorf("intc %d is not defined", constIndex) } + ops.trace("intc %d: %d", constIndex, ops.intc[constIndex]) + return nil } -// IntLiteral writes opcodes for loading a uint literal -func (ops *OpStream) IntLiteral(val uint64) { +// intLiteral writes opcodes for loading a uint literal +func (ops *OpStream) intLiteral(val uint64) error { ops.hasPseudoInt = true found := false @@ -437,7 +437,7 @@ func (ops *OpStream) IntLiteral(val uint64) { if !found { if ops.cntIntcBlock > 0 { - ops.errorf("int %d used without %d in intcblock", val, val) + return fmt.Errorf("value %d does not appear in existing intcblock", val) } constIndex = uint(len(ops.intc)) ops.intc = append(ops.intc, val) @@ -446,11 +446,11 @@ func (ops *OpStream) IntLiteral(val uint64) { value: val, position: ops.pending.Len(), }) - ops.Intc(constIndex) + return ops.writeIntc(constIndex) } -// Bytec writes opcodes for loading a []byte constant onto the stack. -func (ops *OpStream) Bytec(constIndex uint) { +// writeBytec writes opcodes for loading a []byte constant onto the stack. +func (ops *OpStream) writeBytec(constIndex uint) error { switch constIndex { case 0: ops.pending.WriteByte(OpsByName[ops.Version]["bytec_0"].Opcode) @@ -462,21 +462,21 @@ func (ops *OpStream) Bytec(constIndex uint) { ops.pending.WriteByte(OpsByName[ops.Version]["bytec_3"].Opcode) default: if constIndex > 0xff { - ops.error("cannot have more than 256 byte constants") + return errors.New("cannot have more than 256 byte constants") } ops.pending.WriteByte(OpsByName[ops.Version]["bytec"].Opcode) ops.pending.WriteByte(uint8(constIndex)) } if constIndex >= uint(len(ops.bytec)) { - ops.errorf("bytec %d is not defined", constIndex) - } else { - ops.trace("bytec %d %s", constIndex, hex.EncodeToString(ops.bytec[constIndex])) + return fmt.Errorf("bytec %d is not defined", constIndex) } + ops.trace("bytec %d %s", constIndex, hex.EncodeToString(ops.bytec[constIndex])) + return nil } -// ByteLiteral writes opcodes and data for loading a []byte literal +// byteLiteral writes opcodes and data for loading a []byte literal // Values are accumulated so that they can be put into a bytecblock -func (ops *OpStream) ByteLiteral(val []byte) { +func (ops *OpStream) byteLiteral(val []byte) error { ops.hasPseudoByte = true found := false @@ -490,7 +490,7 @@ func (ops *OpStream) ByteLiteral(val []byte) { } if !found { if ops.cntBytecBlock > 0 { - ops.errorf("byte/addr/method used without value in bytecblock") + return fmt.Errorf("value 0x%x does not appear in existing bytecblock", val) } constIndex = uint(len(ops.bytec)) ops.bytec = append(ops.bytec, val) @@ -499,21 +499,21 @@ func (ops *OpStream) ByteLiteral(val []byte) { value: val, position: ops.pending.Len(), }) - ops.Bytec(constIndex) + return ops.writeBytec(constIndex) } -func asmInt(ops *OpStream, spec *OpSpec, args []string) error { - if len(args) != 1 { - return ops.errorf("%s needs one immediate argument, was given %d", spec.Name, len(args)) +func asmInt(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { + if err := ops.checkArgCount(spec.Name, mnemonic, args, 1); err != nil { + return err } // After backBranchEnabledVersion, control flow is confusing, so if there's // a manual cblock, use push instead of trying to use what's given. if ops.cntIntcBlock > 0 && ops.Version >= backBranchEnabledVersion { // We don't understand control-flow, so use pushint - ops.warnf("int %s used with explicit intcblock. must pushint", args[0]) + ops.warn(args[0], "int %s used with explicit intcblock. must pushint", args[0].str) pushint := OpsByName[ops.Version]["pushint"] - return asmPushInt(ops, &pushint, args) + return asmPushInt(ops, &pushint, mnemonic, args) } // There are no backjumps, but there are multiple cblocks. Maybe one is @@ -521,65 +521,71 @@ func asmInt(ops *OpStream, spec *OpSpec, args []string) error { if ops.cntIntcBlock > 1 { pushint, ok := OpsByName[ops.Version]["pushint"] if ok { - return asmPushInt(ops, &pushint, args) + return asmPushInt(ops, &pushint, mnemonic, args) } - return ops.errorf("int %s used with manual intcblocks. Use intc.", args[0]) + return mnemonic.errorf("int %s used with manual intcblocks. Use intc.", args[0].str) } // In both of the above clauses, we _could_ track whether a particular // intcblock dominates the current instruction. If so, we could use it. // check txn type constants - i, ok := txnTypeMap[args[0]] - if ok { - ops.IntLiteral(i) - return nil + i, ok := txnTypeMap[args[0].str] + if !ok { + // check OnCompletion constants + i, ok = onCompletionMap[args[0].str] } - // check OnCompletion constants - oc, isOCStr := onCompletionMap[args[0]] - if isOCStr { - ops.IntLiteral(oc) - return nil + if !ok { + val, err := strconv.ParseUint(args[0].str, 0, 64) + if err != nil { + return args[0].errorf("unable to parse %#v as integer", args[0].str) + } + i = val } - val, err := strconv.ParseUint(args[0], 0, 64) + err := ops.intLiteral(i) if err != nil { - return ops.error(err) + return args[0].error(err) } - ops.IntLiteral(val) return nil } // Explicit invocation of const lookup and push -func asmIntC(ops *OpStream, spec *OpSpec, args []string) error { - if len(args) != 1 { - return ops.errorf("%s needs one immediate argument, was given %d", spec.Name, len(args)) +func asmIntC(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { + if err := ops.checkArgCount(spec.Name, mnemonic, args, 1); err != nil { + return err + } + constIndex, err := byteImm(args[0].str, "constant") + if err != nil { + return args[0].error(err) } - constIndex, err := byteImm(args[0], "constant") + err = ops.writeIntc(uint(constIndex)) if err != nil { - return ops.error(err) + return args[0].error(err) } - ops.Intc(uint(constIndex)) return nil } -func asmByteC(ops *OpStream, spec *OpSpec, args []string) error { - if len(args) != 1 { - return ops.errorf("%s needs one immediate argument, was given %d", spec.Name, len(args)) +func asmByteC(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { + if err := ops.checkArgCount(spec.Name, mnemonic, args, 1); err != nil { + return err + } + constIndex, err := byteImm(args[0].str, "constant") + if err != nil { + return args[0].error(err) } - constIndex, err := byteImm(args[0], "constant") + err = ops.writeBytec(uint(constIndex)) if err != nil { - return ops.error(err) + return args[0].error(err) } - ops.Bytec(uint(constIndex)) return nil } -func asmPushInt(ops *OpStream, spec *OpSpec, args []string) error { - if len(args) != 1 { - return ops.errorf("%s needs one immediate argument, was given %d", spec.Name, len(args)) +func asmPushInt(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { + if err := ops.checkArgCount(spec.Name, mnemonic, args, 1); err != nil { + return err } - val, err := strconv.ParseUint(args[0], 0, 64) + val, err := strconv.ParseUint(args[0].str, 0, 64) if err != nil { - return ops.error(err) + return args[0].errorf("unable to parse %#v as integer", args[0].str) } ops.pending.WriteByte(spec.Opcode) var scratch [binary.MaxVarintLen64]byte @@ -588,22 +594,24 @@ func asmPushInt(ops *OpStream, spec *OpSpec, args []string) error { return nil } -func asmPushInts(ops *OpStream, spec *OpSpec, args []string) error { +func asmPushInts(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { ops.pending.WriteByte(spec.Opcode) _, err := asmIntImmArgs(ops, args) return err } -func asmPushBytes(ops *OpStream, spec *OpSpec, args []string) error { +func asmPushBytes(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { + // asmPushBytes is sometimes used to assemble the "byte" mnemonic, so use + // mnemonic.str instead of spec.Name when reporting errors. if len(args) == 0 { - return ops.errorf("%s needs byte literal argument", spec.Name) + return mnemonic.errorAfterf("%s needs byte literal argument", mnemonic.str) } val, consumed, err := parseBinaryArgs(args) if err != nil { - return ops.error(err) + return args[consumed].errorf("%s %w", mnemonic.str, err) } if len(args) != consumed { - return ops.errorf("%s with extraneous argument", spec.Name) + return args[consumed].errorf("%s with extraneous argument", mnemonic.str) } ops.pending.WriteByte(spec.Opcode) var scratch [binary.MaxVarintLen64]byte @@ -613,9 +621,9 @@ func asmPushBytes(ops *OpStream, spec *OpSpec, args []string) error { return nil } -func asmPushBytess(ops *OpStream, spec *OpSpec, args []string) error { +func asmPushBytess(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { ops.pending.WriteByte(spec.Opcode) - _, err := asmByteImmArgs(ops, args) + _, err := asmByteImmArgs(ops, spec, args) return err } @@ -632,66 +640,73 @@ func base32DecodeAnyPadding(x string) (val []byte, err error) { return } -func parseBinaryArgs(args []string) (val []byte, consumed int, err error) { - arg := args[0] +// parseBinaryArgs parses a byte literal argument. It returns the argument, +// interpetted into raw bytes, and the number of tokens consumed. +func parseBinaryArgs(args []token) ([]byte, int, error) { + arg := args[0].str if strings.HasPrefix(arg, "base32(") || strings.HasPrefix(arg, "b32(") { open := strings.IndexRune(arg, '(') close := strings.IndexRune(arg, ')') if close == -1 { - err = errors.New("byte base32 arg lacks close paren") - return + return nil, 0, fmt.Errorf("argument %s lacks closing parenthesis", arg) + } + if close != len(arg)-1 { + return nil, 0, fmt.Errorf("argument %s must end at first closing parenthesis", arg) } - val, err = base32DecodeAnyPadding(arg[open+1 : close]) + val, err := base32DecodeAnyPadding(arg[open+1 : close]) if err != nil { - return + if cie, ok := err.(base32.CorruptInputError); ok { + return nil, 0, base32.CorruptInputError(int64(cie) + int64(open) + 1) + } + return nil, 0, err } - consumed = 1 + return val, 1, nil } else if strings.HasPrefix(arg, "base64(") || strings.HasPrefix(arg, "b64(") { open := strings.IndexRune(arg, '(') close := strings.IndexRune(arg, ')') if close == -1 { - err = errors.New("byte base64 arg lacks close paren") - return + return nil, 0, fmt.Errorf("argument %s lacks closing parenthesis", arg) } - val, err = base64.StdEncoding.DecodeString(arg[open+1 : close]) + if close != len(arg)-1 { + return nil, 0, fmt.Errorf("argument %s must end at first closing parenthesis", arg) + } + val, err := base64.StdEncoding.DecodeString(arg[open+1 : close]) if err != nil { - return + return nil, 0, err } - consumed = 1 + return val, 1, nil } else if strings.HasPrefix(arg, "0x") { - val, err = hex.DecodeString(arg[2:]) + val, err := hex.DecodeString(arg[2:]) if err != nil { - return + return nil, 0, err } - consumed = 1 + return val, 1, nil } else if arg == "base32" || arg == "b32" { if len(args) < 2 { - err = fmt.Errorf("need literal after 'byte %s'", arg) - return + return nil, 0, fmt.Errorf("%s needs byte literal argument", arg) } - val, err = base32DecodeAnyPadding(args[1]) + val, err := base32DecodeAnyPadding(args[1].str) if err != nil { - return + return nil, 1, err // return 1, so that the right token is blamed } - consumed = 2 + return val, 2, nil } else if arg == "base64" || arg == "b64" { if len(args) < 2 { - err = fmt.Errorf("need literal after 'byte %s'", arg) - return + return nil, 0, fmt.Errorf("%s needs byte literal argument", arg) } - val, err = base64.StdEncoding.DecodeString(args[1]) + val, err := base64.StdEncoding.DecodeString(args[1].str) if err != nil { - return + return nil, 1, err } - consumed = 2 + return val, 2, nil } else if len(arg) > 1 && arg[0] == '"' && arg[len(arg)-1] == '"' { - val, err = parseStringLiteral(arg) - consumed = 1 - } else { - err = fmt.Errorf("byte arg did not parse: %v", arg) - return + val, err := parseStringLiteral(arg) + if err != nil { + return nil, 0, err + } + return val, 1, err } - return + return nil, 0, fmt.Errorf("arg did not parse: %v", arg) } func parseStringLiteral(input string) (result []byte, err error) { @@ -736,7 +751,7 @@ func parseStringLiteral(input string) (result []byte, err error) { pos++ continue default: - return nil, fmt.Errorf("invalid escape seq \\%c", char) + return nil, fmt.Errorf("invalid escape sequence \\%c", char) } } if hexSeq { @@ -766,28 +781,29 @@ func parseStringLiteral(input string) (result []byte, err error) { // byte {base64,b64,base32,b32} ... // byte 0x.... // byte "this is a string\n" -func asmByte(ops *OpStream, spec *OpSpec, args []string) error { +func asmByte(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { if len(args) == 0 { - return ops.errorf("%s needs byte literal argument", spec.Name) + return mnemonic.errorAfterf("%s needs byte literal argument", spec.Name) } // After backBranchEnabledVersion, control flow is confusing, so if there's // a manual cblock, use push instead of trying to use what's given. if ops.cntBytecBlock > 0 && ops.Version >= backBranchEnabledVersion { // We don't understand control-flow, so use pushbytes - ops.warnf("byte %s used with explicit bytecblock. must pushbytes", args[0]) - pushbytes := OpsByName[ops.Version]["pushbytes"] - return asmPushBytes(ops, &pushbytes, args) + ops.warn(args[0], "byte %s used with explicit bytecblock. must pushbytes", args[0].str) + pushbytes := OpsByName[ops.Version]["pushbytes"] // make sure pushbytes opcode is written + return asmPushBytes(ops, &pushbytes, mnemonic, args) } // There are no backjumps, but there are multiple cblocks. Maybe one is // conditional skipped. Too confusing. if ops.cntBytecBlock > 1 { + // use pushbytes opcode if available pushbytes, ok := OpsByName[ops.Version]["pushbytes"] if ok { - return asmPushBytes(ops, &pushbytes, args) + return asmPushBytes(ops, &pushbytes, mnemonic, args) } - return ops.errorf("byte %s used with manual bytecblocks. Use bytec.", args[0]) + return args[0].errorf("byte %s used with manual bytecblocks. Use bytec.", args[0].str) } // In both of the above clauses, we _could_ track whether a particular @@ -795,49 +811,55 @@ func asmByte(ops *OpStream, spec *OpSpec, args []string) error { val, consumed, err := parseBinaryArgs(args) if err != nil { - return ops.error(err) + return args[consumed].errorf("%s %w", spec.Name, err) } if len(args) != consumed { - return ops.errorf("%s with extraneous argument", spec.Name) + return args[consumed].errorf("%s with extraneous argument", spec.Name) + } + err = ops.byteLiteral(val) + if err != nil { + return args[0].error(err) } - ops.ByteLiteral(val) return nil } // method "add(uint64,uint64)uint64" -func asmMethod(ops *OpStream, spec *OpSpec, args []string) error { - if len(args) == 0 { - return ops.error("method requires a literal argument") +func asmMethod(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { + if err := ops.checkArgCount(spec.Name, mnemonic, args, 1); err != nil { + return err } - arg := args[0] + arg := args[0].str if len(arg) > 1 && arg[0] == '"' && arg[len(arg)-1] == '"' { methodSig, err := parseStringLiteral(arg) if err != nil { - return ops.error(err) + return args[0].error(err) } methodSigStr := string(methodSig) err = abi.VerifyMethodSignature(methodSigStr) if err != nil { // Warn if an invalid signature is used. Don't return an error, since the ABI is not // governed by the core protocol, so there may be changes to it that we don't know about - ops.warnf("Invalid ARC-4 ABI method signature for method op: %s", err.Error()) + ops.warn(args[0], "invalid ARC-4 ABI method signature for method op: %w", err) } hash := sha512.Sum512_256(methodSig) - ops.ByteLiteral(hash[0:4]) + err = ops.byteLiteral(hash[:4]) + if err != nil { + return args[0].error(err) + } return nil } - return ops.error("Unable to parse method signature") + return args[0].errorf("unable to parse method signature") } -func asmIntImmArgs(ops *OpStream, args []string) ([]uint64, error) { +func asmIntImmArgs(ops *OpStream, args []token) ([]uint64, *sourceError) { ivals := make([]uint64, len(args)) var scratch [binary.MaxVarintLen64]byte l := binary.PutUvarint(scratch[:], uint64(len(args))) ops.pending.Write(scratch[:l]) for i, xs := range args { - cu, err := strconv.ParseUint(xs, 0, 64) + cu, err := strconv.ParseUint(xs.str, 0, 64) if err != nil { - ops.error(err) + ops.record(xs.error(err)) } l = binary.PutUvarint(scratch[:], cu) ops.pending.Write(scratch[:l]) @@ -847,7 +869,7 @@ func asmIntImmArgs(ops *OpStream, args []string) ([]uint64, error) { return ivals, nil } -func asmIntCBlock(ops *OpStream, spec *OpSpec, args []string) error { +func asmIntCBlock(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { ops.pending.WriteByte(spec.Opcode) ivals, err := asmIntImmArgs(ops, args) if err != nil { @@ -857,7 +879,7 @@ func asmIntCBlock(ops *OpStream, spec *OpSpec, args []string) error { // If we previously processed an `int`, we thought we could insert our // own intcblock, but now we see a manual one. if ops.hasPseudoInt { - ops.error("intcblock following int") + return mnemonic.errorf("intcblock following int") } ops.intcRefs = nil ops.intc = ivals @@ -867,7 +889,7 @@ func asmIntCBlock(ops *OpStream, spec *OpSpec, args []string) error { return nil } -func asmByteImmArgs(ops *OpStream, args []string) ([][]byte, error) { +func asmByteImmArgs(ops *OpStream, spec *OpSpec, args []token) ([][]byte, *sourceError) { bvals := make([][]byte, 0, len(args)) rest := args for len(rest) > 0 { @@ -877,7 +899,7 @@ func asmByteImmArgs(ops *OpStream, args []string) ([][]byte, error) { // intcblock, but parseBinaryArgs would have // to return a useful consumed value even in // the face of errors. Hard. - return nil, ops.error(err) + return nil, rest[0].errorf("%s %w", spec.Name, err) } bvals = append(bvals, val) rest = rest[consumed:] @@ -894,9 +916,9 @@ func asmByteImmArgs(ops *OpStream, args []string) ([][]byte, error) { return bvals, nil } -func asmByteCBlock(ops *OpStream, spec *OpSpec, args []string) error { +func asmByteCBlock(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { ops.pending.WriteByte(spec.Opcode) - bvals, err := asmByteImmArgs(ops, args) + bvals, err := asmByteImmArgs(ops, spec, args) if err != nil { return err } @@ -905,7 +927,7 @@ func asmByteCBlock(ops *OpStream, spec *OpSpec, args []string) error { // If we previously processed a pseudo `byte`, we thought we could // insert our own bytecblock, but now we see a manual one. if ops.hasPseudoByte { - ops.error("bytecblock following byte/addr/method") + return mnemonic.errorf("bytecblock following byte/addr/method") } ops.bytecRefs = nil ops.bytec = bvals @@ -916,25 +938,28 @@ func asmByteCBlock(ops *OpStream, spec *OpSpec, args []string) error { // addr A1EU... // parses base32-with-checksum account address strings into a byte literal -func asmAddr(ops *OpStream, spec *OpSpec, args []string) error { - if len(args) != 1 { - return ops.errorf("%s needs one immediate argument, was given %d", spec.Name, len(args)) +func asmAddr(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { + if err := ops.checkArgCount(spec.Name, mnemonic, args, 1); err != nil { + return err + } + addr, err := basics.UnmarshalChecksumAddress(args[0].str) + if err != nil { + return args[0].error(err) } - addr, err := basics.UnmarshalChecksumAddress(args[0]) + err = ops.byteLiteral(addr[:]) if err != nil { - return ops.error(err) + return args[0].error(err) } - ops.ByteLiteral(addr[:]) return nil } -func asmArg(ops *OpStream, spec *OpSpec, args []string) error { - if len(args) != 1 { - return ops.errorf("%s needs one immediate argument, was given %d", spec.Name, len(args)) +func asmArg(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { + if err := ops.checkArgCount(spec.Name, mnemonic, args, 1); err != nil { + return err } - val, err := byteImm(args[0], "argument") + val, err := byteImm(args[0].str, "argument") if err != nil { - return ops.error(err) + return args[0].error(err) } altSpec := *spec if val < 4 { @@ -948,14 +973,14 @@ func asmArg(ops *OpStream, spec *OpSpec, args []string) error { case 3: altSpec = OpsByName[ops.Version]["arg_3"] } - args = []string{} + args = []token{} } - return asmDefault(ops, &altSpec, args) + return asmDefault(ops, &altSpec, mnemonic, args) } -func asmBranch(ops *OpStream, spec *OpSpec, args []string) error { - if len(args) != 1 { - return ops.errorf("%s needs a single label argument", spec.Name) +func asmBranch(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { + if err := ops.checkArgCount(spec.Name, mnemonic, args, 1); err != nil { + return err } ops.referToLabel(ops.pending.Len()+1, args[0], ops.pending.Len()+spec.Size) @@ -966,10 +991,10 @@ func asmBranch(ops *OpStream, spec *OpSpec, args []string) error { return nil } -func asmSwitch(ops *OpStream, spec *OpSpec, args []string) error { +func asmSwitch(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { numOffsets := len(args) if numOffsets > math.MaxUint8 { - return ops.errorf("%s cannot take more than 255 labels", spec.Name) + return args[math.MaxUint8].errorf("%s cannot take more than 255 labels", spec.Name) } ops.pending.WriteByte(spec.Opcode) ops.pending.WriteByte(byte(numOffsets)) @@ -983,16 +1008,16 @@ func asmSwitch(ops *OpStream, spec *OpSpec, args []string) error { return nil } -func asmSubstring(ops *OpStream, spec *OpSpec, args []string) error { - err := asmDefault(ops, spec, args) +func asmSubstring(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { + err := asmDefault(ops, spec, mnemonic, args) if err != nil { return err } // Having run asmDefault, only need to check extra constraints. - start, _ := strconv.ParseUint(args[0], 0, 64) - end, _ := strconv.ParseUint(args[1], 0, 64) + start, _ := strconv.ParseUint(args[0].str, 0, 64) + end, _ := strconv.ParseUint(args[1].str, 0, 64) if end < start { - return ops.error("substring end is before start") + return args[0].errorf("substring end is before start") } return nil } @@ -1016,58 +1041,74 @@ func int8Imm(value string, label string) (byte, error) { return byte(res), err } -func asmItxn(ops *OpStream, spec *OpSpec, args []string) error { +func asmItxn(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { if len(args) == 1 { - return asmDefault(ops, spec, args) + return asmDefault(ops, spec, mnemonic, args) } if len(args) == 2 { itxna := OpsByName[ops.Version]["itxna"] - return asmDefault(ops, &itxna, args) + return asmDefault(ops, &itxna, mnemonic, args) } - return ops.errorf("%s expects 1 or 2 immediate arguments", spec.Name) + return mnemonic.errorf("%s expects 1 or 2 immediate arguments", spec.Name) } // asmGitxn substitutes gitna's spec if the are 3 args -func asmGitxn(ops *OpStream, spec *OpSpec, args []string) error { +func asmGitxn(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { if len(args) == 2 { - return asmDefault(ops, spec, args) + return asmDefault(ops, spec, mnemonic, args) } if len(args) == 3 { itxna := OpsByName[ops.Version]["gitxna"] - return asmDefault(ops, &itxna, args) + return asmDefault(ops, &itxna, mnemonic, args) } - return ops.errorf("%s expects 2 or 3 immediate arguments", spec.Name) + return mnemonic.errorf("%s expects 2 or 3 immediate arguments", spec.Name) } -func asmItxnField(ops *OpStream, spec *OpSpec, args []string) error { - if len(args) != 1 { - return ops.errorf("%s expects one argument", spec.Name) +func asmItxnField(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { + if err := ops.checkArgCount(spec.Name, mnemonic, args, 1); err != nil { + return err } - fs, ok := txnFieldSpecByName[args[0]] + fs, ok := txnFieldSpecByName[args[0].str] if !ok { - return ops.errorf("%s unknown field: %#v", spec.Name, args[0]) + return args[0].errorf("%s unknown field: %#v", spec.Name, args[0].str) } if fs.itxVersion == 0 { - return ops.errorf("%s %#v is not allowed.", spec.Name, args[0]) + return args[0].errorf("%s %#v is not allowed.", spec.Name, args[0].str) } if fs.itxVersion > ops.Version { - return ops.errorf("%s %s field was introduced in v%d. Missed #pragma version?", spec.Name, args[0], fs.itxVersion) + return args[0].errorf("%s %s field was introduced in v%d. Missed #pragma version?", spec.Name, args[0].str, fs.itxVersion) } ops.pending.WriteByte(spec.Opcode) ops.pending.WriteByte(fs.Field()) return nil } -type asmFunc func(*OpStream, *OpSpec, []string) error +type asmFunc func(*OpStream, *OpSpec, token, []token) *sourceError -// Basic assembly. Any extra bytes of opcode are encoded as byte immediates. -func asmDefault(ops *OpStream, spec *OpSpec, args []string) error { - expected := len(spec.OpDetails.Immediates) - if len(args) != expected { +func (ops *OpStream) checkArgCount(name string, mnemonic token, args []token, expected int) *sourceError { + offered := len(args) + if offered != expected { + all := make([]token, len(args)+1) + all[0] = mnemonic + copy(all[1:], args) + line := all[offered].line + col := all[offered].col + len(all[offered].str) // end of last arg (or mnemonic) + if offered > expected { + line = all[expected+1].line + col = all[expected+1].col // start of first extra arg + } if expected == 1 { - return ops.errorf("%s expects 1 immediate argument", spec.Name) + return &sourceError{line, col, fmt.Errorf("%s expects 1 immediate argument", name)} } - return ops.errorf("%s expects %d immediate arguments", spec.Name, expected) + return &sourceError{line, col, fmt.Errorf("%s expects %d immediate arguments", name, expected)} + } + return nil +} + +// Basic assembly. Any extra bytes of opcode are encoded as byte immediates. +func asmDefault(ops *OpStream, spec *OpSpec, mnemonic token, args []token) *sourceError { + if err := ops.checkArgCount(spec.Name, mnemonic, args, len(spec.OpDetails.Immediates)); err != nil { + return err } ops.pending.WriteByte(spec.Opcode) for i, imm := range spec.OpDetails.Immediates { @@ -1077,9 +1118,9 @@ func asmDefault(ops *OpStream, spec *OpSpec, args []string) error { switch imm.kind { case immByte: if imm.Group != nil { - fs, ok := imm.Group.SpecByName(args[i]) + fs, ok := imm.Group.SpecByName(args[i].str) if !ok { - _, err := byteImm(args[i], "") + _, err := byteImm(args[i].str, "") if err == nil { // User supplied a uint, so we see if any of the other immediates take uints for j, otherImm := range spec.OpDetails.Immediates { @@ -1092,43 +1133,44 @@ func asmDefault(ops *OpStream, spec *OpSpec, args []string) error { if isPseudoName { errMsg += " with " + joinIntsOnOr("immediate", len(args)) } - return ops.errorf("%s can only use %#v as immediate %s", errMsg, args[i], strings.Join(correctImmediates, " or ")) + return args[i].errorf("%s can only use %#v as immediate %s", + errMsg, args[i].str, strings.Join(correctImmediates, " or ")) } } if isPseudoName { for numImms, ps := range pseudos { for _, psImm := range ps.OpDetails.Immediates { if psImm.kind == immByte && psImm.Group != nil { - if _, ok := psImm.Group.SpecByName(args[i]); ok { + if _, ok := psImm.Group.SpecByName(args[i].str); ok { numImmediatesWithField = append(numImmediatesWithField, numImms) } } } } if len(numImmediatesWithField) > 0 { - return ops.errorf("%#v field of %s can only be used with %s", args[i], spec.Name, joinIntsOnOr("immediate", numImmediatesWithField...)) + return args[i].errorf("%#v field of %s can only be used with %s", args[i].str, spec.Name, joinIntsOnOr("immediate", numImmediatesWithField...)) } } - return ops.errorf("%s unknown field: %#v", spec.Name, args[i]) + return args[i].errorf("%s unknown field: %#v", spec.Name, args[i].str) } // refine the typestack now, so it is maintained even if there's a version error if fs.Type().Typed() { ops.returns(spec, fs.Type()) } if fs.Version() > ops.Version { - return ops.errorf("%s %s field was introduced in v%d. Missed #pragma version?", - spec.Name, args[i], fs.Version()) + return args[i].errorf("%s %s field was introduced in v%d. Missed #pragma version?", + spec.Name, args[i].str, fs.Version()) } ops.pending.WriteByte(fs.Field()) } else { // simple immediate that must be a number from 0-255 - val, err := byteImm(args[i], imm.Name) + val, err := byteImm(args[i].str, imm.Name) if err != nil { if strings.Contains(err.Error(), "unable to parse") { // Perhaps the field works in a different order for j, otherImm := range spec.OpDetails.Immediates { if otherImm.kind == immByte && otherImm.Group != nil { - if _, match := otherImm.Group.SpecByName(args[i]); match { + if _, match := otherImm.Group.SpecByName(args[i].str); match { correctImmediates = append(correctImmediates, strconv.Itoa(j+1)) } } @@ -1138,21 +1180,21 @@ func asmDefault(ops *OpStream, spec *OpSpec, args []string) error { if isPseudoName { errMsg += " with " + joinIntsOnOr("immediate", len(args)) } - return ops.errorf("%s can only use %#v as immediate %s", errMsg, args[i], strings.Join(correctImmediates, " or ")) + return args[i].errorf("%s can only use %#v as immediate %s", errMsg, args[i].str, strings.Join(correctImmediates, " or ")) } } - return ops.errorf("%s %w", spec.Name, err) + return args[i].errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(val) } case immInt8: - val, err := int8Imm(args[i], imm.Name) + val, err := int8Imm(args[i].str, imm.Name) if err != nil { - return ops.errorf("%s %w", spec.Name, err) + return args[i].errorf("%s %w", spec.Name, err) } ops.pending.WriteByte(val) default: - return ops.errorf("unable to assemble immKind %d", imm.kind) + return args[i].errorf("unable to assemble immKind %d", imm.kind) } } return nil @@ -1160,13 +1202,13 @@ func asmDefault(ops *OpStream, spec *OpSpec, args []string) error { // getImm interprets the arg at index argIndex as an immediate that must be // between -128 and 127 (if signed=true) or between 0 and 255 (if signed=false) -func getImm(args []string, argIndex int, signed bool) (int, bool) { +func getImm(args []token, argIndex int, signed bool) (int, bool) { if len(args) <= argIndex { return 0, false } // We want to parse anything from -128 up to 255. So allow 9 bits. // Normal assembly checking will catch signed as byte, vice versa - n, err := strconv.ParseInt(args[argIndex], 0, 9) + n, err := strconv.ParseInt(args[argIndex].str, 0, 9) if err != nil { return 0, false } @@ -1190,7 +1232,7 @@ func anyTypes(n int) StackTypes { return as } -func typeSwap(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeSwap(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { swapped := StackTypes{StackAny, StackAny} top := len(pgm.stack) - 1 if top >= 0 { @@ -1202,7 +1244,7 @@ func typeSwap(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, err return nil, swapped, nil } -func typeDig(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeDig(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { n, ok := getImm(args, 0, false) if !ok { return nil, nil, nil @@ -1219,7 +1261,7 @@ func typeDig(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, erro return anyTypes(depth), returns, nil } -func typeBury(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeBury(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { n, ok := getImm(args, 0, false) if !ok { return nil, nil, nil @@ -1251,7 +1293,7 @@ func typeBury(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, err return pgm.stack[idx:], returns, nil } -func typeFrameDig(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeFrameDig(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { n, ok := getImm(args, 0, true) if !ok { return nil, nil, nil @@ -1272,7 +1314,7 @@ func typeFrameDig(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, return nil, StackTypes{pgm.stack[idx]}, nil } -func typeFrameBury(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeFrameBury(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { n, ok := getImm(args, 0, true) if !ok { return nil, nil, nil @@ -1313,7 +1355,7 @@ func typeFrameBury(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes return pgm.stack[idx:], returns, nil } -func typeEquals(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeEquals(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { top := len(pgm.stack) - 1 if top >= 0 { // Require arg0 and arg1 to have same avm type @@ -1324,7 +1366,7 @@ func typeEquals(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, e return nil, nil, nil } -func typeDup(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeDup(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { top := len(pgm.stack) - 1 if top >= 0 { return nil, StackTypes{pgm.stack[top], pgm.stack[top]}, nil @@ -1332,7 +1374,7 @@ func typeDup(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, erro return nil, nil, nil } -func typeDupTwo(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeDupTwo(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { topTwo := StackTypes{StackAny, StackAny} top := len(pgm.stack) - 1 if top >= 0 { @@ -1344,7 +1386,7 @@ func typeDupTwo(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, e return nil, append(topTwo, topTwo...), nil } -func typeSelect(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeSelect(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { top := len(pgm.stack) - 1 if top >= 2 { return nil, StackTypes{pgm.stack[top-1].union(pgm.stack[top-2])}, nil @@ -1352,7 +1394,7 @@ func typeSelect(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, e return nil, nil, nil } -func typeSetBit(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeSetBit(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { top := len(pgm.stack) - 1 if top >= 2 { return nil, StackTypes{pgm.stack[top-2]}, nil @@ -1360,7 +1402,7 @@ func typeSetBit(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, e return nil, nil, nil } -func typeCover(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeCover(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { n, ok := getImm(args, 0, false) if !ok { return nil, nil, nil @@ -1382,7 +1424,7 @@ func typeCover(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, er return anyTypes(depth), returns, nil } -func typeUncover(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeUncover(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { n, ok := getImm(args, 0, false) if !ok { return nil, nil, nil @@ -1401,23 +1443,23 @@ func typeUncover(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, } func typeByteMath(resultSize uint64) refineFunc { - return func(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { + return func(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { return nil, StackTypes{NewStackType(avmBytes, bound(0, resultSize))}, nil } } -func typeTxField(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeTxField(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { if len(args) != 1 { return nil, nil, nil } - fs, ok := txnFieldSpecByName[args[0]] + fs, ok := txnFieldSpecByName[args[0].str] if !ok { return nil, nil, nil } return StackTypes{fs.ftype}, nil, nil } -func typeStore(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeStore(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { scratchIndex, ok := getImm(args, 0, false) if !ok { return nil, nil, nil @@ -1429,7 +1471,7 @@ func typeStore(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, er return nil, nil, nil } -func typeStores(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeStores(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { top := len(pgm.stack) - 1 if top < 0 { return nil, nil, nil @@ -1452,7 +1494,7 @@ func typeStores(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, e return nil, nil, nil } -func typeLoad(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeLoad(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { scratchIndex, ok := getImm(args, 0, false) if !ok { return nil, nil, nil @@ -1460,7 +1502,7 @@ func typeLoad(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, err return nil, StackTypes{pgm.scratchSpace[scratchIndex]}, nil } -func typeProto(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeProto(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { a, aok := getImm(args, 0, false) _, rok := getImm(args, 1, false) if !aok || !rok { @@ -1475,8 +1517,7 @@ func typeProto(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, er return nil, nil, nil } -func typeLoads(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { - +func typeLoads(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { top := len(pgm.stack) - 1 if top < 0 { return nil, nil, nil @@ -1496,7 +1537,7 @@ func typeLoads(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, er return nil, StackTypes{scratchType}, nil } -func typePopN(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typePopN(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { n, ok := getImm(args, 0, false) if !ok { return nil, nil, nil @@ -1504,7 +1545,7 @@ func typePopN(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, err return anyTypes(n), nil, nil } -func typeDupN(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeDupN(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { n, ok := getImm(args, 0, false) if !ok { return nil, nil, nil @@ -1523,7 +1564,7 @@ func typeDupN(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, err return nil, copies, nil } -func typePushBytess(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typePushBytess(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { types := make(StackTypes, len(args)) for i := range types { types[i] = StackBytes @@ -1532,7 +1573,7 @@ func typePushBytess(pgm *ProgramKnowledge, args []string) (StackTypes, StackType return nil, types, nil } -func typePushInts(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typePushInts(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { types := make(StackTypes, len(args)) for i := range types { types[i] = StackUint64 @@ -1541,10 +1582,10 @@ func typePushInts(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, return nil, types, nil } -func typePushInt(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typePushInt(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { types := make(StackTypes, len(args)) for i := range types { - val, err := strconv.ParseUint(args[i], 10, 64) + val, err := strconv.ParseUint(args[i].str, 10, 64) if err != nil { types[i] = StackUint64 } else { @@ -1554,12 +1595,12 @@ func typePushInt(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, return nil, types, nil } -func typeBzero(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeBzero(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { // Bzero should only allow its input int to be up to maxStringSize bytes return StackTypes{StackUint64.narrowed(bound(0, maxStringSize))}, StackTypes{StackBytes}, nil } -func typeByte(pgm *ProgramKnowledge, args []string) (StackTypes, StackTypes, error) { +func typeByte(pgm *ProgramKnowledge, args []token) (StackTypes, StackTypes, error) { if len(args) == 0 { return nil, StackTypes{StackBytes}, nil } @@ -1591,41 +1632,45 @@ func joinIntsOnOr(singularTerminator string, list ...int) string { return errMsg + singularTerminator + "s" } -func pseudoImmediatesError(ops *OpStream, name string, specs map[int]OpSpec) { +func pseudoImmediatesError(ops *OpStream, mnemonic token, specs map[int]OpSpec) { immediateCounts := make([]int, len(specs)) i := 0 for numImms := range specs { immediateCounts[i] = numImms i++ } - ops.error(name + " expects " + joinIntsOnOr("immediate argument", immediateCounts...)) + ops.record(mnemonic.errorf("%s expects %s", mnemonic.str, joinIntsOnOr("immediate argument", immediateCounts...))) } // getSpec finds the OpSpec we need during assembly based on its name, our current version, and the immediates passed in // Note getSpec handles both normal OpSpecs and those supplied by versionedPseudoOps // The returned string is the spec's name, annotated if it was a pseudoOp with no immediates to help disambiguate typetracking errors -func getSpec(ops *OpStream, name string, args []string) (OpSpec, string, bool) { +func getSpec(ops *OpStream, mnemonic token, argCount int) (OpSpec, string, bool) { + name := mnemonic.str pseudoSpecs, ok := ops.versionedPseudoOps[name] if ok { - pseudo, ok := pseudoSpecs[len(args)] + pseudo, ok := pseudoSpecs[argCount] if !ok { // Could be that pseudoOp wants to handle immediates itself so check -1 key pseudo, ok = pseudoSpecs[anyImmediates] if !ok { // Number of immediates supplied did not match any of the pseudoOps of the given name, so we try to construct a mock spec that can be used to track types - pseudoImmediatesError(ops, name, pseudoSpecs) + pseudoImmediatesError(ops, mnemonic, pseudoSpecs) proto, version, ok := mergeProtos(pseudoSpecs) if !ok { return OpSpec{}, "", false } - pseudo = OpSpec{Name: name, Proto: proto, Version: version, OpDetails: OpDetails{asm: func(*OpStream, *OpSpec, []string) error { return nil }}} + pseudo = OpSpec{Name: name, Proto: proto, Version: version, OpDetails: OpDetails{ + asm: func(*OpStream, *OpSpec, token, []token) *sourceError { return nil }, + }} } } pseudo.Name = name if pseudo.Version > ops.Version { - ops.errorf("%s opcode with %s was introduced in v%d", pseudo.Name, joinIntsOnOr("immediate", len(args)), pseudo.Version) + ops.record(mnemonic.errorf("%s opcode with %s was introduced in v%d", + pseudo.Name, joinIntsOnOr("immediate", argCount), pseudo.Version)) } - if len(args) == 0 { + if argCount == 0 { return pseudo, pseudo.Name + " without immediates", true } return pseudo, pseudo.Name, true @@ -1635,7 +1680,7 @@ func getSpec(ops *OpStream, name string, args []string) (OpSpec, string, bool) { var err error spec, err = unknownOpcodeComplaint(name, ops.Version) // unknownOpcodeComplaint's job is to return a nice error, so err != nil - ops.error(err) + ops.record(mnemonic.error(err)) } return spec, spec.Name, ok } @@ -1764,29 +1809,69 @@ func prepareVersionedPseudoTable(version uint64) map[string]map[int]OpSpec { return m } -type lineError struct { - Line int - Err error +type sourceError struct { + Line int + Column int + Err error +} + +func (se sourceError) Error() string { + if se.Column != 0 { + return fmt.Sprintf("%d:%d: %s", se.Line, se.Column, se.Err.Error()) + } + return fmt.Sprintf("%d: %s", se.Line, se.Err.Error()) +} + +func (se sourceError) Unwrap() error { + return se.Err +} + +func errorLinef(line int, format string, a ...interface{}) *sourceError { + return &sourceError{line, 0, fmt.Errorf(format, a...)} } -func (le lineError) Error() string { - return fmt.Sprintf("%d: %s", le.Line, le.Err.Error()) +func typecheck(expected, got StackType) bool { + // Some ops push 'any' and we wait for run time to see what it is. + // Some of those 'any' are based on fields that we _could_ know now but haven't written a more detailed system of typecheck for (yet). + if expected == StackAny && got == StackNone { // Any is lenient, but stack can't be empty + return false + } + if (expected == StackAny) || (got == StackAny) { + return true + } + return expected == got +} + +type token struct { + str string + col int + line int +} + +func (t token) error(err error) *sourceError { + return &sourceError{t.line, t.col, err} } -func (le lineError) Unwrap() error { - return le.Err +func (t token) errorf(format string, args ...interface{}) *sourceError { + return t.error(fmt.Errorf(format, args...)) +} + +func (t token) errorAfterf(format string, args ...interface{}) *sourceError { + return &sourceError{t.line, t.col + len(t.str), fmt.Errorf(format, args...)} } // newline not included since handled in scanner var tokenSeparators = [256]bool{'\t': true, ' ': true, ';': true} -func tokensFromLine(line string) []string { - var tokens []string +// tokensFromLine splits a line into tokens, ignoring comments. tokens are +// annotated with the provided lineno, and column where they are found. +func tokensFromLine(sourceLine string, lineno int) []token { + var tokens []token i := 0 - for i < len(line) && tokenSeparators[line[i]] { - if line[i] == ';' { - tokens = append(tokens, ";") + for i < len(sourceLine) && tokenSeparators[sourceLine[i]] { + if sourceLine[i] == ';' { + tokens = append(tokens, token{";", i, lineno}) } i++ } @@ -1794,28 +1879,28 @@ func tokensFromLine(line string) []string { start := i inString := false // tracked to allow spaces and comments inside inBase64 := false // tracked to allow '//' inside - for i < len(line) { - if !tokenSeparators[line[i]] { // if not space - switch line[i] { + for i < len(sourceLine) { + if !tokenSeparators[sourceLine[i]] { // if not space + switch sourceLine[i] { case '"': // is a string literal? if !inString { - if i == 0 || i > 0 && tokenSeparators[line[i-1]] { + if i == 0 || i > 0 && tokenSeparators[sourceLine[i-1]] { inString = true } } else { - if line[i-1] != '\\' { // if not escape symbol + if sourceLine[i-1] != '\\' { // if not escape symbol inString = false } } case '/': // is a comment? - if i < len(line)-1 && line[i+1] == '/' && !inBase64 && !inString { + if i < len(sourceLine)-1 && sourceLine[i+1] == '/' && !inBase64 && !inString { if start != i { // if a comment without whitespace - tokens = append(tokens, line[start:i]) + tokens = append(tokens, token{sourceLine[start:i], start, lineno}) } return tokens } case '(': // is base64( seq? - prefix := line[start:i] + prefix := sourceLine[start:i] if prefix == "base64" || prefix == "b64" { inBase64 = true } @@ -1832,14 +1917,14 @@ func tokensFromLine(line string) []string { // we've hit a space, end last token unless inString if !inString { - token := line[start:i] - tokens = append(tokens, token) - if line[i] == ';' { - tokens = append(tokens, ";") + s := sourceLine[start:i] + tokens = append(tokens, token{s, start, lineno}) + if sourceLine[i] == ';' { + tokens = append(tokens, token{";", i, lineno}) } if inBase64 { inBase64 = false - } else if token == "base64" || token == "b64" { + } else if s == "base64" || s == "b64" { inBase64 = true } } @@ -1847,9 +1932,9 @@ func tokensFromLine(line string) []string { // gobble up consecutive whitespace (but notice semis) if !inString { - for i < len(line) && tokenSeparators[line[i]] { - if line[i] == ';' { - tokens = append(tokens, ";") + for i < len(sourceLine) && tokenSeparators[sourceLine[i]] { + if sourceLine[i] == ';' { + tokens = append(tokens, token{";", i, lineno}) } i++ } @@ -1858,8 +1943,8 @@ func tokensFromLine(line string) []string { } // add rest of the string if any - if start < len(line) { - tokens = append(tokens, line[start:i]) + if start < len(sourceLine) { + tokens = append(tokens, token{sourceLine[start:i], start, lineno}) } return tokens @@ -1872,22 +1957,32 @@ func (ops *OpStream) trace(format string, args ...interface{}) { fmt.Fprintf(ops.Trace, format, args...) } -func (ops *OpStream) typeErrorf(format string, args ...interface{}) { +func (ops *OpStream) typeErrorf(opcode token, format string, args ...interface{}) { if ops.typeTracking { - ops.errorf(format, args...) + ops.record(opcode.errorf(format, args...)) } } +func reJoin(instruction string, args []token) string { + var buf bytes.Buffer + buf.WriteString(instruction) + for _, t := range args { + buf.WriteString(" ") + buf.WriteString(t.str) + } + return buf.String() +} + // trackStack checks that the typeStack has `args` on it, then pushes `returns` to it. -func (ops *OpStream) trackStack(args StackTypes, returns StackTypes, instruction []string) { +func (ops *OpStream) trackStack(args StackTypes, returns StackTypes, instruction string, tokens []token) { // If in deadcode, allow anything. Maybe it's some sort of onchain data. if ops.known.deadcode { return } argcount := len(args) if argcount > len(ops.known.stack) && ops.known.bottom.AVMType == avmNone { - ops.typeErrorf("%s expects %d stack arguments but stack height is %d", - strings.Join(instruction, " "), argcount, len(ops.known.stack)) + ops.typeErrorf(tokens[0], "%s expects %d stack arguments but stack height is %d", + reJoin(instruction, tokens[1:]), argcount, len(ops.known.stack)) } else { firstPop := true for i := argcount - 1; i >= 0; i-- { @@ -1900,8 +1995,8 @@ func (ops *OpStream) trackStack(args StackTypes, returns StackTypes, instruction ops.trace(", %s", argType) } if !stype.overlaps(argType) { - ops.typeErrorf("%s arg %d wanted type %s got %s", - strings.Join(instruction, " "), i, argType, stype) + ops.typeErrorf(tokens[0], "%s arg %d wanted type %s got %s", + reJoin(instruction, tokens[1:]), i, argType, stype) } } if !firstPop { @@ -1922,49 +2017,55 @@ func (ops *OpStream) trackStack(args StackTypes, returns StackTypes, instruction } // nextStatement breaks tokens into two slices at the first semicolon and expands macros along the way. -func nextStatement(ops *OpStream, tokens []string) (current, rest []string) { +func nextStatement(ops *OpStream, tokens []token) (current, rest []token) { for i := 0; i < len(tokens); i++ { token := tokens[i] - replacement, ok := ops.macros[token] + replacement, ok := ops.macros[token.str] if ok { - tokens = append(tokens[0:i], append(replacement, tokens[i+1:]...)...) + tokens = append(tokens[0:i], append(replacement[1:], tokens[i+1:]...)...) // backup to handle potential re-expansion of the first token in the expansion i-- continue } - if token == ";" { + if token.str == ";" { return tokens[:i], tokens[i+1:] } } return tokens, nil } -type directiveFunc func(*OpStream, []string) error +type directiveFunc func(*OpStream, []token) *sourceError var directives = map[string]directiveFunc{"pragma": pragma, "define": define} // assemble reads text from an input and accumulates the program func (ops *OpStream) assemble(text string) error { if ops.Version > LogicVersion && ops.Version != assemblerNoVersion { - return ops.errorf("Can not assemble version %d", ops.Version) + err := fmt.Errorf("Can not assemble version %d", ops.Version) + ops.record(&sourceError{0, 0, err}) + return err } if strings.TrimSpace(text) == "" { - return ops.errorf("Cannot assemble empty program text") + err := errors.New("Cannot assemble empty program text") + ops.record(&sourceError{0, 0, err}) + return err } fin := strings.NewReader(text) scanner := bufio.NewScanner(fin) for scanner.Scan() { ops.sourceLine++ line := scanner.Text() - tokens := tokensFromLine(line) + tokens := tokensFromLine(line, ops.sourceLine) if len(tokens) > 0 { - if first := tokens[0]; first[0] == '#' { - directive := first[1:] + if first := tokens[0]; first.str[0] == '#' { + directive := first.str[1:] if dFunc, ok := directives[directive]; ok { - _ = dFunc(ops, tokens) - ops.trace("%3d: %s line\n", ops.sourceLine, first) + if err := dFunc(ops, tokens); err != nil { + ops.record(err) + } + ops.trace("%3d: %s line\n", first.line, first.str) } else { - ops.errorf("Unknown directive: %s", directive) + ops.record(first.errorf("unknown directive: %s", directive)) } continue } @@ -1981,22 +2082,22 @@ func (ops *OpStream) assemble(text string) error { if ops.versionedPseudoOps == nil { ops.versionedPseudoOps = prepareVersionedPseudoTable(ops.Version) } - opstring := current[0] + opstring := current[0].str if opstring[len(opstring)-1] == ':' { labelName := opstring[:len(opstring)-1] if _, ok := ops.macros[labelName]; ok { - ops.errorf("Cannot create label with same name as macro: %s", labelName) + ops.record(current[0].errorf("Cannot create label with same name as macro: %s", labelName)) } else { - ops.createLabel(opstring[:len(opstring)-1]) + ops.createLabel(current[0]) } current = current[1:] if len(current) == 0 { ops.trace("%3d: label only\n", ops.sourceLine) continue } - opstring = current[0] + opstring = current[0].str } - spec, expandedName, ok := getSpec(ops, opstring, current[1:]) + spec, expandedName, ok := getSpec(ops, current[0], len(current)-1) if ok { ops.trace("%3d: %s\t", ops.sourceLine, opstring) ops.recordSourceLine() @@ -2007,7 +2108,7 @@ func (ops *OpStream) assemble(text string) error { if spec.refine != nil { nargs, nreturns, err := spec.refine(&ops.known, current[1:]) if err != nil { - ops.typeErrorf("%w", err) + ops.typeErrorf(current[0], "%w", err) } if nargs != nil { args = nargs @@ -2016,9 +2117,10 @@ func (ops *OpStream) assemble(text string) error { returns = nreturns } } - ops.trackStack(args, returns, append([]string{expandedName}, current[1:]...)) - spec.asm(ops, &spec, current[1:]) //nolint:errcheck // ignore error and continue, to collect more errors - + ops.trackStack(args, returns, expandedName, current) + if err := spec.asm(ops, &spec, current[0], current[1:]); err != nil { + ops.record(err) + } if spec.deadens() { // An unconditional branch deadens the following code ops.known.deaden() } @@ -2036,16 +2138,7 @@ func (ops *OpStream) assemble(text string) error { if errors.Is(err, bufio.ErrTooLong) { err = errors.New("line too long") } - ops.error(err) - } - - // backward compatibility: do not allow jumps past last instruction in v1 - if ops.Version <= 1 { - for label, dest := range ops.labels { - if dest == ops.pending.Len() { - ops.errorf("label %#v is too far away", label) - } - } + ops.record(&sourceError{ops.sourceLine, 0, err}) } if ops.Version >= optimizeConstantsEnabledVersion { @@ -2066,21 +2159,23 @@ func (ops *OpStream) assemble(text string) error { return nil } -func (ops *OpStream) cycle(macro string, previous ...string) bool { - replacement, ok := ops.macros[macro] +// cycle return a slice of strings that constitute a cycle, if one is +// found. That is, the first token expands to the second, and so on, with the +// first and last string being the same. +func (ops *OpStream) cycle(macro token, previous []string) []string { + replacement, ok := ops.macros[macro.str] if !ok { - return false + return nil } - if len(previous) > 0 && macro == previous[0] { - ops.errorf("Macro cycle discovered: %s", strings.Join(append(previous, macro), " -> ")) - return true + if len(previous) > 0 && macro.str == previous[0] { + return append(previous, macro.str) } - for _, token := range replacement { - if ops.cycle(token, append(previous, macro)...) { - return true + for _, repl := range replacement[1:] { + if found := ops.cycle(repl, append(previous, macro.str)); found != nil { + return found } } - return false + return nil } // recheckMacroNames goes through previously defined macros and ensures they @@ -2091,8 +2186,8 @@ func (ops *OpStream) recheckMacroNames() error { for macroName := range ops.macros { err := checkMacroName(macroName, ops.Version, ops.labels) if err != nil { + ops.record(ops.macros[macroName][0].error(err)) delete(ops.macros, macroName) - ops.error(err) errored = true } } @@ -2156,57 +2251,58 @@ func checkMacroName(macroName string, version uint64, labels map[string]int) err return nil } -func define(ops *OpStream, tokens []string) error { - if tokens[0] != "#define" { - return ops.errorf("invalid syntax: %s", tokens[0]) +func define(ops *OpStream, tokens []token) *sourceError { + if tokens[0].str != "#define" { + return tokens[0].errorf("invalid syntax: %s", tokens[0].str) } if len(tokens) < 3 { - return ops.errorf("define directive requires a name and body") + return tokens[len(tokens)-1].errorf("define directive requires a name and body") } - name := tokens[1] + name := tokens[1].str err := checkMacroName(name, ops.Version, ops.labels) if err != nil { - return ops.error(err) + return tokens[1].error(err) } saved, ok := ops.macros[name] - ops.macros[name] = tokens[2:len(tokens):len(tokens)] - if ops.cycle(tokens[1]) { + ops.macros[name] = tokens[1:len(tokens):len(tokens)] // include the name itself at the front + if found := ops.cycle(tokens[1], nil); found != nil { if ok { - ops.macros[tokens[1]] = saved + ops.macros[name] = saved // restore previous macro } else { - delete(ops.macros, tokens[1]) + delete(ops.macros, name) // remove new macro that caused cycle } + return tokens[1].errorf("macro expansion cycle discovered: %s", strings.Join(found, " -> ")) } return nil } -func pragma(ops *OpStream, tokens []string) error { - if tokens[0] != "#pragma" { - return ops.errorf("invalid syntax: %s", tokens[0]) +func pragma(ops *OpStream, tokens []token) *sourceError { + if tokens[0].str != "#pragma" { + return tokens[0].errorf("invalid syntax: %s", tokens[0].str) } if len(tokens) < 2 { - return ops.error("empty pragma") + return tokens[0].errorf("empty pragma") } - key := tokens[1] + key := tokens[1].str switch key { case "version": if len(tokens) < 3 { - return ops.error("no version value") + return tokens[1].errorf("no version value") } if len(tokens) > 3 { - return ops.errorf("unexpected extra tokens: %s", strings.Join(tokens[3:], " ")) + return tokens[3].errorf("unexpected extra tokens:%s", reJoin("", tokens[3:])) } - value := tokens[2] var ver uint64 if ops.pending.Len() > 0 { - return ops.error("#pragma version is only allowed before instructions") + return tokens[0].errorf("#pragma version is only allowed before instructions") } + value := tokens[2].str ver, err := strconv.ParseUint(value, 0, 64) if err != nil { - return ops.errorf("bad #pragma version: %#v", value) + return tokens[2].errorf("bad #pragma version: %#v", value) } if ver > AssemblerMaxVersion { - return ops.errorf("unsupported version: %d", ver) + return tokens[2].errorf("unsupported version: %d", ver) } // We initialize Version with assemblerNoVersion as a marker for @@ -2214,24 +2310,27 @@ func pragma(ops *OpStream, tokens []string) error { // version for v1. if ops.Version == assemblerNoVersion { ops.Version = ver - return ops.recheckMacroNames() + if err := ops.recheckMacroNames(); err != nil { + return tokens[2].error(err) + } + return nil } if ops.Version != ver { - return ops.errorf("version mismatch: assembling v%d with v%d assembler", ver, ops.Version) + return tokens[2].errorf("version mismatch: assembling v%d with v%d assembler", ver, ops.Version) } // ops.Version is already correct, or needed to be upped. return nil case "typetrack": if len(tokens) < 3 { - return ops.error("no typetrack value") + return tokens[1].errorf("no typetrack value") } if len(tokens) > 3 { - return ops.errorf("unexpected extra tokens: %s", strings.Join(tokens[3:], " ")) + return tokens[3].errorf("unexpected extra tokens:%s", reJoin("", tokens[3:])) } - value := tokens[2] + value := tokens[2].str on, err := strconv.ParseBool(value) if err != nil { - return ops.errorf("bad #pragma typetrack: %#v", value) + return tokens[2].errorf("bad #pragma typetrack: %#v", value) } prev := ops.typeTracking if !prev && on { @@ -2241,41 +2340,45 @@ func pragma(ops *OpStream, tokens []string) error { return nil default: - return ops.errorf("unsupported pragma directive: %#v", key) + return tokens[0].errorf("unsupported pragma directive: %#v", key) } } func (ops *OpStream) resolveLabels() { - saved := ops.sourceLine raw := ops.pending.Bytes() reported := make(map[string]bool) for _, lr := range ops.labelReferences { - ops.sourceLine = lr.sourceLine // so errors get reported where the label was used - dest, ok := ops.labels[lr.label] + dest, ok := ops.labels[lr.label.str] if !ok { - if !reported[lr.label] { - ops.errorf("reference to undefined label %#v", lr.label) + if !reported[lr.label.str] { + ops.record(lr.label.errorf("reference to undefined label %#v", lr.label.str)) } - reported[lr.label] = true + reported[lr.label.str] = true continue } + // backward compatibility: do not allow jumps past last instruction in v1 + if ops.Version <= 1 { + if dest == ops.pending.Len() { + ops.record(lr.label.errorf("label %#v is too far away", lr.label.str)) + } + } + // All branch targets are encoded as 2 offset bytes. The destination is relative to the end of the // instruction they appear in, which is available in lr.offsetPostion if ops.Version < backBranchEnabledVersion && dest < lr.offsetPosition { - ops.errorf("label %#v is a back reference, back jump support was introduced in v4", lr.label) + ops.record(lr.label.errorf("label %#v is a back reference, back jump support was introduced in v4", lr.label.str)) continue } jump := dest - lr.offsetPosition if jump > 0x7fff { - ops.errorf("label %#v is too far away", lr.label) + ops.record(lr.label.errorf("label %#v is too far away", lr.label.str)) continue } raw[lr.position] = uint8(jump >> 8) raw[lr.position+1] = uint8(jump & 0x0ff) } ops.pending = *bytes.NewBuffer(raw) - ops.sourceLine = saved } // AssemblerDefaultVersion what version of code do we emit by default @@ -2425,14 +2528,14 @@ func (ops *OpStream) optimizeConstants(refs []constReference, constBlock []inter } } if !found { - err = ops.lineErrorf(ops.OffsetToLine[ref.getPosition()], "Value not found in constant block: %v", ref.getValue()) + err = errorLinef(ops.OffsetToLine[ref.getPosition()], "value not found in constant block: %v", ref.getValue()) return } } for _, f := range freqs { if f.freq == 0 { - err = ops.errorf("Member of constant block is not used: %v", f.value) + err = errorLinef(ops.sourceLine, "member of constant block is not used: %v", f.value) return } } @@ -2463,7 +2566,7 @@ func (ops *OpStream) optimizeConstants(refs []constReference, constBlock []inter } } if newIndex == -1 { - return nil, ops.lineErrorf(ops.OffsetToLine[ref.getPosition()], "Value not found in constant block: %v", ref.getValue()) + return nil, errorLinef(ops.OffsetToLine[ref.getPosition()], "value not found in constant block: %v", ref.getValue()) } newBytes := ref.makeNewReference(ops, singleton, newIndex) @@ -2565,12 +2668,12 @@ func (ops *OpStream) prependCBlocks() []byte { out := make([]byte, pbl+outl) pl, err := prebytes.Read(out) if pl != pbl || err != nil { - ops.errorf("wat: %d prebytes, %d to buffer? err=%w", pbl, pl, err) + ops.record(&sourceError{ops.sourceLine, 0, fmt.Errorf("%d prebytes, %d to buffer? %w", pbl, pl, err)}) return nil } ol, err := ops.pending.Read(out[pl:]) if ol != outl || err != nil { - ops.errorf("%d program bytes but %d to buffer. err=%w", outl, ol, err) + ops.record(&sourceError{ops.sourceLine, 0, fmt.Errorf("%d program bytes but %d to buffer. %w", outl, ol, err)}) return nil } @@ -2584,48 +2687,17 @@ func (ops *OpStream) prependCBlocks() []byte { return out } -func (ops *OpStream) error(problem interface{}) error { - return ops.lineError(ops.sourceLine, problem) -} - -func (ops *OpStream) lineError(line int, problem interface{}) error { - var err lineError - switch p := problem.(type) { - case string: - err = lineError{Line: line, Err: errors.New(p)} - case error: - err = lineError{Line: line, Err: p} - default: - err = lineError{Line: line, Err: fmt.Errorf("%#v", p)} - } - ops.Errors = append(ops.Errors, err) - return err -} - -func (ops *OpStream) errorf(format string, a ...interface{}) error { - return ops.error(fmt.Errorf(format, a...)) -} - -func (ops *OpStream) lineErrorf(line int, format string, a ...interface{}) error { - return ops.lineError(line, fmt.Errorf(format, a...)) +// record puts an error onto a list for reporting later. The hope is that the +// assembler can keep going after an error that is "swallowed" this way, so that +// more than one TEAL error can be reported in one pass. By explicitly +// swallowing the error this way, we can use the linter properly. +func (ops *OpStream) record(se *sourceError) { + ops.Errors = append(ops.Errors, *se) } -func (ops *OpStream) warn(problem interface{}) error { - var le *lineError - switch p := problem.(type) { - case string: - le = &lineError{Line: ops.sourceLine, Err: errors.New(p)} - case error: - le = &lineError{Line: ops.sourceLine, Err: p} - default: - le = &lineError{Line: ops.sourceLine, Err: fmt.Errorf("%#v", p)} - } - warning := fmt.Errorf("warning: %w", le) +func (ops *OpStream) warn(t token, format string, a ...interface{}) { + warning := &sourceError{Line: t.line, Column: t.col, Err: fmt.Errorf(format, a...)} ops.Warnings = append(ops.Warnings, warning) - return warning -} -func (ops *OpStream) warnf(format string, a ...interface{}) error { - return ops.warn(fmt.Errorf(format, a...)) } // ReportMultipleErrors issues accumulated warnings and outputs errors to an io.Writer. @@ -3046,12 +3118,12 @@ func disassembleInstrumented(program []byte, labels map[int]string) (text string ds.pcOffset = append(ds.pcOffset, PCOffset{dis.pc, out.Len()}) // Actually do the disassembly - var line string - line, err = disassemble(&dis, &op) + var instruction string + instruction, err = disassemble(&dis, &op) if err != nil { return } - out.WriteString(line) + out.WriteString(instruction) out.WriteRune('\n') dis.pc = dis.nextpc } diff --git a/data/transactions/logic/assembler_test.go b/data/transactions/logic/assembler_test.go index fd3b527b43..713528b72c 100644 --- a/data/transactions/logic/assembler_test.go +++ b/data/transactions/logic/assembler_test.go @@ -558,11 +558,24 @@ pop require.Equal(t, ops1.Program, ops2.Program) } -type Expect struct { +type expect struct { l int + c int s string } +func exp(l int, s string, extra ...int) expect { + e := expect{l: l, c: 0, s: s} + switch len(extra) { + case 0: /* nothing */ + case 1: + e.c = extra[0] + default: + panic(extra) + } + return e +} + func testMatch(t testing.TB, actual, expected string) (ok bool) { defer func() { t.Helper() @@ -613,7 +626,7 @@ func summarize(trace *strings.Builder) string { return msg + "(trace truncated)\n" } -func testProg(t testing.TB, source string, ver uint64, expected ...Expect) *OpStream { +func testProg(t testing.TB, source string, ver uint64, expected ...expect) *OpStream { t.Helper() ops, err := assembleWithTrace(source, ver) if len(expected) == 0 { @@ -663,7 +676,7 @@ func testProg(t testing.TB, source string, ver uint64, expected ...Expect) *OpSt t.FailNow() } } else { - var found *lineError + var found *sourceError for i := range errors { if errors[i].Line == exp.l { found = &errors[i] @@ -674,7 +687,11 @@ func testProg(t testing.TB, source string, ver uint64, expected ...Expect) *OpSt t.Log(fmt.Sprintf("Errors: %v", errors)) } require.NotNil(t, found, "Error %s was not found on line %d", exp.s, exp.l) - msg := found.Unwrap().Error() + if exp.c != 0 { + require.Equal(t, exp.c, found.Column, "Error %s was not found at column %d. %s was.", + exp.s, exp.c, found.Error()) + } + msg := found.Unwrap().Error() // unwrap avoids line,col prefix for easier matching if !testMatch(t, msg, exp.s) { t.Log(summarize(ops.Trace)) t.FailNow() @@ -686,7 +703,7 @@ func testProg(t testing.TB, source string, ver uint64, expected ...Expect) *OpSt return ops } -func testLine(t *testing.T, line string, ver uint64, expected string) { +func testLine(t *testing.T, line string, ver uint64, expected string, col ...int) { t.Helper() // By embedding the source line between two other lines, the // test for the correct line number in the error is more @@ -696,35 +713,36 @@ func testLine(t *testing.T, line string, ver uint64, expected string) { testProg(t, source, ver) return } - testProg(t, source, ver, Expect{2, expected}) + testProg(t, source, ver, exp(2, expected, col...)) } func TestAssembleTxna(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - testLine(t, "txna Accounts 256", AssemblerMaxVersion, "txna i beyond 255: 256") - testLine(t, "txna ApplicationArgs 256", AssemblerMaxVersion, "txna i beyond 255: 256") - testLine(t, "txna Sender 256", AssemblerMaxVersion, "txna unknown field: \"Sender\"") - testLine(t, "gtxna 0 Accounts 256", AssemblerMaxVersion, "gtxna i beyond 255: 256") + testLine(t, "txna Accounts 256", AssemblerMaxVersion, "txna i beyond 255: 256", 14) + testLine(t, "txna ApplicationArgs 256", AssemblerMaxVersion, "txna i beyond 255: 256", 21) + testLine(t, "txna Sender 256", AssemblerMaxVersion, "txna unknown field: \"Sender\"", 5) + testLine(t, "gtxna 0 Accounts 256", AssemblerMaxVersion, "gtxna i beyond 255: 256", 17) testLine(t, "gtxna 0 ApplicationArgs 256", AssemblerMaxVersion, "gtxna i beyond 255: 256") - testLine(t, "gtxna 256 Accounts 0", AssemblerMaxVersion, "gtxna t beyond 255: 256") - testLine(t, "gtxna 0 Sender 256", AssemblerMaxVersion, "gtxna unknown field: \"Sender\"") + testLine(t, "gtxna 256 Accounts 0", AssemblerMaxVersion, "gtxna t beyond 255: 256", 6) + testLine(t, "gtxna 0 Sender 256", AssemblerMaxVersion, "gtxna unknown field: \"Sender\"", 8) testLine(t, "gtxna ApplicationArgs 0 255", AssemblerMaxVersion, "gtxna can only use \"ApplicationArgs\" as immediate 2") testLine(t, "gtxna 0 255 ApplicationArgs", AssemblerMaxVersion, "gtxna can only use \"255\" as immediate 1 or 3") testLine(t, "txn Accounts 256", AssemblerMaxVersion, "txn i beyond 255: 256") testLine(t, "txn ApplicationArgs 256", AssemblerMaxVersion, "txn i beyond 255: 256") - testLine(t, "txn 255 ApplicationArgs", AssemblerMaxVersion, "txn with 2 immediates can only use \"255\" as immediate 2") + testLine(t, "txn 255 ApplicationArgs", AssemblerMaxVersion, "txn with 2 immediates can only use \"255\" as immediate 2", 4) testLine(t, "txn Sender 256", AssemblerMaxVersion, "\"Sender\" field of txn can only be used with 1 immediate") testLine(t, "gtxn 0 Accounts 256", AssemblerMaxVersion, "gtxn i beyond 255: 256") testLine(t, "gtxn 0 ApplicationArgs 256", AssemblerMaxVersion, "gtxn i beyond 255: 256") testLine(t, "gtxn 256 Accounts 0", AssemblerMaxVersion, "gtxn t beyond 255: 256") testLine(t, "gtxn 0 Sender 256", AssemblerMaxVersion, "\"Sender\" field of gtxn can only be used with 2 immediates") - testLine(t, "gtxn ApplicationArgs 0 255", AssemblerMaxVersion, "gtxn with 3 immediates can only use \"ApplicationArgs\" as immediate 2") + testLine(t, "gtxn ApplicationArgs 0 255", AssemblerMaxVersion, "gtxn with 3 immediates can only use \"ApplicationArgs\" as immediate 2", 5) testLine(t, "gtxn 0 255 ApplicationArgs", AssemblerMaxVersion, "gtxn with 3 immediates can only use \"255\" as immediate 1 or 3") testLine(t, "txn Accounts 0", 1, "txn opcode with 2 immediates was introduced in v2") + testLine(t, "txn", 2, "txn expects 1 or 2 immediate arguments") testLine(t, "txn Accounts 0 1", 2, "txn expects 1 or 2 immediate arguments") testLine(t, "txna Accounts 0 1", AssemblerMaxVersion, "txna expects 2 immediate arguments") testLine(t, "txn Accounts 0 1", AssemblerMaxVersion, "txn expects 1 or 2 immediate arguments") @@ -758,14 +776,15 @@ func TestAssembleGlobal(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - testLine(t, "global", AssemblerMaxVersion, "global expects 1 immediate argument") + testLine(t, "global", AssemblerMaxVersion, "global expects 1 immediate argument", 6) + testLine(t, "global aa bb", AssemblerMaxVersion, "global expects 1 immediate argument", 10) testLine(t, "global a", AssemblerMaxVersion, "global unknown field: \"a\"") testProg(t, "global MinTxnFee; int 2; +", AssemblerMaxVersion) testProg(t, "global ZeroAddress; byte 0x12; concat; len", AssemblerMaxVersion) testProg(t, "global MinTxnFee; byte 0x12; concat", AssemblerMaxVersion, - Expect{1, "concat arg 0 wanted type []byte..."}) + exp(1, "concat arg 0 wanted type []byte...", 29)) testProg(t, "int 2; global ZeroAddress; +", AssemblerMaxVersion, - Expect{1, "+ arg 1 wanted type uint64..."}) + exp(1, "+ arg 1 wanted type uint64...", 27)) } func TestAssembleDefault(t *testing.T) { @@ -774,10 +793,10 @@ func TestAssembleDefault(t *testing.T) { source := `byte 0x1122334455 int 1 -+ + + // comment ` - testProg(t, source, AssemblerMaxVersion, Expect{3, "+ arg 0 wanted type uint64 got [5]byte"}) + testProg(t, source, AssemblerMaxVersion, exp(3, "+ arg 0 wanted type uint64 got [5]byte", 1)) } // mutateProgVersion replaces version (first two symbols) in hex-encoded program @@ -792,11 +811,11 @@ func TestOpUint(t *testing.T) { for v := uint64(1); v <= AssemblerMaxVersion; v++ { t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) { ops := newOpStream(v) - ops.IntLiteral(0xcafebabe) + ops.intLiteral(0xcafef00d) prog := ops.prependCBlocks() require.NotNil(t, prog) s := hex.EncodeToString(prog) - expected := mutateProgVersion(v, "012001bef5fad70c22") + expected := mutateProgVersion(v, "xx20018de0fbd70c22") require.Equal(t, expected, s) }) } @@ -809,11 +828,11 @@ func TestOpUint64(t *testing.T) { for v := uint64(1); v <= AssemblerMaxVersion; v++ { t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) { ops := newOpStream(v) - ops.IntLiteral(0xcafebabecafebabe) + ops.intLiteral(0xcafef00dcafef00d) prog := ops.prependCBlocks() require.NotNil(t, prog) s := hex.EncodeToString(prog) - require.Equal(t, mutateProgVersion(v, "012001bef5fad7ecd7aeffca0122"), s) + require.Equal(t, mutateProgVersion(v, "xx20018de0fbd7dc81bcffca0122"), s) }) } } @@ -825,12 +844,12 @@ func TestOpBytes(t *testing.T) { for v := uint64(1); v <= AssemblerMaxVersion; v++ { t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) { ops := newOpStream(v) - ops.ByteLiteral([]byte("abcdef")) + ops.byteLiteral([]byte("abcdef")) prog := ops.prependCBlocks() require.NotNil(t, prog) s := hex.EncodeToString(prog) require.Equal(t, mutateProgVersion(v, "0126010661626364656628"), s) - testProg(t, "byte 0x7; len", v, Expect{1, "...odd length hex string"}) + testProg(t, "byte 0x7; len", v, exp(1, "...odd length hex string", 5)) }) } } @@ -839,8 +858,8 @@ func TestAssembleInt(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - expectedDefaultConsts := "012001bef5fad70c22" - expectedOptimizedConsts := "0181bef5fad70c" + expectedDefaultConsts := "xx20018de0fbd70c22" + expectedOptimizedConsts := "xx818de0fbd70c" for v := uint64(1); v <= AssemblerMaxVersion; v++ { t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) { @@ -849,7 +868,7 @@ func TestAssembleInt(t *testing.T) { expected = expectedOptimizedConsts } - text := "int 0xcafebabe" + text := "int 0xcafef00d" ops := testProg(t, text, v) s := hex.EncodeToString(ops.Program) require.Equal(t, mutateProgVersion(v, expected), s) @@ -893,9 +912,30 @@ func TestAssembleBytes(t *testing.T) { expectedDefaultConsts := "0126010661626364656628" expectedOptimizedConsts := "018006616263646566" - bad := [][]string{ - {"byte", "...needs byte literal argument"}, - {`byte "john" "doe"`, "...with extraneous argument"}, + bad := []struct { + source string + msg string + col int + }{ + {"byte", "...needs byte literal argument", 4}, + {`byte "john" "doe"`, "...with extraneous argument", 12}, + {"byte base64", "... base64 needs...", 5}, // maybe we should report error at end of "base64"? + {"byte base32", "... base32 needs...", 5}, + // these next messages could have the exact column of the problem, but + // would require too much refactoring for the value + {`byte "jo\qhn"`, "...invalid escape sequence...", 5}, + {`byte base64(YWJjZGVm)extrajunk`, "...must end at first closing parenthesis", 5}, + {`byte base64(YWJjZGVm)x`, "...must end at first closing parenthesis", 5}, + {`byte base64(YWJjZGVm`, "...lacks closing parenthesis", 5}, + {`byte base32(MFRGGZDFMY)extrajunk`, "...must end at first closing parenthesis", 5}, + {`byte base32(MFRGGZDFMY)x`, "...must end at first closing parenthesis", 5}, + {`byte base32(MFRGGZDFMY`, "...lacks closing parenthesis", 5}, + {`byte b32 mfrggzdfmy`, "...illegal base32 data at input byte 0", 9}, + {`byte b32 MFrggzdfmy`, "...illegal base32 data at input byte 2", 9}, + {`byte b32(mfrggzdfmy)`, "...illegal base32 data at input byte 4", 5}, + {`byte b32(MFrggzdfmy)`, "...illegal base32 data at input byte 6", 5}, + {`byte base32(mfrggzdfmy)`, "...illegal base32 data at input byte 7", 5}, + {`byte base32(MFrggzdfmy)`, "...illegal base32 data at input byte 9", 5}, } for v := uint64(1); v <= AssemblerMaxVersion; v++ { @@ -916,10 +956,10 @@ func TestAssembleBytes(t *testing.T) { } for _, b := range bad { - testProg(t, b[0], v, Expect{1, b[1]}) + testProg(t, b.source, v, exp(1, b.msg, b.col)) // pushbytes should produce the same errors if v >= 3 { - testProg(t, strings.Replace(b[0], "byte", "pushbytes", 1), v, Expect{1, b[1]}) + testProg(t, strings.Replace(b.source, "byte", "pushbytes", 1), v, exp(1, b.msg, b.col+len("pushs"))) } } }) @@ -970,13 +1010,13 @@ func TestManualCBlocks(t *testing.T) { "bytecblock 0x44 0x55 0x4455; bytec_0; byte 0x55; concat; bytec_2; ==") // But complain if they do not - testProg(t, "intcblock 4; int 3;", 3, Expect{1, "int 3 used without 3 in intcblock"}) - testProg(t, "bytecblock 0x44; byte 0x33;", 3, Expect{1, "byte/addr/method used without value in bytecblock"}) + testProg(t, "intcblock 4; int 3;", 3, exp(1, "value 3 does not appear...", 17)) + testProg(t, "bytecblock 0x44; byte 0x33;", 3, exp(1, "value 0x33 does not appear...", 22)) // Or if the ref comes before the constant block, even if they match - testProg(t, "int 5; intcblock 4;", 3, Expect{1, "intcblock following int"}) - testProg(t, "int 4; intcblock 4;", 3, Expect{1, "intcblock following int"}) - testProg(t, "addr RWXCBB73XJITATVQFOI7MVUUQOL2PFDDSDUMW4H4T2SNSX4SEUOQ2MM7F4; bytecblock 0x44", 3, Expect{1, "bytecblock following byte/addr/method"}) + testProg(t, "int 5; intcblock 4;", 3, exp(1, "intcblock following int", 7)) + testProg(t, "int 4; intcblock 4;", 3, exp(1, "intcblock following int", 7)) + testProg(t, "addr RWXCBB73XJITATVQFOI7MVUUQOL2PFDDSDUMW4H4T2SNSX4SEUOQ2MM7F4; bytecblock 0x44", 3, exp(1, "bytecblock following byte/addr/method")) // But we can't complain precisely once backjumps are allowed, so we force // compile to push*. (We don't analyze the CFG, so we don't know if we can @@ -989,9 +1029,9 @@ func TestManualCBlocks(t *testing.T) { "bytecblock 0x44 0x55 0x4455; byte 0x44; byte 0x55; concat; byte 0x4455; ==", "bytecblock 0x44 0x55 0x4455; pushbytes 0x44; pushbytes 0x55; concat; pushbytes 0x4455; ==") // Can't switch to push* after the fact. - testProg(t, "int 5; intcblock 4;", 4, Expect{1, "intcblock following int"}) - testProg(t, "int 4; intcblock 4;", 4, Expect{1, "intcblock following int"}) - testProg(t, "addr RWXCBB73XJITATVQFOI7MVUUQOL2PFDDSDUMW4H4T2SNSX4SEUOQ2MM7F4; bytecblock 0x44", 4, Expect{1, "bytecblock following byte/addr/method"}) + testProg(t, "int 5; intcblock 4;", 4, exp(1, "intcblock following int", 7)) + testProg(t, "int 4; intcblock 4;", 4, exp(1, "intcblock following int", 7)) + testProg(t, "addr RWXCBB73XJITATVQFOI7MVUUQOL2PFDDSDUMW4H4T2SNSX4SEUOQ2MM7F4; bytecblock 0x44", 4, exp(1, "bytecblock following byte/addr/method", 65)) // Ignore manually added cblocks in deadcode, so they can be added easily to // existing programs. There are proposals to put metadata there. @@ -1022,12 +1062,12 @@ func TestManualCBlocksPreBackBranch(t *testing.T) { testProg(t, "intcblock 10 20; int 10;", backBranchEnabledVersion-1) // By the same token, assembly complains if that intcblock doesn't have the // constant. In v3, and v3 only, it *could* pushint. - testProg(t, "intcblock 10 20; int 30;", backBranchEnabledVersion-1, Expect{1, "int 30 used..."}) + testProg(t, "intcblock 10 20; int 30;", backBranchEnabledVersion-1, exp(1, "value 30 does not appear...")) // Since the second intcblock is dead, the `int 10` "sees" the first block, not the second testProg(t, "intcblock 10 20; b skip; intcblock 3 4 5; skip: int 10;", backBranchEnabledVersion-1) testProg(t, "intcblock 10 20; b skip; intcblock 3 4 5; skip: int 3;", backBranchEnabledVersion-1, - Expect{1, "int 3 used..."}) + exp(1, "value 3 does not appear...", 52)) // Here, the intcblock in effect is unknowable, better to force the user to // use intc (unless pushint is available to save the day). @@ -1038,23 +1078,23 @@ func TestManualCBlocksPreBackBranch(t *testing.T) { // backBranchEnabledVersion-2 does not testProg(t, "intcblock 10 20; txn NumAppArgs; bz skip; intcblock 3 4 5; skip: int 10;", backBranchEnabledVersion-2, - Expect{1, "int 10 used with manual intcblocks. Use intc."}) + exp(1, "int 10 used with manual intcblocks. Use intc.", 65)) testProg(t, "intcblock 10 20; txn NumAppArgs; bz skip; intcblock 3 4 5; skip: int 3;", backBranchEnabledVersion-2, - Expect{1, "int 3 used with manual intcblocks. Use intc."}) + exp(1, "int 3 used with manual intcblocks. Use intc.", 65)) // REPEAT ABOVE, BUT FOR BYTE BLOCKS testProg(t, "bytecblock 0x10 0x20; byte 0x10;", backBranchEnabledVersion-1) - testProg(t, "bytecblock 0x10 0x20; byte 0x30;", backBranchEnabledVersion-1, Expect{1, "byte/addr/method used..."}) + testProg(t, "bytecblock 0x10 0x20; byte 0x30;", backBranchEnabledVersion-1, exp(1, "value 0x30 does not appear...", 27)) testProg(t, "bytecblock 0x10 0x20; b skip; bytecblock 0x03 0x04 0x05; skip: byte 0x10;", backBranchEnabledVersion-1) testProg(t, "bytecblock 0x10 0x20; b skip; bytecblock 0x03 0x04 0x05; skip: byte 0x03;", backBranchEnabledVersion-1, - Expect{1, "byte/addr/method used..."}) + exp(1, "value 0x03 does not appear...", 68)) testProg(t, "bytecblock 0x10 0x20; txn NumAppArgs; bz skip; bytecblock 0x03 0x04 0x05; skip: byte 0x10;", backBranchEnabledVersion-1) testProg(t, "bytecblock 0x10 0x20; txn NumAppArgs; bz skip; bytecblock 0x03 0x04 0x05; skip: byte 0x03;", backBranchEnabledVersion-1) testProg(t, "bytecblock 0x10 0x20; txn NumAppArgs; bz skip; bytecblock 0x03 0x04 0x05; skip: byte 0x10;", backBranchEnabledVersion-2, - Expect{1, "byte 0x10 used with manual bytecblocks. Use bytec."}) + exp(1, "byte 0x10 used with manual bytecblocks. Use bytec.")) testProg(t, "bytecblock 0x10 0x20; txn NumAppArgs; bz skip; bytecblock 0x03 0x04 0x05; skip: byte 0x03;", backBranchEnabledVersion-2, - Expect{1, "byte 0x03 used with manual bytecblocks. Use bytec."}) + exp(1, "byte 0x03 used with manual bytecblocks. Use bytec.")) } func TestAssembleOptimizedConstants(t *testing.T) { @@ -1288,13 +1328,25 @@ int ClearState } } -func TestFieldsFromLine(t *testing.T) { +func stringsOf(tokens []token) []string { + if tokens == nil { + return nil + } + out := make([]string, len(tokens)) + for i, t := range tokens { + out[i] = t.str + } + return out +} + +func TestTokensFromLine(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() check := func(line string, tokens ...string) { t.Helper() - assert.Equal(t, tokensFromLine(line), tokens) + fromLine := stringsOf(tokensFromLine(line, 0)) + assert.Equal(t, fromLine, tokens) } check("op arg", "op", "arg") @@ -1348,38 +1400,29 @@ func TestNextStatement(t *testing.T) { // this test ensures nextStatement splits tokens on semicolons properly // macro testing should be handled in TestMacros ops := newOpStream(AssemblerMaxVersion) - check := func(tokens []string, left []string, right []string) { + check := func(line string, left []string, right []string) { t.Helper() + tokens := tokensFromLine(line, 0) current, next := nextStatement(&ops, tokens) - assert.Equal(t, left, current) - assert.Equal(t, right, next) + assert.Equal(t, left, stringsOf(current)) + assert.Equal(t, right, stringsOf(next)) } - check([]string{"hey,", "how's", ";", ";", "it", "going", ";"}, + check(`hey, how's ; ; it going ;`, []string{"hey,", "how's"}, []string{";", "it", "going", ";"}, ) - check([]string{";"}, - []string{}, - []string{}, - ) + check(";", []string{}, []string{}) - check([]string{";", "it", "going"}, - []string{}, - []string{"it", "going"}, - ) + check(`; it going`, []string{}, []string{"it", "going"}) - check([]string{"hey,", "how's"}, - []string{"hey,", "how's"}, - nil, - ) + check(`hey, how's`, []string{"hey,", "how's"}, nil) - check([]string{`"hey in quotes;"`, "getting", `";"`, ";", "tricky"}, + check(`"hey in quotes;" getting ";" ; tricky`, []string{`"hey in quotes;"`, "getting", `";"`}, []string{"tricky"}, ) - } func TestAssembleRejectNegJump(t *testing.T) { @@ -1392,7 +1435,7 @@ bnz wat int 2` for v := uint64(1); v < backBranchEnabledVersion; v++ { t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) { - testProg(t, source, v, Expect{3, "label \"wat\" is a back reference..."}) + testProg(t, source, v, exp(3, "label \"wat\" is a back reference...", 4)) }) } for v := uint64(backBranchEnabledVersion); v <= AssemblerMaxVersion; v++ { @@ -1446,7 +1489,23 @@ bnz nowhere int 2` for v := uint64(1); v <= AssemblerMaxVersion; v++ { t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) { - testProg(t, source, v, Expect{2, "reference to undefined label \"nowhere\""}) + testProg(t, source, v, exp(2, "reference to undefined label \"nowhere\"", 4)) + }) + } +} + +func TestAssembleRejectDupLabel(t *testing.T) { + partitiontest.PartitionTest(t) + t.Parallel() + + source := ` + XXX: int 1; pop; + XXX: int 1; pop; // different indent to prove the returned column is from the right label + int 1 +` + for v := uint64(1); v <= AssemblerMaxVersion; v++ { + t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) { + testProg(t, source, v, exp(3, "duplicate label \"XXX\"", 2)) }) } } @@ -1479,8 +1538,8 @@ int 2` for v := uint64(1); v <= AssemblerMaxVersion; v++ { t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) { testProg(t, source, v, - Expect{2, "reference to undefined label \"nowhere\""}, - Expect{4, "txn unknown field: \"XYZ\""}) + exp(2, "reference to undefined label \"nowhere\"", 4), + exp(4, "txn unknown field: \"XYZ\"", 4)) }) } } @@ -1681,20 +1740,48 @@ func TestConstantArgs(t *testing.T) { t.Parallel() for v := uint64(1); v <= AssemblerMaxVersion; v++ { - testProg(t, "int", v, Expect{1, "int needs one immediate argument, was given 0"}) - testProg(t, "int 1 2", v, Expect{1, "int needs one immediate argument, was given 2"}) - testProg(t, "intc", v, Expect{1, "intc needs one immediate argument, was given 0"}) - testProg(t, "intc hi bye", v, Expect{1, "intc needs one immediate argument, was given 2"}) - testProg(t, "byte", v, Expect{1, "byte needs byte literal argument"}) - testProg(t, "bytec", v, Expect{1, "bytec needs one immediate argument, was given 0"}) - testProg(t, "bytec 1 x", v, Expect{1, "bytec needs one immediate argument, was given 2"}) - testProg(t, "addr", v, Expect{1, "addr needs one immediate argument, was given 0"}) - testProg(t, "addr x y", v, Expect{1, "addr needs one immediate argument, was given 2"}) + testProg(t, "int", v, exp(1, "int expects 1 immediate argument", 3)) + testProg(t, "int pay", v) + testProg(t, "int pya", v, exp(1, "unable to parse \"pya\" as integer", 4)) + testProg(t, "int 1 2", v, exp(1, "int expects 1 immediate argument", 6)) + testProg(t, "intc", v, exp(1, "intc expects 1 immediate argument", 4)) + testProg(t, "intc pay", v, exp(1, "unable to parse constant \"pay\" as integer", 5)) // don't accept "pay" constant + testProg(t, "intc hi bye", v, exp(1, "intc expects 1 immediate argument", 8)) + testProg(t, "byte", v, exp(1, "byte needs byte literal argument", 4)) + testProg(t, "byte b32", v, exp(1, "byte b32 needs byte literal argument")) + testProg(t, "byte 0xaa 0xbb", v, exp(1, "byte with extraneous argument", 10)) + testProg(t, "byte b32 MFRGGZDFMY MFRGGZDFMY", v, exp(1, "byte with extraneous argument", 20)) + testProg(t, "bytec", v, exp(1, "bytec expects 1 immediate argument")) + testProg(t, "bytec 1 x", v, exp(1, "bytec expects 1 immediate argument")) + testProg(t, "bytec pay", v, exp(1, "unable to parse constant \"pay\" as integer", 6)) // don't accept "pay" constant + testProg(t, "addr", v, exp(1, "addr expects 1 immediate argument", 4)) + testProg(t, "addr x y", v, exp(1, "addr expects 1 immediate argument", 9)) + testProg(t, "addr x", v, exp(1, "failed to decode address x ...", 5)) + testProg(t, "method", v, exp(1, "method expects 1 immediate argument", 6)) + testProg(t, "method xx yy", v, exp(1, "method expects 1 immediate argument", 10)) } for v := uint64(3); v <= AssemblerMaxVersion; v++ { - testProg(t, "pushint", v, Expect{1, "pushint needs one immediate argument, was given 0"}) - testProg(t, "pushint 3 4", v, Expect{1, "pushint needs one immediate argument, was given 2"}) - testProg(t, "pushbytes", v, Expect{1, "pushbytes needs byte literal argument"}) + testProg(t, "pushint", v, exp(1, "pushint expects 1 immediate argument")) + testProg(t, "pushint 3 4", v, exp(1, "pushint expects 1 immediate argument")) + testProg(t, "pushint x", v, exp(1, "unable to parse \"x\" as integer", 8)) + testProg(t, "pushbytes", v, exp(1, "pushbytes needs byte literal argument")) + testProg(t, "pushbytes b32", v, exp(1, "pushbytes b32 needs byte literal argument")) + testProg(t, "pushbytes b32(MFRGGZDFMY", v, exp(1, "pushbytes argument b32(MFRGGZDFMY lacks closing parenthesis")) + testProg(t, "pushbytes b32(MFRGGZDFMY)X", v, exp(1, "pushbytes argument b32(MFRGGZDFMY)X must end at first closing parenthesis")) + } + + for v := uint64(8); v <= AssemblerMaxVersion; v++ { + testProg(t, "pushints", v) + testProg(t, "pushints 200", v) + testProg(t, "pushints 3 4", v) + + testProg(t, "pushbytess", v) + testProg(t, "pushbytess 0xff", v) + testProg(t, "pushbytess 0xaa 0xbb", v) + + testProg(t, "pushbytess b32(MFRGGZDFMY) b32(MFRGGZDFMY)", v) + testProg(t, "pushbytess b32 MFRGGZDFMY b32 MFRGGZDFMY", v) + testProg(t, "pushbytess b32(MFRGGZDFMY b32(MFRGGZDFMY)", v, exp(1, "pushbytess argument b32(MFRGGZDFMY lacks closing parenthesis")) } } @@ -1703,17 +1790,17 @@ func TestBranchArgs(t *testing.T) { t.Parallel() for v := uint64(2); v <= AssemblerMaxVersion; v++ { - testProg(t, "b", v, Expect{1, "b needs a single label argument"}) - testProg(t, "b lab1 lab2", v, Expect{1, "b needs a single label argument"}) - testProg(t, "int 1; bz", v, Expect{1, "bz needs a single label argument"}) - testProg(t, "int 1; bz a b", v, Expect{1, "bz needs a single label argument"}) - testProg(t, "int 1; bnz", v, Expect{1, "bnz needs a single label argument"}) - testProg(t, "int 1; bnz c d", v, Expect{1, "bnz needs a single label argument"}) + testProg(t, "b", v, exp(1, "b expects 1 immediate argument")) + testProg(t, "b lab1 lab2", v, exp(1, "b expects 1 immediate argument")) + testProg(t, "int 1; bz", v, exp(1, "bz expects 1 immediate argument")) + testProg(t, "int 1; bz a b", v, exp(1, "bz expects 1 immediate argument")) + testProg(t, "int 1; bnz", v, exp(1, "bnz expects 1 immediate argument")) + testProg(t, "int 1; bnz c d", v, exp(1, "bnz expects 1 immediate argument")) } for v := uint64(4); v <= AssemblerMaxVersion; v++ { - testProg(t, "callsub", v, Expect{1, "callsub needs a single label argument"}) - testProg(t, "callsub one two", v, Expect{1, "callsub needs a single label argument"}) + testProg(t, "callsub", v, exp(1, "callsub expects 1 immediate argument")) + testProg(t, "callsub one two", v, exp(1, "callsub expects 1 immediate argument")) } } @@ -1836,7 +1923,7 @@ balance int 1 ==` for v := uint64(2); v < directRefEnabledVersion; v++ { - testProg(t, source, v, Expect{2, "balance arg 0 wanted type uint64 got [1]byte"}) + testProg(t, source, v, exp(2, "balance arg 0 wanted type uint64 got [1]byte")) } for v := uint64(directRefEnabledVersion); v <= AssemblerMaxVersion; v++ { testProg(t, source, v) @@ -1852,7 +1939,7 @@ min_balance int 1 ==` for v := uint64(3); v < directRefEnabledVersion; v++ { - testProg(t, source, v, Expect{2, "min_balance arg 0 wanted type uint64 got [1]byte"}) + testProg(t, source, v, exp(2, "min_balance arg 0 wanted type uint64 got [1]byte")) } for v := uint64(directRefEnabledVersion); v <= AssemblerMaxVersion; v++ { testProg(t, source, v) @@ -1866,25 +1953,25 @@ func TestAssembleAsset(t *testing.T) { for v := uint64(2); v <= AssemblerMaxVersion; v++ { t.Run(strconv.Itoa(int(v)), func(t *testing.T) { testProg(t, "asset_holding_get ABC 1", v, - Expect{1, "asset_holding_get ABC 1 expects 2 stack arguments..."}) + exp(1, "asset_holding_get ABC 1 expects 2 stack arguments...")) testProg(t, "int 1; asset_holding_get ABC 1", v, - Expect{1, "asset_holding_get ABC 1 expects 2 stack arguments..."}) + exp(1, "asset_holding_get ABC 1 expects 2 stack arguments...")) testProg(t, "int 1; int 1; asset_holding_get ABC 1", v, - Expect{1, "asset_holding_get expects 1 immediate argument"}) + exp(1, "asset_holding_get expects 1 immediate argument")) testProg(t, "int 1; int 1; asset_holding_get ABC", v, - Expect{1, "asset_holding_get unknown field: \"ABC\""}) + exp(1, "asset_holding_get unknown field: \"ABC\"")) testProg(t, "byte 0x1234; asset_params_get ABC 1", v, - Expect{1, "asset_params_get ABC 1 arg 0 wanted type uint64..."}) + exp(1, "asset_params_get ABC 1 arg 0 wanted type uint64...")) // Test that AssetUnitName is known to return bytes testProg(t, "int 1; asset_params_get AssetUnitName; pop; int 1; +", v, - Expect{1, "+ arg 0 wanted type uint64..."}) + exp(1, "+ arg 0 wanted type uint64...")) // Test that AssetTotal is known to return uint64 testProg(t, "int 1; asset_params_get AssetTotal; pop; byte 0x12; concat", v, - Expect{1, "concat arg 0 wanted type []byte..."}) + exp(1, "concat arg 0 wanted type []byte...")) testLine(t, "asset_params_get ABC 1", v, "asset_params_get expects 1 immediate argument") testLine(t, "asset_params_get ABC", v, "asset_params_get unknown field: \"ABC\"") @@ -2250,7 +2337,7 @@ func TestStringLiteralParsing(t *testing.T) { s = `"test\a"` result, err = parseStringLiteral(s) - require.EqualError(t, err, "invalid escape seq \\a") + require.EqualError(t, err, "invalid escape sequence \\a") require.Nil(t, result) s = `"test\x10\x1"` @@ -2270,15 +2357,18 @@ func TestPragmas(t *testing.T) { } testProg(t, `#pragma version 100`, assemblerNoVersion, - Expect{1, "unsupported version: 100"}) + exp(1, "unsupported version: 100")) - testProg(t, `int 1`, 99, Expect{0, "Can not assemble version 99"}) + testProg(t, `int 1`, 99, exp(0, "Can not assemble version 99")) // Allow this on the off chance someone needs to reassemble an old logigsig testProg(t, `#pragma version 0`, assemblerNoVersion) testProg(t, `#pragma version a`, assemblerNoVersion, - Expect{1, `bad #pragma version: "a"`}) + exp(1, `bad #pragma version: "a"`)) + + testProg(t, `#pramga version 3`, assemblerNoVersion, + exp(1, "unknown directive: pramga")) // will default to 1 ops := testProg(t, "int 3", assemblerNoVersion) @@ -2292,24 +2382,24 @@ func TestPragmas(t *testing.T) { require.Equal(t, uint64(2), ops.Version) // changing version is not allowed - testProg(t, "#pragma version 1", 2, Expect{1, "version mismatch..."}) - testProg(t, "#pragma version 2", 1, Expect{1, "version mismatch..."}) + testProg(t, "#pragma version 1", 2, exp(1, "version mismatch...")) + testProg(t, "#pragma version 2", 1, exp(1, "version mismatch...")) testProg(t, "#pragma version 2\n#pragma version 1", assemblerNoVersion, - Expect{2, "version mismatch..."}) + exp(2, "version mismatch...")) // repetitive, but fine ops = testProg(t, "#pragma version 2\n#pragma version 2", assemblerNoVersion) require.Equal(t, uint64(2), ops.Version) testProg(t, "\nint 1\n#pragma version 2", assemblerNoVersion, - Expect{3, "#pragma version is only allowed before instructions"}) + exp(3, "#pragma version is only allowed before instructions")) testProg(t, "#pragma run-mode 2", assemblerNoVersion, - Expect{1, `unsupported pragma directive: "run-mode"`}) + exp(1, `unsupported pragma directive: "run-mode"`)) testProg(t, "#pragma versions", assemblerNoVersion, - Expect{1, `unsupported pragma directive: "versions"`}) + exp(1, `unsupported pragma directive: "versions"`)) ops = testProg(t, "#pragma version 1", assemblerNoVersion) require.Equal(t, uint64(1), ops.Version) @@ -2317,33 +2407,33 @@ func TestPragmas(t *testing.T) { ops = testProg(t, "\n#pragma version 1", assemblerNoVersion) require.Equal(t, uint64(1), ops.Version) - testProg(t, "#pragma", assemblerNoVersion, Expect{1, "empty pragma"}) + testProg(t, "#pragma", assemblerNoVersion, exp(1, "empty pragma")) testProg(t, "#pragma version", assemblerNoVersion, - Expect{1, "no version value"}) + exp(1, "no version value")) ops = testProg(t, " #pragma version 5 ", assemblerNoVersion) require.Equal(t, uint64(5), ops.Version) testProg(t, "#pragma version 5 blah", assemblerNoVersion, - Expect{1, "unexpected extra tokens: blah"}) + exp(1, "unexpected extra tokens: blah")) testProg(t, "#pragma typetrack", assemblerNoVersion, - Expect{1, "no typetrack value"}) + exp(1, "no typetrack value")) testProg(t, "#pragma typetrack blah", assemblerNoVersion, - Expect{1, `bad #pragma typetrack: "blah"`}) + exp(1, `bad #pragma typetrack: "blah"`)) testProg(t, "#pragma typetrack false blah", assemblerNoVersion, - Expect{1, "unexpected extra tokens: blah"}) + exp(1, "unexpected extra tokens: blah")) // Currently pragmas don't treat semicolons as newlines. It would probably // be nice to fix this. testProg(t, "#pragma version 5; int 1", assemblerNoVersion, - Expect{1, "unexpected extra tokens: ; int 1"}) + exp(1, "unexpected extra tokens: ; int 1")) testProg(t, "#pragma typetrack false; int 1", assemblerNoVersion, - Expect{1, "unexpected extra tokens: ; int 1"}) + exp(1, "unexpected extra tokens: ; int 1")) } func TestAssemblePragmaVersion(t *testing.T) { @@ -2357,8 +2447,8 @@ int 1 ops1 := testProg(t, "int 1", 1) require.Equal(t, ops1.Program, ops.Program) - testProg(t, text, 0, Expect{1, "version mismatch..."}) - testProg(t, text, 2, Expect{1, "version mismatch..."}) + testProg(t, text, 0, exp(1, "version mismatch...")) + testProg(t, text, 2, exp(1, "version mismatch...")) testProg(t, text, assemblerNoVersion) ops = testProg(t, text, assemblerNoVersion) @@ -2371,8 +2461,8 @@ int 1 ops2 := testProg(t, "int 1", 2) require.Equal(t, ops2.Program, ops.Program) - testProg(t, text, 0, Expect{1, "version mismatch..."}) - testProg(t, text, 1, Expect{1, "version mismatch..."}) + testProg(t, text, 0, exp(1, "version mismatch...")) + testProg(t, text, 1, exp(1, "version mismatch...")) ops = testProg(t, text, assemblerNoVersion) require.Equal(t, ops2.Program, ops.Program) @@ -2389,7 +2479,7 @@ len require.Equal(t, ops2.Program, ops.Program) testProg(t, "#pragma unk", assemblerNoVersion, - Expect{1, `unsupported pragma directive: "unk"`}) + exp(1, `unsupported pragma directive: "unk"`)) } func TestAssembleConstants(t *testing.T) { @@ -2463,7 +2553,7 @@ func TestMethodWarning(t *testing.T) { } require.Len(t, ops.Warnings, 1) - require.Contains(t, ops.Warnings[0].Error(), "Invalid ARC-4 ABI method signature for method op") + require.ErrorContains(t, ops.Warnings[0], "invalid ARC-4 ABI method signature for method op") } } } @@ -2503,29 +2593,29 @@ func TestSwapTypeCheck(t *testing.T) { t.Parallel() /* reconfirm that we detect this type error */ - testProg(t, "int 1; byte 0x1234; +", AssemblerMaxVersion, Expect{1, "+ arg 1..."}) + testProg(t, "int 1; byte 0x1234; +", AssemblerMaxVersion, exp(1, "+ arg 1...")) /* despite swap, we track types */ - testProg(t, "int 1; byte 0x1234; swap; +", AssemblerMaxVersion, Expect{1, "+ arg 0..."}) - testProg(t, "byte 0x1234; int 1; swap; +", AssemblerMaxVersion, Expect{1, "+ arg 1..."}) + testProg(t, "int 1; byte 0x1234; swap; +", AssemblerMaxVersion, exp(1, "+ arg 0...")) + testProg(t, "byte 0x1234; int 1; swap; +", AssemblerMaxVersion, exp(1, "+ arg 1...")) } func TestDigAsm(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - testProg(t, "int 1; dig; +", AssemblerMaxVersion, Expect{1, "dig expects 1 immediate..."}) - testProg(t, "int 1; dig junk; +", AssemblerMaxVersion, Expect{1, "dig unable to parse..."}) + testProg(t, "int 1; dig; +", AssemblerMaxVersion, exp(1, "dig expects 1 immediate...")) + testProg(t, "int 1; dig junk; +", AssemblerMaxVersion, exp(1, "dig unable to parse...")) testProg(t, "int 1; byte 0x1234; int 2; dig 2; +", AssemblerMaxVersion) testProg(t, "byte 0x32; byte 0x1234; int 2; dig 2; +", AssemblerMaxVersion, - Expect{1, "+ arg 1..."}) + exp(1, "+ arg 1...")) testProg(t, "byte 0x32; byte 0x1234; int 2; dig 3; +", AssemblerMaxVersion, - Expect{1, "dig 3 expects 4..."}) + exp(1, "dig 3 expects 4...")) testProg(t, "int 1; byte 0x1234; int 2; dig 12; +", AssemblerMaxVersion, - Expect{1, "dig 12 expects 13..."}) + exp(1, "dig 12 expects 13...")) // Confirm that digging something out does not ruin our knowledge about the types in the middle testProg(t, "int 1; byte 0x1234; byte 0x1234; dig 2; dig 3; +; pop; +", AssemblerMaxVersion, - Expect{1, "+ arg 1..."}) + exp(1, "+ arg 1...")) testProg(t, "int 3; pushbytes \"123456\"; int 1; dig 2; substring3", AssemblerMaxVersion) } @@ -2533,62 +2623,62 @@ func TestDigAsm(t *testing.T) { func TestBuryAsm(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - testProg(t, "int 1; bury; +", AssemblerMaxVersion, Expect{1, "bury expects 1 immediate..."}) - testProg(t, "int 1; bury junk; +", AssemblerMaxVersion, Expect{1, "bury unable to parse..."}) + testProg(t, "int 1; bury; +", AssemblerMaxVersion, exp(1, "bury expects 1 immediate...")) + testProg(t, "int 1; bury junk; +", AssemblerMaxVersion, exp(1, "bury unable to parse...")) testProg(t, "int 1; byte 0x1234; int 2; bury 1; +", AssemblerMaxVersion) // the 2 replaces the byte string testProg(t, "int 2; int 2; byte 0x1234; bury 1; +", AssemblerMaxVersion, - Expect{1, "+ arg 1..."}) + exp(1, "+ arg 1...")) testProg(t, "byte 0x32; byte 0x1234; int 2; bury 3; +", AssemblerMaxVersion, - Expect{1, "bury 3 expects 4..."}) + exp(1, "bury 3 expects 4...")) testProg(t, "int 1; byte 0x1234; int 2; bury 12; +", AssemblerMaxVersion, - Expect{1, "bury 12 expects 13..."}) + exp(1, "bury 12 expects 13...")) // We do not lose track of the ints between ToS and bury index testProg(t, "int 0; int 1; int 2; int 4; bury 3; concat", AssemblerMaxVersion, - Expect{1, "concat arg 1 wanted type []byte..."}) + exp(1, "concat arg 1 wanted type []byte...")) // Even when we are burying into unknown (seems repetitive, but is an easy bug) testProg(t, "int 0; int 0; b LABEL; LABEL: int 1; int 2; int 4; bury 4; concat", AssemblerMaxVersion, - Expect{1, "concat arg 1 wanted type []byte..."}) + exp(1, "concat arg 1 wanted type []byte...")) } func TestEqualsTypeCheck(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - testProg(t, "int 1; byte 0x1234; ==", AssemblerMaxVersion, Expect{1, "== arg 0..."}) - testProg(t, "int 1; byte 0x1234; !=", AssemblerMaxVersion, Expect{1, "!= arg 0..."}) - testProg(t, "byte 0x1234; int 1; ==", AssemblerMaxVersion, Expect{1, "== arg 0..."}) - testProg(t, "byte 0x1234; int 1; !=", AssemblerMaxVersion, Expect{1, "!= arg 0..."}) + testProg(t, "int 1; byte 0x1234; ==", AssemblerMaxVersion, exp(1, "== arg 0...")) + testProg(t, "int 1; byte 0x1234; !=", AssemblerMaxVersion, exp(1, "!= arg 0...")) + testProg(t, "byte 0x1234; int 1; ==", AssemblerMaxVersion, exp(1, "== arg 0...")) + testProg(t, "byte 0x1234; int 1; !=", AssemblerMaxVersion, exp(1, "!= arg 0...")) } func TestDupTypeCheck(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - testProg(t, "byte 0x1234; dup; int 1; +", AssemblerMaxVersion, Expect{1, "+ arg 0..."}) + testProg(t, "byte 0x1234; dup; int 1; +", AssemblerMaxVersion, exp(1, "+ arg 0...")) testProg(t, "byte 0x1234; int 1; dup; +", AssemblerMaxVersion) - testProg(t, "byte 0x1234; int 1; dup2; +", AssemblerMaxVersion, Expect{1, "+ arg 0..."}) - testProg(t, "int 1; byte 0x1234; dup2; +", AssemblerMaxVersion, Expect{1, "+ arg 1..."}) + testProg(t, "byte 0x1234; int 1; dup2; +", AssemblerMaxVersion, exp(1, "+ arg 0...")) + testProg(t, "int 1; byte 0x1234; dup2; +", AssemblerMaxVersion, exp(1, "+ arg 1...")) - testProg(t, "byte 0x1234; int 1; dup; dig 1; len", AssemblerMaxVersion, Expect{1, "len arg 0..."}) - testProg(t, "int 1; byte 0x1234; dup; dig 1; !", AssemblerMaxVersion, Expect{1, "! arg 0..."}) + testProg(t, "byte 0x1234; int 1; dup; dig 1; len", AssemblerMaxVersion, exp(1, "len arg 0...")) + testProg(t, "int 1; byte 0x1234; dup; dig 1; !", AssemblerMaxVersion, exp(1, "! arg 0...")) - testProg(t, "byte 0x1234; int 1; dup2; dig 2; len", AssemblerMaxVersion, Expect{1, "len arg 0..."}) - testProg(t, "int 1; byte 0x1234; dup2; dig 2; !", AssemblerMaxVersion, Expect{1, "! arg 0..."}) + testProg(t, "byte 0x1234; int 1; dup2; dig 2; len", AssemblerMaxVersion, exp(1, "len arg 0...")) + testProg(t, "int 1; byte 0x1234; dup2; dig 2; !", AssemblerMaxVersion, exp(1, "! arg 0...")) } func TestSelectTypeCheck(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - testProg(t, "int 1; int 2; int 3; select; len", AssemblerMaxVersion, Expect{1, "len arg 0..."}) - testProg(t, "byte 0x1234; byte 0x5678; int 3; select; !", AssemblerMaxVersion, Expect{1, "! arg 0..."}) + testProg(t, "int 1; int 2; int 3; select; len", AssemblerMaxVersion, exp(1, "len arg 0...")) + testProg(t, "byte 0x1234; byte 0x5678; int 3; select; !", AssemblerMaxVersion, exp(1, "! arg 0...")) } func TestSetBitTypeCheck(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - testProg(t, "int 1; int 2; int 3; setbit; len", AssemblerMaxVersion, Expect{1, "len arg 0..."}) - testProg(t, "byte 0x1234; int 2; int 3; setbit; !", AssemblerMaxVersion, Expect{1, "! arg 0..."}) + testProg(t, "int 1; int 2; int 3; setbit; len", AssemblerMaxVersion, exp(1, "len arg 0...")) + testProg(t, "byte 0x1234; int 2; int 3; setbit; !", AssemblerMaxVersion, exp(1, "! arg 0...")) } func TestScratchTypeCheck(t *testing.T) { @@ -2597,15 +2687,15 @@ func TestScratchTypeCheck(t *testing.T) { // All scratch slots should start as uint64 testProg(t, "load 0; int 1; +", AssemblerMaxVersion) // Check load and store accurately using the scratch space - testProg(t, "byte 0x01; store 0; load 0; int 1; +", AssemblerMaxVersion, Expect{1, "+ arg 0..."}) + testProg(t, "byte 0x01; store 0; load 0; int 1; +", AssemblerMaxVersion, exp(1, "+ arg 0...")) // Loads should know the type it's loading if all the slots are the same type - testProg(t, "int 0; loads; btoi", AssemblerMaxVersion, Expect{1, "btoi arg 0..."}) + testProg(t, "int 0; loads; btoi", AssemblerMaxVersion, exp(1, "btoi arg 0...")) // Loads only knows the type when slot is a const - testProg(t, "byte 0x01; store 0; int 1; loads; btoi", AssemblerMaxVersion, Expect{1, "btoi arg 0..."}) + testProg(t, "byte 0x01; store 0; int 1; loads; btoi", AssemblerMaxVersion, exp(1, "btoi arg 0...")) // Loads doesnt know the type if its the result of some other expression where we lose information testProg(t, "byte 0x01; store 0; load 0; btoi; loads; btoi", AssemblerMaxVersion) // Stores should only set slots to StackAny if they are not the same type as what is being stored - testProg(t, "byte 0x01; store 0; int 3; byte 0x01; stores; load 0; int 1; +", AssemblerMaxVersion, Expect{1, "+ arg 0..."}) + testProg(t, "byte 0x01; store 0; int 3; byte 0x01; stores; load 0; int 1; +", AssemblerMaxVersion, exp(1, "+ arg 0...")) // ScratchSpace should reset after hitting label in deadcode testProg(t, "byte 0x01; store 0; b label1; label1:; load 0; int 1; +", AssemblerMaxVersion) // But it should reset to StackAny not uint64 @@ -2613,7 +2703,7 @@ func TestScratchTypeCheck(t *testing.T) { // Callsubs should also reset the scratch space testProg(t, "callsub A; load 0; btoi; return; A: byte 0x01; store 0; retsub", AssemblerMaxVersion) // But the scratchspace should still be tracked after the callsub - testProg(t, "callsub A; int 1; store 0; load 0; btoi; return; A: retsub", AssemblerMaxVersion, Expect{1, "btoi arg 0..."}) + testProg(t, "callsub A; int 1; store 0; load 0; btoi; return; A: retsub", AssemblerMaxVersion, exp(1, "btoi arg 0...")) } @@ -2652,7 +2742,7 @@ func TestScratchBounds(t *testing.T) { require.Equal(t, osv.AVMType, avmAny) require.ElementsMatch(t, osv.Bound, static(0)) - testProg(t, "byte 0xff; store 1; load 1; return", AssemblerMaxVersion, Expect{1, "return arg 0 wanted type uint64 ..."}) + testProg(t, "byte 0xff; store 1; load 1; return", AssemblerMaxVersion, exp(1, "return arg 0 wanted type uint64 ...")) } // TestProtoAsm confirms that the assembler will yell at you if you are @@ -2661,7 +2751,7 @@ func TestScratchBounds(t *testing.T) { func TestProtoAsm(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - testProg(t, "proto 0 0", AssemblerMaxVersion, Expect{1, "proto must be unreachable..."}) + testProg(t, "proto 0 0", AssemblerMaxVersion, exp(1, "proto must be unreachable...")) testProg(t, notrack("proto 0 0"), AssemblerMaxVersion) testProg(t, "b a; int 1; a: proto 0 0", AssemblerMaxVersion) // we could flag a `b` to `proto` @@ -2685,9 +2775,9 @@ func TestCoverAsm(t *testing.T) { t.Parallel() testProg(t, `int 4; byte "john"; int 5; cover 2; pop; +`, AssemblerMaxVersion) testProg(t, `int 4; byte "ayush"; int 5; cover 1; pop; +`, AssemblerMaxVersion) - testProg(t, `int 4; byte "john"; int 5; cover 2; +`, AssemblerMaxVersion, Expect{1, "+ arg 1..."}) + testProg(t, `int 4; byte "john"; int 5; cover 2; +`, AssemblerMaxVersion, exp(1, "+ arg 1...")) - testProg(t, `int 4; cover junk`, AssemblerMaxVersion, Expect{1, "cover unable to parse n ..."}) + testProg(t, `int 4; cover junk`, AssemblerMaxVersion, exp(1, "cover unable to parse n ...")) testProg(t, notrack(`int 4; int 5; cover 0`), AssemblerMaxVersion) } @@ -2697,45 +2787,45 @@ func TestUncoverAsm(t *testing.T) { testProg(t, `int 4; byte "john"; int 5; uncover 2; +`, AssemblerMaxVersion) testProg(t, `int 4; byte "ayush"; int 5; uncover 1; pop; +`, AssemblerMaxVersion) testProg(t, `int 1; byte "jj"; byte "ayush"; byte "john"; int 5; uncover 4; +`, AssemblerMaxVersion) - testProg(t, `int 4; byte "ayush"; int 5; uncover 1; +`, AssemblerMaxVersion, Expect{1, "+ arg 1..."}) + testProg(t, `int 4; byte "ayush"; int 5; uncover 1; +`, AssemblerMaxVersion, exp(1, "+ arg 1...")) } func TestTxTypes(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - testProg(t, "itxn_begin; itxn_field Sender", 5, Expect{1, "itxn_field Sender expects 1 stack argument..."}) - testProg(t, "itxn_begin; int 1; itxn_field Sender", 5, Expect{1, "...wanted type address got 1"}) - testProg(t, "itxn_begin; byte 0x56127823; itxn_field Sender", 5, Expect{1, "...wanted type address got [4]byte"}) + testProg(t, "itxn_begin; itxn_field Sender", 5, exp(1, "itxn_field Sender expects 1 stack argument...")) + testProg(t, "itxn_begin; int 1; itxn_field Sender", 5, exp(1, "...wanted type address got 1")) + testProg(t, "itxn_begin; byte 0x56127823; itxn_field Sender", 5, exp(1, "...wanted type address got [4]byte")) testProg(t, "itxn_begin; global ZeroAddress; itxn_field Sender", 5) - testProg(t, "itxn_begin; itxn_field Amount", 5, Expect{1, "itxn_field Amount expects 1 stack argument..."}) - testProg(t, "itxn_begin; byte 0x87123376; itxn_field Amount", 5, Expect{1, "...wanted type uint64 got [4]byte"}) + testProg(t, "itxn_begin; itxn_field Amount", 5, exp(1, "itxn_field Amount expects 1 stack argument...")) + testProg(t, "itxn_begin; byte 0x87123376; itxn_field Amount", 5, exp(1, "...wanted type uint64 got [4]byte")) testProg(t, "itxn_begin; int 1; itxn_field Amount", 5) } func TestBadInnerFields(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - testProg(t, "itxn_begin; int 1000; itxn_field FirstValid", 5, Expect{1, "...is not allowed."}) - testProg(t, "itxn_begin; int 1000; itxn_field FirstValidTime", 5, Expect{1, "...is not allowed."}) - testProg(t, "itxn_begin; int 1000; itxn_field LastValid", 5, Expect{1, "...is not allowed."}) - testProg(t, "itxn_begin; int 32; bzero; itxn_field Lease", 5, Expect{1, "...is not allowed."}) - testProg(t, "itxn_begin; byte 0x7263; itxn_field Note", 5, Expect{1, "...Note field was introduced in v6..."}) - testProg(t, "itxn_begin; global ZeroAddress; itxn_field VotePK", 5, Expect{1, "...VotePK field was introduced in v6..."}) - testProg(t, "itxn_begin; int 32; bzero; itxn_field TxID", 5, Expect{1, "...is not allowed."}) + testProg(t, "itxn_begin; int 1000; itxn_field FirstValid", 5, exp(1, "...is not allowed.")) + testProg(t, "itxn_begin; int 1000; itxn_field FirstValidTime", 5, exp(1, "...is not allowed.")) + testProg(t, "itxn_begin; int 1000; itxn_field LastValid", 5, exp(1, "...is not allowed.")) + testProg(t, "itxn_begin; int 32; bzero; itxn_field Lease", 5, exp(1, "...is not allowed.")) + testProg(t, "itxn_begin; byte 0x7263; itxn_field Note", 5, exp(1, "...Note field was introduced in v6...")) + testProg(t, "itxn_begin; global ZeroAddress; itxn_field VotePK", 5, exp(1, "...VotePK field was introduced in v6...")) + testProg(t, "itxn_begin; int 32; bzero; itxn_field TxID", 5, exp(1, "...is not allowed.")) - testProg(t, "itxn_begin; int 1000; itxn_field FirstValid", 6, Expect{1, "...is not allowed."}) - testProg(t, "itxn_begin; int 1000; itxn_field LastValid", 6, Expect{1, "...is not allowed."}) - testProg(t, "itxn_begin; int 32; bzero; itxn_field Lease", 6, Expect{1, "...is not allowed."}) + testProg(t, "itxn_begin; int 1000; itxn_field FirstValid", 6, exp(1, "...is not allowed.")) + testProg(t, "itxn_begin; int 1000; itxn_field LastValid", 6, exp(1, "...is not allowed.")) + testProg(t, "itxn_begin; int 32; bzero; itxn_field Lease", 6, exp(1, "...is not allowed.")) testProg(t, "itxn_begin; byte 0x7263; itxn_field Note", 6) testProg(t, "itxn_begin; global ZeroAddress; itxn_field VotePK", 6) - testProg(t, "itxn_begin; int 32; bzero; itxn_field TxID", 6, Expect{1, "...is not allowed."}) + testProg(t, "itxn_begin; int 32; bzero; itxn_field TxID", 6, exp(1, "...is not allowed.")) } func TestTypeTracking(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - testProg(t, "+", LogicVersion, Expect{1, "+ expects 2 stack arguments..."}) + testProg(t, "+", LogicVersion, exp(1, "+ expects 2 stack arguments...")) // hitting a label in deadcode starts analyzing again, with unknown stack testProg(t, "b end; label: +; end: b label", LogicVersion) @@ -2745,7 +2835,7 @@ func TestTypeTracking(t *testing.T) { // but we do want to ensure we're not just treating the code after callsub as dead testProg(t, "callsub A; int 1; concat; return; A: int 1; int 2; retsub", LogicVersion, - Expect{1, "concat arg 1 wanted..."}) + exp(1, "concat arg 1 wanted...")) // retsub deadens code, like any unconditional branch testProg(t, "callsub A; +; return; A: int 1; int 2; retsub; concat", LogicVersion) @@ -2761,7 +2851,7 @@ label: + confusion: b label -`, LogicVersion, Expect{7, "+ arg 0 wanted type uint64..."}) +`, LogicVersion, exp(7, "+ arg 0 wanted type uint64...")) // Unless that same error is in dead code. testProg(t, ` @@ -2815,7 +2905,7 @@ done: concat #pragma typetrack true concat -`, LogicVersion, Expect{5, "concat arg 1 wanted type []byte..."}) +`, LogicVersion, exp(5, "concat arg 1 wanted type []byte...")) } func TestMergeProtos(t *testing.T) { @@ -2849,9 +2939,9 @@ func TestGetSpec(t *testing.T) { ops.versionedPseudoOps["dummyPseudo"] = make(map[int]OpSpec) ops.versionedPseudoOps["dummyPseudo"][1] = OpSpec{Name: "b:", Version: AssemblerMaxVersion, Proto: proto("b:")} ops.versionedPseudoOps["dummyPseudo"][2] = OpSpec{Name: ":", Version: AssemblerMaxVersion} - _, _, ok := getSpec(ops, "dummyPseudo", []string{}) + _, _, ok := getSpec(ops, token{str: "dummyPseudo"}, 0) require.False(t, ok) - _, _, ok = getSpec(ops, "nonsense", []string{}) + _, _, ok = getSpec(ops, token{str: "nonsense"}, 0) require.False(t, ok) require.Equal(t, 2, len(ops.Errors)) require.Equal(t, "unknown opcode: nonsense", ops.Errors[1].Err.Error()) @@ -2881,8 +2971,8 @@ func TestReplacePseudo(t *testing.T) { for v := uint64(replaceVersion); v <= AssemblerMaxVersion; v++ { testProg(t, "byte 0x0000; byte 0x1234; replace 0", v) testProg(t, "byte 0x0000; int 0; byte 0x1234; replace", v) - testProg(t, "byte 0x0000; byte 0x1234; replace", v, Expect{1, "replace without immediates expects 3 stack arguments but stack height is 2"}) - testProg(t, "byte 0x0000; int 0; byte 0x1234; replace 0", v, Expect{1, "replace 0 arg 0 wanted type []byte got 0"}) + testProg(t, "byte 0x0000; byte 0x1234; replace", v, exp(1, "replace without immediates expects 3 stack arguments but stack height is 2")) + testProg(t, "byte 0x0000; int 0; byte 0x1234; replace 0", v, exp(1, "replace 0 arg 0 wanted type []byte got 0")) } } @@ -2936,14 +3026,14 @@ func TestAssembleSwitch(t *testing.T) { switch label1 label2 label1: ` - testProg(t, source, AssemblerMaxVersion, NewExpect(3, "reference to undefined label \"label2\"")) + testProg(t, source, AssemblerMaxVersion, Exp(3, "reference to undefined label \"label2\"")) // fail when target index != uint64 testProg(t, ` byte "fail" switch label1 labe11: - `, AssemblerMaxVersion, Expect{3, "switch label1 arg 0 wanted type uint64..."}) + `, AssemblerMaxVersion, exp(3, "switch label1 arg 0 wanted type uint64...")) // No labels is pretty degenerate, but ok, I suppose. It's just a no-op testProg(t, ` @@ -2982,7 +3072,7 @@ int 1 switch %s extra %s `, strings.Join(labels, " "), strings.Join(labels, ":\n")+":\n") - testProg(t, source, AssemblerMaxVersion, Expect{3, "switch cannot take more than 255 labels"}) + testProg(t, source, AssemblerMaxVersion, exp(3, "switch cannot take more than 255 labels")) // allow duplicate label reference source = ` @@ -3199,7 +3289,7 @@ add: #define c woah hey int 1 c`, - AssemblerMaxVersion, Expect{5, "Macro cycle discovered: c -> hey -> x -> d -> c"}, Expect{7, "unknown opcode: c"}, + AssemblerMaxVersion, exp(5, "macro expansion cycle discovered: c -> hey -> x -> d -> c"), exp(7, "unknown opcode: c"), ) testProg(t, ` @@ -3209,13 +3299,13 @@ add: #define c d int 1 c`, - AssemblerMaxVersion, Expect{5, "Macro cycle discovered: c -> d -> x -> c"}, Expect{7, "+ expects..."}, + AssemblerMaxVersion, exp(5, "macro expansion cycle discovered: c -> d -> x -> c"), exp(2, "+ expects...", 12), ) testProg(t, ` #define X X int 3`, - AssemblerMaxVersion, Expect{2, "Macro cycle discovered: X -> X"}, + AssemblerMaxVersion, exp(2, "macro expansion cycle discovered: X -> X"), ) // Check that macros names can't be things like named constants, opcodes, etc. @@ -3230,10 +3320,10 @@ add: #define + hey // since versioned check is now online, we can error here int 1`, assemblerNoVersion, - Expect{3, "Named constants..."}, - Expect{4, "Named constants..."}, - Expect{6, "Macro names cannot be opcodes: +"}, - Expect{8, "Macro names cannot be opcodes: +"}, + exp(3, "Named constants..."), + exp(4, "Named constants..."), + exp(5, "Macro names cannot be opcodes: +"), + exp(8, "Macro names cannot be opcodes: +"), ) // Same check, but this time since no version is given, the versioned check @@ -3247,10 +3337,10 @@ add: #define return hi #define + hey`, assemblerNoVersion, - Expect{3, "Named constants..."}, - Expect{4, "Named constants..."}, - Expect{6, "Macro names cannot be opcodes: +"}, - Expect{8, "Macro names cannot be opcodes: +"}, + exp(3, "Named constants..."), + exp(4, "Named constants..."), + exp(5, "Macro names cannot be opcodes: +"), + exp(8, "Macro names cannot be opcodes: +"), ) testProg(t, ` @@ -3261,7 +3351,8 @@ add: #define ApplicationArgs heyyyyy // no error b/c ApplicationArgs is after v1 int 1`, assemblerNoVersion, - Expect{4, "Macro names cannot be field names: Sender"}, // error happens once version is known + exp(2, "Macro names cannot be field names: Sender"), + exp(5, "Macro names cannot be field names: Sender"), ) // Same check but defaults to AssemblerDefaultVersion instead of pragma @@ -3272,8 +3363,8 @@ add: #define Sender helllooooo #define ApplicationArgs heyyyyy`, assemblerNoVersion, - Expect{4, "Macro names cannot be field names: Sender"}, // error happens once version is auto-set - Expect{5, "Macro names cannot be field names: Sender"}, // and on following line + exp(2, "Macro names cannot be field names: Sender"), + exp(5, "Macro names cannot be field names: Sender"), ) // define needs name and body testLine(t, "#define", AssemblerMaxVersion, "define directive requires a name and body") @@ -3300,20 +3391,20 @@ add: int 1 #define coolLabel 1`, AssemblerMaxVersion, - Expect{4, "Labels cannot be used as macro names: coolLabel"}, + exp(4, "Labels cannot be used as macro names: coolLabel"), ) testProg(t, ` #define coolLabel 1 coolLabel: int 1`, AssemblerMaxVersion, - Expect{3, "Cannot create label with same name as macro: coolLabel"}, + exp(3, "Cannot create label with same name as macro: coolLabel"), ) - // Admittedly these two tests are just for coverage + // These two tests are just for coverage, they really really can't happen ops := newOpStream(AssemblerMaxVersion) - err := define(&ops, []string{"not#define"}) + err := define(&ops, []token{{str: "not#define"}}) require.EqualError(t, err, "0: invalid syntax: not#define") - err = pragma(&ops, []string{"not#pragma"}) + err = pragma(&ops, []token{{str: "not#pragma"}}) require.EqualError(t, err, "0: invalid syntax: not#pragma") } @@ -3329,20 +3420,20 @@ func TestAssembleImmediateRanges(t *testing.T) { testProg(t, "load 255;", AssemblerMaxVersion) testProg(t, "int 1; store -1000;", AssemblerMaxVersion, - Expect{1, "store unable to parse..."}) + exp(1, "store unable to parse...")) testProg(t, "load -100;", AssemblerMaxVersion, - Expect{1, "load unable to parse..."}) + exp(1, "load unable to parse...")) testProg(t, "int 1; store 256;", AssemblerMaxVersion, - Expect{1, "store i beyond 255: 256"}) + exp(1, "store i beyond 255: 256")) testProg(t, "frame_dig -1;", AssemblerMaxVersion) testProg(t, "frame_dig 127;", AssemblerMaxVersion) testProg(t, "int 1; frame_bury -128;", AssemblerMaxVersion) testProg(t, "frame_dig 128;", AssemblerMaxVersion, - Expect{1, "frame_dig unable to parse..."}) + exp(1, "frame_dig unable to parse...")) testProg(t, "int 1; frame_bury -129;", AssemblerMaxVersion, - Expect{1, "frame_bury unable to parse..."}) + exp(1, "frame_bury unable to parse...")) } func TestAssembleMatch(t *testing.T) { @@ -3355,7 +3446,7 @@ func TestAssembleMatch(t *testing.T) { match label1 label2 label1: ` - testProg(t, source, AssemblerMaxVersion, NewExpect(3, "reference to undefined label \"label2\"")) + testProg(t, source, AssemblerMaxVersion, Exp(3, "reference to undefined label \"label2\"")) // No labels is pretty degenerate, but ok, I suppose. It's just a no-op testProg(t, ` @@ -3403,7 +3494,7 @@ int 1 match %s extra %s `, strings.Join(labels, " "), strings.Join(labels, ":\n")+":\n") - testProg(t, source, AssemblerMaxVersion, Expect{3, "match cannot take more than 255 labels"}) + testProg(t, source, AssemblerMaxVersion, exp(3, "match cannot take more than 255 labels")) // allow duplicate label reference source = ` @@ -3452,20 +3543,19 @@ func TestAssemblePushConsts(t *testing.T) { // enforce correct types source = `pushints "1" "2" "3"` - testProg(t, source, AssemblerMaxVersion, Expect{1, `strconv.ParseUint: parsing "\"1\"": invalid syntax`}) + testProg(t, source, AssemblerMaxVersion, exp(1, `strconv.ParseUint: parsing "\"1\"": invalid syntax`)) source = `pushbytess 1 2 3` - testProg(t, source, AssemblerMaxVersion, Expect{1, "byte arg did not parse: 1"}) + testProg(t, source, AssemblerMaxVersion, exp(1, "pushbytess arg did not parse: 1")) source = `pushints 6 4; concat` - testProg(t, source, AssemblerMaxVersion, Expect{1, "concat arg 1 wanted type []byte got uint64"}) + testProg(t, source, AssemblerMaxVersion, exp(1, "concat arg 1 wanted type []byte got uint64")) source = `pushbytess "x" "y"; +` - testProg(t, source, AssemblerMaxVersion, Expect{1, "+ arg 1 wanted type uint64 got []byte"}) + testProg(t, source, AssemblerMaxVersion, exp(1, "+ arg 1 wanted type uint64 got []byte")) } func TestAssembleEmpty(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - emptyExpect := Expect{0, "Cannot assemble empty program text"} emptyPrograms := []string{ "", " ", @@ -3477,7 +3567,7 @@ func TestAssembleEmpty(t *testing.T) { for version := uint64(1); version <= AssemblerMaxVersion; version++ { for _, prog := range emptyPrograms { - testProg(t, prog, version, emptyExpect) + testProg(t, prog, version, exp(0, "Cannot assemble empty program text")) } testProg(t, nonEmpty, version) } @@ -3487,14 +3577,8 @@ func TestReportMultipleErrors(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() - assertWithMsg := func(t *testing.T, expectedOutput string, b bytes.Buffer) { - if b.String() != expectedOutput { - t.Errorf("Unexpected output: got %q, want %q", b.String(), expectedOutput) - } - } - ops := &OpStream{ - Errors: []lineError{ + Errors: []sourceError{ {Line: 1, Err: errors.New("error 1")}, {Err: errors.New("error 2")}, {Line: 3, Err: errors.New("error 3")}, @@ -3514,7 +3598,7 @@ test.txt: 3: error 3 test.txt: warning 1 test.txt: warning 2 ` - assertWithMsg(t, expected, b) + require.Equal(t, expected, b.String()) // Test the case where fname is empty b.Reset() @@ -3525,45 +3609,45 @@ test.txt: warning 2 warning 1 warning 2 ` - assertWithMsg(t, expected, b) + require.Equal(t, expected, b.String()) // no errors or warnings at all ops = &OpStream{} b.Reset() ops.ReportMultipleErrors("blah blah", &b) expected = "" - assertWithMsg(t, expected, b) + require.Equal(t, expected, b.String()) // more than 10 errors: file := "great-file.go" - les := []lineError{} + les := []sourceError{} expectedStrs := []string{} for i := 1; i <= 11; i++ { errS := fmt.Errorf("error %d", i) - les = append(les, lineError{i, errS}) + les = append(les, sourceError{i, 5, errS}) if i <= 10 { - expectedStrs = append(expectedStrs, fmt.Sprintf("%s: %d: %s", file, i, errS)) + expectedStrs = append(expectedStrs, fmt.Sprintf("%s: %d:5: %s", file, i, errS)) } } expected = strings.Join(expectedStrs, "\n") + "\n" ops = &OpStream{Errors: les} b.Reset() ops.ReportMultipleErrors(file, &b) - assertWithMsg(t, expected, b) + require.Equal(t, expected, b.String()) // exactly 1 error + filename - ops = &OpStream{Errors: []lineError{{42, errors.New("super annoying error")}}} + ops = &OpStream{Errors: []sourceError{{42, 0, errors.New("super annoying error")}}} b.Reset() ops.ReportMultipleErrors("galaxy.py", &b) expected = "galaxy.py: 1 error: 42: super annoying error\n" - assertWithMsg(t, expected, b) + require.Equal(t, expected, b.String()) // exactly 1 error w/o filename - ops = &OpStream{Errors: []lineError{{42, errors.New("super annoying error")}}} + ops = &OpStream{Errors: []sourceError{{42, 0, errors.New("super annoying error")}}} b.Reset() ops.ReportMultipleErrors("", &b) expected = "1 error: 42: super annoying error\n" - assertWithMsg(t, expected, b) + require.Equal(t, expected, b.String()) } // TestDisassembleBadBranch ensures a clean error when a branch has no target. diff --git a/data/transactions/logic/backwardCompat_test.go b/data/transactions/logic/backwardCompat_test.go index e8353e5d27..84b230bb87 100644 --- a/data/transactions/logic/backwardCompat_test.go +++ b/data/transactions/logic/backwardCompat_test.go @@ -464,22 +464,22 @@ func TestBackwardCompatAssemble(t *testing.T) { // v1 does not allow branching to the last line // v2 makes such programs legal t.Parallel() - source := "int 1; int 1; bnz done; done:" - t.Run("v=default", func(t *testing.T) { - t.Parallel() - testProg(t, source, assemblerNoVersion, Expect{1, "label \"done\" is too far away"}) - }) - - t.Run("v=default", func(t *testing.T) { - t.Parallel() - testProg(t, source, 0, Expect{1, "label \"done\" is too far away"}) - }) - - t.Run("v=default", func(t *testing.T) { - t.Parallel() - testProg(t, source, 1, Expect{1, "label \"done\" is too far away"}) - }) + // Label is ok, it just can't be branched to + source := "int 1; done:" + testProg(t, source, assemblerNoVersion) + testProg(t, source, 0) + testProg(t, source, 1) + + // use multiple lines, so that error report is checked better + source = `int 1; + int 1; + bnz done; + done: +` + testProg(t, source, assemblerNoVersion, exp(3, "label \"done\" is too far away", 5)) + testProg(t, source, 0, exp(3, "label \"done\" is too far away", 5)) + testProg(t, source, 1, exp(3, "label \"done\" is too far away", 5)) for v := uint64(2); v <= AssemblerMaxVersion; v++ { v := v diff --git a/data/transactions/logic/box_test.go b/data/transactions/logic/box_test.go index 323a64e5a8..5f08878a93 100644 --- a/data/transactions/logic/box_test.go +++ b/data/transactions/logic/box_test.go @@ -242,7 +242,7 @@ func TestBoxAvailability(t *testing.T) { TestApps(t, []string{ `byte "self"; int 64; box_create`, `byte "B"; int 10; int 4; box_extract; byte 0x00000000; ==`, - }, nil, 8, ledger, NewExpect(1, fmt.Sprintf("invalid Box reference %#x", 'B'))) + }, nil, 8, ledger, Exp(1, fmt.Sprintf("invalid Box reference %#x", 'B'))) // B is available if indexed by 0 in tx[1].Boxes group := MakeSampleTxnGroup(MakeSampleTxn(), txntest.Txn{ @@ -254,7 +254,7 @@ func TestBoxAvailability(t *testing.T) { TestApps(t, []string{ `byte "self"; int 64; box_create`, `byte "B"; int 10; int 4; box_extract; byte 0x00000000; ==`, - }, group, 8, ledger, NewExpect(1, "no such box")) + }, group, 8, ledger, Exp(1, "no such box")) // B is available if listed by appId in tx[1].Boxes group = MakeSampleTxnGroup(MakeSampleTxn(), txntest.Txn{ @@ -267,7 +267,7 @@ func TestBoxAvailability(t *testing.T) { TestApps(t, []string{ `byte "self"; int 64; box_create`, `byte "B"; int 10; int 4; box_extract; byte 0x00000000; ==`, - }, group, 8, ledger, NewExpect(1, "no such box")) + }, group, 8, ledger, Exp(1, "no such box")) } func TestBoxReadBudget(t *testing.T) { diff --git a/data/transactions/logic/debugger.go b/data/transactions/logic/debugger.go index 0d62b8dc84..bc10ca79dc 100644 --- a/data/transactions/logic/debugger.go +++ b/data/transactions/logic/debugger.go @@ -184,7 +184,7 @@ func makeDebugState(cx *EvalContext) *DebugState { if err != nil { sv = stackValue{Bytes: []byte(err.Error())} } - globals[fs.field] = stackValueToTealValue(&sv) + globals[fs.field] = sv.toEncodedTealValue() } ds.Globals = globals @@ -244,22 +244,13 @@ func (d *DebugState) PCToLine(pc int) int { return len(strings.Split(d.Disassembly[:offset], "\n")) - one } -func stackValueToTealValue(sv *stackValue) basics.TealValue { - tv := sv.toTealValue() - return basics.TealValue{ - Type: tv.Type, - Bytes: base64.StdEncoding.EncodeToString([]byte(tv.Bytes)), - Uint: tv.Uint, - } -} - -// valueDeltaToValueDelta converts delta's bytes to base64 in a new struct -func valueDeltaToValueDelta(vd *basics.ValueDelta) basics.ValueDelta { - return basics.ValueDelta{ - Action: vd.Action, - Bytes: base64.StdEncoding.EncodeToString([]byte(vd.Bytes)), - Uint: vd.Uint, +// toEncodedTealValue converts stackValue to basics.TealValue, with the Bytes +// field b64 encoded, so it is suitable for conversion to JSON. +func (sv stackValue) toEncodedTealValue() basics.TealValue { + if sv.avmType() == avmBytes { + return basics.TealValue{Type: basics.TealBytesType, Bytes: base64.StdEncoding.EncodeToString(sv.Bytes)} } + return basics.TealValue{Type: basics.TealUintType, Uint: sv.Uint} } // parseCallStack initializes an array of CallFrame objects from the raw @@ -296,12 +287,12 @@ func (a *debuggerEvalTracerAdaptor) refreshDebugState(cx *EvalContext, evalError stack := make([]basics.TealValue, len(cx.stack)) for i, sv := range cx.stack { - stack[i] = stackValueToTealValue(&sv) + stack[i] = sv.toEncodedTealValue() } scratch := make([]basics.TealValue, len(cx.scratch)) for i, sv := range cx.scratch { - scratch[i] = stackValueToTealValue(&sv) + scratch[i] = sv.toEncodedTealValue() } ds.Stack = stack diff --git a/data/transactions/logic/debugger_test.go b/data/transactions/logic/debugger_test.go index 1303e57131..283bcaa6df 100644 --- a/data/transactions/logic/debugger_test.go +++ b/data/transactions/logic/debugger_test.go @@ -17,10 +17,8 @@ package logic import ( - "encoding/base64" "testing" - "github.com/algorand/go-algorand/data/basics" "github.com/algorand/go-algorand/test/partitiontest" "github.com/stretchr/testify/require" ) @@ -63,22 +61,6 @@ func TestLineToPC(t *testing.T) { require.Equal(t, 0, pc) } -func TestValueDeltaToValueDelta(t *testing.T) { - partitiontest.PartitionTest(t) - t.Parallel() - - vDelta := basics.ValueDelta{ - Action: basics.SetUintAction, - Bytes: "some string", - Uint: uint64(0xffffffff), - } - ans := valueDeltaToValueDelta(&vDelta) - require.Equal(t, vDelta.Action, ans.Action) - require.NotEqual(t, vDelta.Bytes, ans.Bytes) - require.Equal(t, base64.StdEncoding.EncodeToString([]byte(vDelta.Bytes)), ans.Bytes) - require.Equal(t, vDelta.Uint, ans.Uint) -} - const testCallStackProgram string = `intcblock 1 callsub label1 intc_0 diff --git a/data/transactions/logic/eval.go b/data/transactions/logic/eval.go index 2cd78c40ff..e5e55525e5 100644 --- a/data/transactions/logic/eval.go +++ b/data/transactions/logic/eval.go @@ -160,7 +160,7 @@ func (sv stackValue) string(limit int) (string, error) { return string(sv.Bytes), nil } -func (sv stackValue) toTealValue() (tv basics.TealValue) { +func (sv stackValue) toTealValue() basics.TealValue { if sv.avmType() == avmBytes { return basics.TealValue{Type: basics.TealBytesType, Bytes: string(sv.Bytes)} } @@ -539,10 +539,16 @@ func (ep *EvalParams) RecordAD(gi int, ad transactions.ApplyData) { } ep.TxnGroup[gi].ApplyData = ad if aid := ad.ConfigAsset; aid != 0 { - ep.available.createdAsas = append(ep.available.createdAsas, aid) + if ep.available.createdAsas == nil { + ep.available.createdAsas = make(map[basics.AssetIndex]struct{}) + } + ep.available.createdAsas[aid] = struct{}{} } if aid := ad.ApplicationID; aid != 0 { - ep.available.createdApps = append(ep.available.createdApps, aid) + if ep.available.createdApps == nil { + ep.available.createdApps = make(map[basics.AppIndex]struct{}) + } + ep.available.createdApps[aid] = struct{}{} } } @@ -954,14 +960,21 @@ func EvalContract(program []byte, gi int, aid basics.AppIndex, params *EvalParam } } - // If this is a creation, make any "0 index" box refs available now that we - // have an appID. + // If this is a creation... if cx.txn.Txn.ApplicationID == 0 { + // make any "0 index" box refs available now that we have an appID. for _, br := range cx.txn.Txn.Boxes { if br.Index == 0 { cx.EvalParams.available.boxes[boxRef{cx.appID, string(br.Name)}] = false } } + // and add the appID to `createdApps` + if cx.EvalParams.Proto.LogicSigVersion >= sharedResourcesVersion { + if cx.EvalParams.available.createdApps == nil { + cx.EvalParams.available.createdApps = make(map[basics.AppIndex]struct{}) + } + cx.EvalParams.available.createdApps[cx.appID] = struct{}{} + } } // Check the I/O budget for reading if this is the first top-level app call @@ -4248,13 +4261,15 @@ func opExtract64Bits(cx *EvalContext) error { // assignAccount is used to convert a stackValue into a 32-byte account value, // enforcing any "availability" restrictions in force. func (cx *EvalContext) assignAccount(sv stackValue) (basics.Address, error) { - _, err := sv.address() + addr, err := sv.address() if err != nil { return basics.Address{}, err } - addr, _, err := cx.accountReference(sv) - return addr, err + if cx.availableAccount(addr) { + return addr, nil + } + return basics.Address{}, fmt.Errorf("invalid Account reference %s", addr) } // accountReference yields the address and Accounts offset designated by a @@ -4323,7 +4338,7 @@ func (cx *EvalContext) availableAccount(addr basics.Address) bool { // Allow an address for an app that was created in group if cx.version >= createdResourcesVersion { - for _, appID := range cx.available.createdApps { + for appID := range cx.available.createdApps { createdAddress := cx.getApplicationAddress(appID) if addr == createdAddress { return true @@ -5199,10 +5214,8 @@ func (cx *EvalContext) availableAsset(aid basics.AssetIndex) bool { } // or was created in group if cx.version >= createdResourcesVersion { - for _, assetID := range cx.available.createdAsas { - if assetID == aid { - return true - } + if _, ok := cx.available.createdAsas[aid]; ok { + return true } } @@ -5241,10 +5254,8 @@ func (cx *EvalContext) availableApp(aid basics.AppIndex) bool { } // or was created in group if cx.version >= createdResourcesVersion { - for _, appID := range cx.available.createdApps { - if appID == aid { - return true - } + if _, ok := cx.available.createdApps[aid]; ok { + return true } } // Or, it can be the current app diff --git a/data/transactions/logic/evalAppTxn_test.go b/data/transactions/logic/evalAppTxn_test.go index 22c0e1691d..c72236a878 100644 --- a/data/transactions/logic/evalAppTxn_test.go +++ b/data/transactions/logic/evalAppTxn_test.go @@ -584,12 +584,12 @@ func TestNumInnerPooled(t *testing.T) { TestApps(t, []string{short, long}, grp, LogicVersion, ledger) TestApps(t, []string{long, short}, grp, LogicVersion, ledger) TestApps(t, []string{long, long}, grp, LogicVersion, ledger, - NewExpect(1, "too many inner transactions")) + Exp(1, "too many inner transactions")) grp = append(grp, grp[0]) TestApps(t, []string{short, long, long}, grp, LogicVersion, ledger, - NewExpect(2, "too many inner transactions")) + Exp(2, "too many inner transactions")) TestApps(t, []string{long, long, long}, grp, LogicVersion, ledger, - NewExpect(1, "too many inner transactions")) + Exp(1, "too many inner transactions")) } func TestAssetCreate(t *testing.T) { diff --git a/data/transactions/logic/evalStateful_test.go b/data/transactions/logic/evalStateful_test.go index be36eb6859..3899cdaebb 100644 --- a/data/transactions/logic/evalStateful_test.go +++ b/data/transactions/logic/evalStateful_test.go @@ -383,7 +383,7 @@ func TestBalance(t *testing.T) { // won't assemble in old version teal if v < directRefEnabledVersion { testProg(t, source, ep.Proto.LogicSigVersion, - Expect{1, "balance arg 0 wanted type uint64..."}) + exp(1, "balance arg 0 wanted type uint64...")) return } @@ -399,7 +399,7 @@ func TestBalance(t *testing.T) { } func testApps(t *testing.T, programs []string, txgroup []transactions.SignedTxn, version uint64, ledger *Ledger, - expected ...Expect) *EvalParams { + expected ...expect) *EvalParams { t.Helper() codes := make([][]byte, len(programs)) for i, program := range programs { @@ -427,7 +427,7 @@ func testApps(t *testing.T, programs []string, txgroup []transactions.SignedTxn, return ep } -func testAppsBytes(t *testing.T, programs [][]byte, ep *EvalParams, expected ...Expect) { +func testAppsBytes(t *testing.T, programs [][]byte, ep *EvalParams, expected ...expect) { t.Helper() require.LessOrEqual(t, len(programs), len(ep.TxnGroup)) for i := range ep.TxnGroup { @@ -623,7 +623,7 @@ func TestAppCheckOptedIn(t *testing.T) { testApp(t, "int 1; int 2; app_opted_in; int 0; ==", pre) // in pre, int 2 is an actual app id testApp(t, "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui01\"; int 2; app_opted_in; int 1; ==", now) testProg(t, "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui01\"; int 2; app_opted_in; int 1; ==", directRefEnabledVersion-1, - Expect{1, "app_opted_in arg 0 wanted type uint64..."}) + exp(1, "app_opted_in arg 0 wanted type uint64...")) // Receiver opts into 888, the current app in testApp ledger.NewLocals(txn.Txn.Receiver, 888) @@ -698,7 +698,7 @@ byte "ALGO" testApp(t, text, now) testApp(t, strings.Replace(text, "int 1 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui01\"", -1), now) testProg(t, strings.Replace(text, "int 1 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui01\"", -1), directRefEnabledVersion-1, - Expect{4, "app_local_get_ex arg 0 wanted type uint64..."}) + exp(4, "app_local_get_ex arg 0 wanted type uint64...")) testApp(t, strings.Replace(text, "int 100 // app id", "int 2", -1), now) // Next we're testing if the use of the current app's id works // as a direct reference. The error is because the receiver @@ -771,7 +771,7 @@ byte "ALGO" testApp(t, text, now) testApp(t, strings.Replace(text, "int 0 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00\"", -1), now) testProg(t, strings.Replace(text, "int 0 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00\"", -1), directRefEnabledVersion-1, - Expect{3, "app_local_get arg 0 wanted type uint64..."}) + exp(3, "app_local_get arg 0 wanted type uint64...")) testApp(t, strings.Replace(text, "int 0 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui01\"", -1), now) testApp(t, strings.Replace(text, "int 0 // account idx", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui02\"", -1), now, "invalid Account reference") @@ -1033,7 +1033,7 @@ func testAssetsByVersion(t *testing.T, assetsTestProgram string, version uint64) // it wasn't legal to use a direct ref for account testProg(t, `byte "aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00"; int 54; asset_holding_get AssetBalance`, - directRefEnabledVersion-1, Expect{1, "asset_holding_get AssetBalance arg 0 wanted type uint64..."}) + directRefEnabledVersion-1, exp(1, "asset_holding_get AssetBalance arg 0 wanted type uint64...")) // but it is now (empty asset yields 0,0 on stack) testApp(t, `byte "aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00"; int 55; asset_holding_get AssetBalance; ==`, now) // This is receiver, who is in Assets array @@ -1076,7 +1076,7 @@ func testAssetsByVersion(t *testing.T, assetsTestProgram string, version uint64) testApp(t, strings.Replace(assetsTestProgram, "int 55", "int 0", -1), now) // but old code cannot - testProg(t, strings.Replace(assetsTestProgram, "int 0//account", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00\"", -1), directRefEnabledVersion-1, Expect{3, "asset_holding_get AssetBalance arg 0 wanted type uint64..."}) + testProg(t, strings.Replace(assetsTestProgram, "int 0//account", "byte \"aoeuiaoeuiaoeuiaoeuiaoeuiaoeui00\"", -1), directRefEnabledVersion-1, exp(3, "asset_holding_get AssetBalance arg 0 wanted type uint64...")) if version < 5 { // Can't run these with AppCreator anyway @@ -2391,7 +2391,7 @@ int 1 delta := testApp(t, withBytes, ep) // But won't even compile in old teal testProg(t, withBytes, directRefEnabledVersion-1, - Expect{4, "app_local_put arg 0 wanted..."}, Expect{11, "app_local_del arg 0 wanted..."}) + exp(4, "app_local_put arg 0 wanted..."), exp(11, "app_local_del arg 0 wanted...")) require.Equal(t, 0, len(delta.GlobalDelta)) require.Equal(t, 2, len(delta.LocalDeltas)) ledger.Reset() @@ -2900,9 +2900,9 @@ func TestTxnEffects(t *testing.T) { // Look past the logs of tx 0 testApps(t, []string{"byte 0x37; log; int 1", "gtxna 0 Logs 1; byte 0x37; =="}, nil, AssemblerMaxVersion, nil, - Expect{1, "invalid Logs index 1"}) + exp(1, "invalid Logs index 1")) testApps(t, []string{"byte 0x37; log; int 1", "int 6; gtxnas 0 Logs; byte 0x37; =="}, nil, AssemblerMaxVersion, nil, - Expect{1, "invalid Logs index 6"}) + exp(1, "invalid Logs index 6")) } func TestRound(t *testing.T) { @@ -3002,7 +3002,7 @@ func TestPooledAppCallsVerifyOp(t *testing.T) { call := transactions.SignedTxn{Txn: transactions.Transaction{Type: protocol.ApplicationCallTx}} // Simulate test with 2 grouped txn testApps(t, []string{source, ""}, []transactions.SignedTxn{call, call}, LogicVersion, ledger, - Expect{0, "pc=107 dynamic cost budget exceeded, executing ed25519verify: local program cost was 5"}) + exp(0, "pc=107 dynamic cost budget exceeded, executing ed25519verify: local program cost was 5")) // Simulate test with 3 grouped txn testApps(t, []string{source, "", ""}, []transactions.SignedTxn{call, call, call}, LogicVersion, ledger) diff --git a/data/transactions/logic/eval_test.go b/data/transactions/logic/eval_test.go index f93df4149e..de99cab3a1 100644 --- a/data/transactions/logic/eval_test.go +++ b/data/transactions/logic/eval_test.go @@ -621,7 +621,7 @@ after: dup pop ` - testProg(t, code, LogicVersion, Expect{12, "+ expects 2 stack arguments..."}) + testProg(t, code, LogicVersion, exp(12, "+ expects 2 stack arguments...")) testAccepts(t, notrack(code), 1) } @@ -2474,17 +2474,17 @@ func TestSubstringFlop(t *testing.T) { // fails in compiler testProg(t, `byte 0xf000000000000000 substring -len`, 2, Expect{2, "substring expects 2 immediate arguments"}) +len`, 2, exp(2, "substring expects 2 immediate arguments")) // fails in compiler testProg(t, `byte 0xf000000000000000 substring 1 -len`, 2, Expect{2, "substring expects 2 immediate arguments"}) +len`, 2, exp(2, "substring expects 2 immediate arguments")) // fails in compiler testProg(t, `byte 0xf000000000000000 substring 4 2 -len`, 2, Expect{2, "substring end is before start"}) +len`, 2, exp(2, "substring end is before start")) // fails at runtime testPanics(t, `byte 0xf000000000000000 @@ -2539,17 +2539,17 @@ func TestExtractFlop(t *testing.T) { // fails in compiler testProg(t, `byte 0xf000000000000000 extract - len`, 5, Expect{2, "extract without immediates expects 3 stack arguments but stack height is 1"}) + len`, 5, exp(2, "extract without immediates expects 3 stack arguments but stack height is 1")) testProg(t, `byte 0xf000000000000000 extract 1 - len`, 5, Expect{2, "extract expects 0 or 2 immediate arguments"}) + len`, 5, exp(2, "extract expects 0 or 2 immediate arguments")) testProg(t, `byte 0xf000000000000000 int 0 int 5 extract3 1 2 - len`, 5, Expect{4, "extract3 expects 0 immediate arguments"}) + len`, 5, exp(4, "extract3 expects 0 immediate arguments")) // fails at runtime err := testPanics(t, `byte 0xf000000000000000 @@ -2751,7 +2751,7 @@ func TestGload(t *testing.T) { } if testCase.errContains != "" { - testApps(t, sources, txgroup, LogicVersion, nil, Expect{testCase.errTxn, testCase.errContains}) + testApps(t, sources, txgroup, LogicVersion, nil, exp(testCase.errTxn, testCase.errContains)) } else { testApps(t, sources, txgroup, LogicVersion, nil) } @@ -4437,7 +4437,7 @@ func testEvaluation(t *testing.T, program string, introduced uint64, tester eval t.Run(fmt.Sprintf("v=%d", v), func(t *testing.T) { t.Helper() if v < introduced { - testProg(t, notrack(program), v, Expect{0, "...was introduced..."}) + testProg(t, notrack(program), v, exp(0, "...was introduced...")) return } ops := testProg(t, program, v) @@ -4632,7 +4632,7 @@ func TestBury(t *testing.T) { // bury 0 panics source := "int 3; int 2; int 7; bury 0; int 1; return" - testProg(t, source, 8, Expect{1, "bury 0 always fails"}) + testProg(t, source, 8, exp(1, "bury 0 always fails")) testPanics(t, notrack("int 3; int 2; int 7; bury 0; int 1; return"), 8, "bury outside stack") // bury 1 pops the ToS and replaces the thing "1 down", which becomes the new ToS @@ -5282,13 +5282,13 @@ By Herman Melville`, "", source := fmt.Sprintf(template, hex.EncodeToString([]byte(tc.decoded)), hex.EncodeToString([]byte(tc.encoded)), tc.alph) if tc.error == "" { if LogicVersion < fidoVersion { - testProg(t, source, AssemblerMaxVersion, Expect{0, "unknown opcode..."}) + testProg(t, source, AssemblerMaxVersion, exp(0, "unknown opcode...")) } else { testAccepts(t, source, fidoVersion) } } else { if LogicVersion < fidoVersion { - testProg(t, source, AssemblerMaxVersion, Expect{0, "unknown opcode..."}) + testProg(t, source, AssemblerMaxVersion, exp(0, "unknown opcode...")) } else { err := testPanics(t, source, fidoVersion) require.Error(t, err) @@ -5405,7 +5405,7 @@ func TestOpJSONRef(t *testing.T) { ep.SigLedger = ledger testCases := []struct { source string - previousVersErrors []Expect + previousVersErrors []expect }{ { source: `byte "{\"key0\": 0,\"key1\": \"algo\",\"key2\":{\"key3\": \"teal\", \"key4\":3}, \"key5\": 18446744073709551615 }"; @@ -5413,7 +5413,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONUint64; int 0; ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 0,\"key1\": \"algo\",\"key2\":{\"key3\": \"teal\", \"key4\": 3}, \"key5\": 18446744073709551615 }"; @@ -5421,7 +5421,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONUint64; int 18446744073709551615; //max uint64 value ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 0,\"key1\": \"algo\",\"key2\":{\"key3\": \"teal\", \"key4\": 3}, \"key5\": 18446744073709551615 }"; @@ -5429,7 +5429,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONString; byte "algo"; ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 0,\"key1\": \"\\u0061\\u006C\\u0067\\u006F\",\"key2\":{\"key3\": \"teal\", \"key4\": 3}, \"key5\": 18446744073709551615 }"; @@ -5437,7 +5437,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONString; byte "algo"; ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 0,\"key1\": \"algo\",\"key2\":{\"key3\": \"teal\", \"key4\": {\"key40\": 10}}, \"key5\": 18446744073709551615 }"; @@ -5449,7 +5449,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONUint64 int 10 ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}, {5, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref"), exp(5, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 0,\"key1\": \"algo\",\"key2\":{\"key3\": \"teal\", \"key4\": {\"key40\": 10}}, \"key5\": 18446744073709551615 }"; @@ -5459,7 +5459,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONString; byte "teal" ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}, {5, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref"), exp(5, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 0,\"key1\": \"algo\",\"key2\":{\"key3\": \"\\"teal\\"\", \"key4\": {\"key40\": 10}}, \"key5\": 18446744073709551615 }"; @@ -5469,7 +5469,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONString; byte ""teal"" // quotes match ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}, {5, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref"), exp(5, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 0,\"key1\": \"algo\",\"key2\":{\"key3\": \" teal \", \"key4\": {\"key40\": 10}}, \"key5\": 18446744073709551615 }"; @@ -5479,7 +5479,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONString; byte " teal " // spaces match ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}, {5, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref"), exp(5, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 0,\"key1\": \"algo\",\"key2\":{\"key3\": \"teal\", \"key4\": {\"key40\": 10, \"key40\": \"10\"}}, \"key5\": 18446744073709551615 }"; @@ -5490,7 +5490,7 @@ func TestOpJSONRef(t *testing.T) { byte "{\"key40\": 10, \"key40\": \"10\"}" == `, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, { source: `byte "{\"rawId\": \"responseId\",\"id\": \"0\",\"response\": {\"attestationObject\": \"based64url_encoded_buffer\",\"clientDataJSON\": \" based64url_encoded_client_data\"},\"getClientExtensionResults\": {},\"type\": \"public-key\"}"; @@ -5498,7 +5498,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONObject; byte "{\"attestationObject\": \"based64url_encoded_buffer\",\"clientDataJSON\": \" based64url_encoded_client_data\"}" // object as it appeared in input ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, { source: `byte "{\"rawId\": \"responseId\",\"id\": \"0\",\"response\": {\"attestationObject\": \"based64url_encoded_buffer\",\"clientD\\u0061taJSON\": \" based64url_encoded_client_data\"},\"getClientExtensionResults\": {},\"type\": \"public-key\"}"; @@ -5506,7 +5506,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONObject; byte "{\"attestationObject\": \"based64url_encoded_buffer\",\"clientD\\u0061taJSON\": \" based64url_encoded_client_data\"}" // object as it appeared in input ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, { source: `byte "{\"rawId\": \"responseId\",\"id\": \"0\",\"response\": {\"attestationObject\": \"based64url_encoded_buffer\",\"clientDataJSON\": \" based64url_encoded_client_data\"},\"getClientExtensionResults\": {},\"type\": \"public-key\"}"; @@ -5516,7 +5516,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONString; byte " based64url_encoded_client_data"; ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}, {5, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref"), exp(5, "unknown opcode: json_ref")}, }, { source: `byte "{\"\\u0072\\u0061\\u0077\\u0049\\u0044\": \"responseId\",\"id\": \"0\",\"response\": {\"attestationObject\": \"based64url_encoded_buffer\",\"clientDataJSON\": \" based64url_encoded_client_data\"},\"getClientExtensionResults\": {},\"type\": \"public-key\"}"; @@ -5524,7 +5524,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONString; byte "responseId" ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, // JavaScript MAX_SAFE_INTEGER { @@ -5533,7 +5533,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONUint64; int 9007199254740991; ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, // maximum uint64 { @@ -5542,7 +5542,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONUint64; int 18446744073709551615; ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, // larger-than-uint64s are allowed if not requested { @@ -5551,7 +5551,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONUint64; int 0; ==`, - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, } @@ -5586,57 +5586,57 @@ func TestOpJSONRef(t *testing.T) { failedCases := []struct { source string error string - previousVersErrors []Expect + previousVersErrors []expect }{ { source: `byte "{\"key0\": 1 }"; byte "key0"; json_ref JSONString;`, error: "json: cannot unmarshal number into Go value of type string", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": [1] }"; byte "key0"; json_ref JSONString;`, error: "json: cannot unmarshal array into Go value of type string", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": {\"key1\":1} }"; byte "key0"; json_ref JSONString;`, error: "json: cannot unmarshal object into Go value of type string", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": \"1\" }"; byte "key0"; json_ref JSONUint64;`, error: "json: cannot unmarshal string into Go value of type uint64", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": [\"1\"] }"; byte "key0"; json_ref JSONUint64;`, error: "json: cannot unmarshal array into Go value of type uint64", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": {\"key1\":1} }"; byte "key0"; json_ref JSONUint64;`, error: "json: cannot unmarshal object into Go value of type uint64", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": [1]}"; byte "key0"; json_ref JSONObject;`, error: "json: cannot unmarshal array into Go value of type map[string]json.RawMessage", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 1}"; byte "key0"; json_ref JSONObject;`, error: "json: cannot unmarshal number into Go value of type map[string]json.RawMessage", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": \"1\"}"; byte "key0"; json_ref JSONObject;`, error: "json: cannot unmarshal string into Go value of type map[string]json.RawMessage", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 1,\"key1\": \"algo\",\"key2\":{\"key3\": \"teal\", \"key4\": [1,2,3]} }"; byte "key3"; json_ref JSONString;`, error: "key key3 not found in JSON text", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 1,\"key1\": \"algo\",\"key2\":{\"key3\": \"teal\", \"key4\": [1,2,3]}}"; @@ -5646,52 +5646,52 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONString `, error: "key key5 not found in JSON text", - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}, {5, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref"), exp(5, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": -0,\"key1\": 2.5,\"key2\": -3}"; byte "key0"; json_ref JSONUint64;`, error: "json: cannot unmarshal number -0 into Go value of type uint64", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 1e10,\"key1\": 2.5,\"key2\": -3}"; byte "key0"; json_ref JSONUint64;`, error: "json: cannot unmarshal number 1e10 into Go value of type uint64", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 0.2e-2,\"key1\": 2.5,\"key2\": -3}"; byte "key0"; json_ref JSONUint64;`, error: "json: cannot unmarshal number 0.2e-2 into Go value of type uint64", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 1.0,\"key1\": 2.5,\"key2\": -3}"; byte "key0"; json_ref JSONUint64;`, error: "json: cannot unmarshal number 1.0 into Go value of type uint64", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 1.0,\"key1\": 2.5,\"key2\": -3}"; byte "key1"; json_ref JSONUint64;`, error: "json: cannot unmarshal number 2.5 into Go value of type uint64", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 1.0,\"key1\": 2.5,\"key2\": -3}"; byte "key2"; json_ref JSONUint64;`, error: "json: cannot unmarshal number -3 into Go value of type uint64", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 18446744073709551616}"; byte "key0"; json_ref JSONUint64;`, error: "json: cannot unmarshal number 18446744073709551616 into Go value of type uint64", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 1,}"; byte "key0"; json_ref JSONString;`, error: "error while parsing JSON text, invalid json text", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 1, \"key0\": \"3\"}"; byte "key0"; json_ref JSONString;`, error: "error while parsing JSON text, invalid json text, duplicate keys not allowed", - previousVersErrors: []Expect{{1, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(1, "unknown opcode: json_ref")}, }, { source: `byte "{\"key0\": 0,\"key1\": \"algo\",\"key2\":{\"key3\": \"teal\", \"key4\": {\"key40\": 10, \"key40\": \"should fail!\"}}}"; @@ -5703,7 +5703,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONString `, error: "error while parsing JSON text, invalid json text, duplicate keys not allowed", - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}, {5, "unknown opcode: json_ref"}, {7, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref"), exp(5, "unknown opcode: json_ref"), exp(7, "unknown opcode: json_ref")}, }, { source: `byte "[1,2,3]"; @@ -5711,7 +5711,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONUint64 `, error: "error while parsing JSON text, invalid json text, only json object is allowed", - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, { source: `byte "2"; @@ -5719,7 +5719,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONUint64 `, error: "error while parsing JSON text, invalid json text, only json object is allowed", - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, { source: `byte "null"; @@ -5727,7 +5727,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONUint64 `, error: "error while parsing JSON text, invalid json text, only json object is allowed", - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, { source: `byte "true"; @@ -5735,7 +5735,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONUint64 `, error: "error while parsing JSON text, invalid json text, only json object is allowed", - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, { source: `byte "\"sometext\""; @@ -5743,7 +5743,7 @@ func TestOpJSONRef(t *testing.T) { json_ref JSONUint64 `, error: "error while parsing JSON text, invalid json text, only json object is allowed", - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, { source: `byte "{noquotes: \"shouldn't work\"}"; @@ -5752,7 +5752,7 @@ func TestOpJSONRef(t *testing.T) { byte "shouldn't work"; ==`, error: "error while parsing JSON text, invalid json text", - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, // max uint64 + 1 should fail { @@ -5762,7 +5762,7 @@ func TestOpJSONRef(t *testing.T) { int 1; return`, error: "json: cannot unmarshal number 18446744073709551616 into Go value of type uint64", - previousVersErrors: []Expect{{3, "unknown opcode: json_ref"}}, + previousVersErrors: []expect{exp(3, "unknown opcode: json_ref")}, }, } diff --git a/data/transactions/logic/export_test.go b/data/transactions/logic/export_test.go index 44f90f0400..1a21d9ff15 100644 --- a/data/transactions/logic/export_test.go +++ b/data/transactions/logic/export_test.go @@ -24,10 +24,6 @@ import "github.com/algorand/go-algorand/data/basics" // we export some extra things to make testing easier there. But we do it in a // _test.go file, so they are only exported during testing. -func NewExpect(l int, s string) Expect { - return Expect{l, s} -} - func (ep *EvalParams) Reset() { ep.reset() } @@ -45,6 +41,7 @@ func (l *Ledger) DelBoxes(app basics.AppIndex, names ...string) { } var DefaultEvalParams = defaultEvalParams +var Exp = exp var MakeSampleEnv = makeSampleEnv var MakeSampleEnvWithVersion = makeSampleEnvWithVersion var MakeSampleTxn = makeSampleTxn diff --git a/data/transactions/logic/fields_test.go b/data/transactions/logic/fields_test.go index e0819e7073..bedb079079 100644 --- a/data/transactions/logic/fields_test.go +++ b/data/transactions/logic/fields_test.go @@ -232,7 +232,7 @@ func TestAssetParamsFieldsVersions(t *testing.T) { ledger.NewAsset(txn.Sender, 55, basics.AssetParams{}) ep.Proto.LogicSigVersion = v if field.version > v { - testProg(t, text, v, Expect{1, "...was introduced in..."}) + testProg(t, text, v, exp(1, "...was introduced in...")) ops := testProg(t, text, field.version) // assemble in the future ops.Program[0] = byte(v) testAppBytes(t, ops.Program, ep, "invalid asset_params_get field") @@ -282,7 +282,7 @@ func TestAcctParamsFieldsVersions(t *testing.T) { ledger.NewAccount(txn.Sender, 200_000) if field.version > v { // check assembler fails if version before introduction - testProg(t, text, v, Expect{1, "...was introduced in..."}) + testProg(t, text, v, exp(1, "...was introduced in...")) ops := testProg(t, text, field.version) // assemble in the future ops.Program[0] = byte(v) // but set version back to before intro if v < 6 { diff --git a/data/transactions/logic/frames_test.go b/data/transactions/logic/frames_test.go index c46a8dd848..63ff1c21c3 100644 --- a/data/transactions/logic/frames_test.go +++ b/data/transactions/logic/frames_test.go @@ -50,7 +50,7 @@ func TestDupPopN(t *testing.T) { testAccepts(t, "int 1; int 1; int 1; popn 2", fpVersion) testAccepts(t, "int 1; int 0; popn 1", fpVersion) testPanics(t, "int 1; int 0; popn 2", fpVersion) - testProg(t, "int 1; int 0; popn 3", LogicVersion, Expect{1, "popn 3 expects 3..."}) + testProg(t, "int 1; int 0; popn 3", LogicVersion, exp(1, "popn 3 expects 3...")) testPanics(t, notrack("int 1; int 0; popn 3"), fpVersion) testAccepts(t, `int 7; dupn 250; dupn 250; dupn 250; dupn 249; @@ -69,9 +69,9 @@ func TestDupPopNTyping(t *testing.T) { t.Parallel() testProg(t, "int 8; dupn 2; +; pop", LogicVersion) - testProg(t, "int 8; dupn 2; concat; pop", LogicVersion, Expect{1, "...wanted type []byte..."}) + testProg(t, "int 8; dupn 2; concat; pop", LogicVersion, exp(1, "...wanted type []byte...")) - testProg(t, "popn 1", LogicVersion, Expect{1, "...expects 1 stack argument..."}) + testProg(t, "popn 1", LogicVersion, exp(1, "...expects 1 stack argument...")) } func TestSimpleFrame(t *testing.T) { @@ -342,7 +342,7 @@ func TestFrameAccess(t *testing.T) { int 1 return ` - testProg(t, source, fpVersion, Expect{4, "frame_dig above stack"}) + testProg(t, source, fpVersion, exp(4, "frame_dig above stack")) testPanics(t, notrack(source), fpVersion, "frame_dig above stack") source = ` @@ -357,7 +357,7 @@ func TestFrameAccess(t *testing.T) { int 1 return ` - testProg(t, source, fpVersion, Expect{5, "frame_dig above stack"}) + testProg(t, source, fpVersion, exp(5, "frame_dig above stack")) testPanics(t, notrack(source), fpVersion, "frame_dig above stack") // Note that at the moment of frame_bury, the stack IS big enough, because @@ -376,7 +376,7 @@ func TestFrameAccess(t *testing.T) { int 1 return ` - testProg(t, source, fpVersion, Expect{6, "frame_bury above stack"}) + testProg(t, source, fpVersion, exp(6, "frame_bury above stack")) testPanics(t, notrack(source), fpVersion, "frame_bury above stack") } @@ -400,7 +400,7 @@ main: pop // argument popped frame_dig -1 // but then frame_dig used to get at it ` - testProg(t, source, fpVersion, Expect{7, "frame_dig above stack"}) + testProg(t, source, fpVersion, exp(7, "frame_dig above stack")) testPanics(t, notrack(source), fpVersion, "frame_dig above stack") testAccepts(t, ` @@ -427,7 +427,7 @@ main: frame_bury 1; retsub ` - testProg(t, source, fpVersion, Expect{8, "frame_dig above stack"}) + testProg(t, source, fpVersion, exp(8, "frame_dig above stack")) testPanics(t, notrack(source), fpVersion) } @@ -442,7 +442,7 @@ main: proto 1 1 frame_dig -10 // digging down below arguments ` - testProg(t, source, fpVersion, Expect{6, "frame_dig -10 in sub with 1 arg..."}) + testProg(t, source, fpVersion, exp(6, "frame_dig -10 in sub with 1 arg...")) testPanics(t, notrack(source), fpVersion, "frame_dig -10 in sub with 1 arg") testPanics(t, ` @@ -459,7 +459,7 @@ main: proto 1 15 frame_bury -10 // burying down below arguments ` - testProg(t, source, fpVersion, Expect{6, "frame_bury -10 in sub with 1 arg..."}) + testProg(t, source, fpVersion, exp(6, "frame_bury -10 in sub with 1 arg...")) testPanics(t, notrack(source), fpVersion, "frame_bury -10 in sub with 1 arg") // Without `proto`, frame_bury can't be checked by assembler, but still panics diff --git a/data/transactions/logic/resources.go b/data/transactions/logic/resources.go index 4db2d5d595..00045100ec 100644 --- a/data/transactions/logic/resources.go +++ b/data/transactions/logic/resources.go @@ -31,8 +31,8 @@ import ( type resources struct { // These resources were created previously in the group, so they can be used // by later transactions. - createdAsas []basics.AssetIndex - createdApps []basics.AppIndex + createdAsas map[basics.AssetIndex]struct{} + createdApps map[basics.AppIndex]struct{} // These resources have been used by some txn in the group, so they are // available. These maps track the availability of the basic objects (often @@ -101,6 +101,16 @@ func (r *resources) fill(tx *transactions.Transaction, ep *EvalParams) { } func (cx *EvalContext) allows(tx *transactions.Transaction, calleeVer uint64) error { + // if the caller is pre-sharing, it can't prepare transactions with + // resources that are not available, so `tx` is surely legal. + if cx.version < sharedResourcesVersion { + // this is important, not just an optimization, because a pre-sharing + // creation txn has access to the app and app account it is currently + // creating (and therefore can pass that access down), but cx.available + // doesn't track that properly until v9's protocol upgrade. See + // TestInnerAppCreateAndOptin for an example. + return nil + } switch tx.Type { case protocol.PaymentTx, protocol.KeyRegistrationTx, protocol.AssetConfigTx: // these transactions don't touch cross-product resources, so no error is possible @@ -110,7 +120,7 @@ func (cx *EvalContext) allows(tx *transactions.Transaction, calleeVer uint64) er case protocol.AssetFreezeTx: return cx.allowsAssetFreeze(&tx.Header, &tx.AssetFreezeTxnFields) case protocol.ApplicationCallTx: - return cx.allowsApplicationCall(&tx.Header, &tx.ApplicationCallTxnFields, cx.version, calleeVer) + return cx.allowsApplicationCall(&tx.Header, &tx.ApplicationCallTxnFields, calleeVer) default: return fmt.Errorf("unknown inner transaction type %s", tx.Type) } @@ -158,13 +168,11 @@ func (cx *EvalContext) allowsHolding(addr basics.Address, ai basics.AssetIndex) return true } // If an ASA was created in this group, then allow holding access for any allowed account. - for _, created := range r.createdAsas { - if created == ai { - return cx.availableAccount(addr) - } + if _, ok := r.createdAsas[ai]; ok { + return cx.availableAccount(addr) } // If the address was "created" by making its app in this group, then allow for available assets. - for _, created := range r.createdApps { + for created := range r.createdApps { if cx.getApplicationAddress(created) == addr { return cx.availableAsset(ai) } @@ -184,17 +192,15 @@ func (cx *EvalContext) allowsLocals(addr basics.Address, ai basics.AppIndex) boo return true } // All locals of created apps are available - for _, created := range r.createdApps { - if created == ai { - return cx.availableAccount(addr) - } + if _, ok := r.createdApps[ai]; ok { + return cx.availableAccount(addr) } if cx.txn.Txn.ApplicationID == 0 && cx.appID == ai { return cx.availableAccount(addr) } // All locals of created app accounts are available - for _, created := range r.createdApps { + for created := range r.createdApps { if cx.getApplicationAddress(created) == addr { return cx.availableApp(ai) } @@ -315,11 +321,10 @@ func (r *resources) fillApplicationCall(ep *EvalParams, hdr *transactions.Header } } -func (cx *EvalContext) allowsApplicationCall(hdr *transactions.Header, tx *transactions.ApplicationCallTxnFields, callerVer, calleeVer uint64) error { - // If an old (pre resource sharing) app is being called from an app that has - // resource sharing enabled, we need to confirm that no new "cross-product" - // resources have become available. - if callerVer < sharedResourcesVersion || calleeVer >= sharedResourcesVersion { +func (cx *EvalContext) allowsApplicationCall(hdr *transactions.Header, tx *transactions.ApplicationCallTxnFields, calleeVer uint64) error { + // If the callee is at least sharedResourcesVersion, then it will check + // availability properly itself. + if calleeVer >= sharedResourcesVersion { return nil } diff --git a/data/transactions/logic/resources_test.go b/data/transactions/logic/resources_test.go index c4aed20b71..4437f11837 100644 --- a/data/transactions/logic/resources_test.go +++ b/data/transactions/logic/resources_test.go @@ -62,7 +62,7 @@ func TestAppSharing(t *testing.T) { // In v8, the first tx can read app params of 500, because it's in its // foreign array, but the second can't logic.TestApps(t, []string{getSchema, getSchema}, txntest.Group(&appl0, &appl1), 8, nil, - logic.NewExpect(1, "unavailable App 500")) + logic.Exp(1, "unavailable App 500")) // In v9, the second can, because the first can. logic.TestApps(t, []string{getSchema, getSchema}, txntest.Group(&appl0, &appl1), 9, nil) @@ -73,7 +73,7 @@ func TestAppSharing(t *testing.T) { // app_local_get* requires the address and the app exist, else the program fails logic.TestApps(t, []string{getLocalEx, getLocalEx}, txntest.Group(&appl0, &appl1), 8, nil, - logic.NewExpect(0, "no account")) + logic.Exp(0, "no account")) _, _, ledger := logic.MakeSampleEnv() ledger.NewAccount(appl0.Sender, 100_000) @@ -82,42 +82,42 @@ func TestAppSharing(t *testing.T) { ledger.NewLocals(appl0.Sender, 500) // opt in // Now txn0 passes, but txn1 has an error because it can't see app 500 logic.TestApps(t, []string{getLocalEx, getLocalEx}, txntest.Group(&appl0, &appl1), 9, ledger, - logic.NewExpect(1, "unavailable Local State")) + logic.Exp(1, "unavailable Local State")) // But it's ok in appl2, because appl2 uses the same Sender, even though the // foreign-app is not repeated in appl2 because the holding being accessed // is the one from tx0. logic.TestApps(t, []string{getLocalEx, getLocalEx}, txntest.Group(&appl0, &appl2), 9, ledger) logic.TestApps(t, []string{getLocalEx, getLocalEx}, txntest.Group(&appl0, &appl2), 8, ledger, // version 8 does not get sharing - logic.NewExpect(1, "unavailable App 500")) + logic.Exp(1, "unavailable App 500")) // Checking if an account is opted in has pretty much the same rules optInCheck500 := "txn Sender; int 500; app_opted_in" // app_opted_in requires the address and the app exist, else the program fails logic.TestApps(t, []string{optInCheck500, optInCheck500}, txntest.Group(&appl0, &appl1), 9, nil, // nil ledger, no account - logic.NewExpect(0, "no account: "+appl0.Sender.String())) + logic.Exp(0, "no account: "+appl0.Sender.String())) // Now txn0 passes, but txn1 has an error because it can't see app 500 locals for appl1.Sender logic.TestApps(t, []string{optInCheck500, optInCheck500}, txntest.Group(&appl0, &appl1), 9, ledger, - logic.NewExpect(1, "unavailable Local State "+appl1.Sender.String())) + logic.Exp(1, "unavailable Local State "+appl1.Sender.String())) // But it's ok in appl2, because appl2 uses the same Sender, even though the // foreign-app is not repeated in appl2 because the holding being accessed // is the one from tx0. logic.TestApps(t, []string{optInCheck500, optInCheck500}, txntest.Group(&appl0, &appl2), 9, ledger) logic.TestApps(t, []string{optInCheck500, optInCheck500}, txntest.Group(&appl0, &appl2), 8, ledger, // version 8 does not get sharing - logic.NewExpect(1, "unavailable App 500")) + logic.Exp(1, "unavailable App 500")) // Confirm sharing applies to the app id called in tx0, not just foreign app array optInCheck900 := "txn Sender; int 900; app_opted_in; !" // we did not opt any senders into 900 // as above, appl1 can't see the local state, but appl2 can b/c sender is same as appl0 logic.TestApps(t, []string{optInCheck900, optInCheck900}, txntest.Group(&appl0, &appl1), 9, ledger, - logic.NewExpect(1, "unavailable Local State "+appl1.Sender.String())) + logic.Exp(1, "unavailable Local State "+appl1.Sender.String())) logic.TestApps(t, []string{optInCheck900, optInCheck900}, txntest.Group(&appl0, &appl2), 9, ledger) logic.TestApps(t, []string{optInCheck900, optInCheck900}, txntest.Group(&appl0, &appl2), 8, ledger, // v8=no sharing - logic.NewExpect(1, "unavailable App 900")) + logic.Exp(1, "unavailable App 900")) // Now, confirm that *setting* a local state in tx1 that was made available // in tx0 works. The extra check here is that the change is recorded @@ -128,7 +128,7 @@ func TestAppSharing(t *testing.T) { sources := []string{noop, putLocal} appl1.ApplicationArgs = [][]byte{appl0.Sender[:]} // tx1 will try to modify local state exposed in tx0 logic.TestApps(t, sources, txntest.Group(&appl0, &appl1), 9, ledger, - logic.NewExpect(1, "account "+appl0.Sender.String()+" is not opted into 901")) + logic.Exp(1, "account "+appl0.Sender.String()+" is not opted into 901")) ledger.NewLocals(appl0.Sender, 901) // opt in ep := logic.TestApps(t, sources, txntest.Group(&appl0, &appl1), 9, ledger) require.Len(t, ep.TxnGroup, 2) @@ -147,12 +147,12 @@ func TestAppSharing(t *testing.T) { // when running all three, appl2 can't read the locals of app in tx0 and addr in tx1 sources = []string{"", "", "gtxn 1 Sender; gtxn 0 Applications 0; byte 0xAA; app_local_get_ex"} logic.TestApps(t, sources, txntest.Group(&appl0, &appl1, &appl2), 9, nil, - logic.NewExpect(2, "unavailable Local State")) // note that the error message is for Locals, not specialized + logic.Exp(2, "unavailable Local State")) // note that the error message is for Locals, not specialized // same test of account in array of tx1 rather than Sender appl1.Accounts = []basics.Address{{7, 7}} sources = []string{"", "", "gtxn 1 Accounts 1; gtxn 0 Applications 0; byte 0xAA; app_local_get_ex"} logic.TestApps(t, sources, txntest.Group(&appl0, &appl1, &appl2), 9, nil, - logic.NewExpect(2, "unavailable Local State")) // note that the error message is for Locals, not specialized + logic.Exp(2, "unavailable Local State")) // note that the error message is for Locals, not specialized } // TestBetterLocalErrors confirms that we get specific errors about the missing @@ -223,7 +223,7 @@ func TestAssetSharing(t *testing.T) { // In v8, the first tx can read asset 400, because it's in its foreign array, // but the second can't logic.TestApps(t, []string{getTotal, getTotal}, txntest.Group(&appl0, &appl1), 8, nil, - logic.NewExpect(1, "unavailable Asset 400")) + logic.Exp(1, "unavailable Asset 400")) // In v9, the second can, because the first can. logic.TestApps(t, []string{getTotal, getTotal}, txntest.Group(&appl0, &appl1), 9, nil) @@ -232,9 +232,9 @@ func TestAssetSharing(t *testing.T) { // In contrast, here there's no help from v9, because the second tx is // reading a holding for a different account. logic.TestApps(t, []string{getBalance, getBalance}, txntest.Group(&appl0, &appl1), 8, nil, - logic.NewExpect(1, "unavailable Asset 400")) + logic.Exp(1, "unavailable Asset 400")) logic.TestApps(t, []string{getBalance, getBalance}, txntest.Group(&appl0, &appl1), 9, nil, - logic.NewExpect(1, "unavailable Holding")) + logic.Exp(1, "unavailable Holding")) // But it's ok in appl2, because the same account is used, even though the // foreign-asset is not repeated in appl2. logic.TestApps(t, []string{getBalance, getBalance}, txntest.Group(&appl0, &appl2), 9, nil) @@ -242,12 +242,12 @@ func TestAssetSharing(t *testing.T) { // when running all three, appl2 can't read the holding of asset in tx0 and addr in tx1 sources := []string{"", "", "gtxn 1 Sender; gtxn 0 Assets 0; asset_holding_get AssetBalance"} logic.TestApps(t, sources, txntest.Group(&appl0, &appl1, &appl2), 9, nil, - logic.NewExpect(2, "unavailable Holding")) // note that the error message is for Holding, not specialized + logic.Exp(2, "unavailable Holding")) // note that the error message is for Holding, not specialized // same test of account in array of tx1 rather than Sender appl1.Accounts = []basics.Address{{7, 7}} sources = []string{"", "", "gtxn 1 Accounts 1; gtxn 0 Assets 0; asset_holding_get AssetBalance"} logic.TestApps(t, sources, txntest.Group(&appl0, &appl1, &appl2), 9, nil, - logic.NewExpect(2, "unavailable Holding")) // note that the error message is for Holding, not specialized + logic.Exp(2, "unavailable Holding")) // note that the error message is for Holding, not specialized } // TestBetterHoldingErrors confirms that we get specific errors about the missing @@ -386,9 +386,9 @@ func TestOtherTxSharing(t *testing.T) { logic.TestApps(t, []string{senderBalance, ""}, txntest.Group(&appl, &send), 9, ledger) logic.TestApps(t, []string{"", senderBalance}, txntest.Group(&send, &appl), 8, ledger, - logic.NewExpect(1, "invalid Account reference")) + logic.Exp(1, "invalid Account reference")) logic.TestApps(t, []string{senderBalance, ""}, txntest.Group(&appl, &send), 8, ledger, - logic.NewExpect(0, "invalid Account reference")) + logic.Exp(0, "invalid Account reference")) } holdingAccess := ` @@ -401,11 +401,11 @@ func TestOtherTxSharing(t *testing.T) { t.Run("keyreg", func(t *testing.T) { appl.ApplicationArgs = [][]byte{senderAcct[:], {200}} logic.TestApps(t, []string{"", holdingAccess}, txntest.Group(&keyreg, &appl), 9, ledger, - logic.NewExpect(1, "unavailable Asset 200")) + logic.Exp(1, "unavailable Asset 200")) withRef := appl withRef.ForeignAssets = []basics.AssetIndex{200} logic.TestApps(t, []string{"", holdingAccess}, txntest.Group(&keyreg, &withRef), 9, ledger, - logic.NewExpect(1, "unavailable Holding "+senderAcct.String())) + logic.Exp(1, "unavailable Holding "+senderAcct.String())) }) t.Run("pay", func(t *testing.T) { // The receiver is available for algo balance reading @@ -415,7 +415,7 @@ func TestOtherTxSharing(t *testing.T) { // The other account is not (it's not even in the pay txn) appl.ApplicationArgs = [][]byte{otherAcct[:]} logic.TestApps(t, []string{"", otherBalance}, txntest.Group(&pay, &appl), 9, ledger, - logic.NewExpect(1, "invalid Account reference "+otherAcct.String())) + logic.Exp(1, "invalid Account reference "+otherAcct.String())) // The other account becomes accessible because used in CloseRemainderTo withClose := pay @@ -427,7 +427,7 @@ func TestOtherTxSharing(t *testing.T) { // The other account is not available even though it's all the extra addresses appl.ApplicationArgs = [][]byte{otherAcct[:]} logic.TestApps(t, []string{"", otherBalance}, txntest.Group(&acfg, &appl), 9, ledger, - logic.NewExpect(1, "invalid Account reference "+otherAcct.String())) + logic.Exp(1, "invalid Account reference "+otherAcct.String())) }) t.Run("axfer", func(t *testing.T) { @@ -454,9 +454,9 @@ func TestOtherTxSharing(t *testing.T) { // AssetCloseTo holding becomes available when set appl.ApplicationArgs = [][]byte{other2Acct[:], {byte(axfer.XferAsset)}} logic.TestApps(t, []string{"", other2Balance}, txntest.Group(&axfer, &appl), 9, ledger, - logic.NewExpect(1, "invalid Account reference "+other2Acct.String())) + logic.Exp(1, "invalid Account reference "+other2Acct.String())) logic.TestApps(t, []string{"", holdingAccess}, txntest.Group(&axfer, &appl), 9, ledger, - logic.NewExpect(1, "unavailable Account "+other2Acct.String())) + logic.Exp(1, "unavailable Account "+other2Acct.String())) withClose := axfer withClose.AssetCloseTo = other2Acct @@ -475,7 +475,7 @@ func TestOtherTxSharing(t *testing.T) { appl.ApplicationArgs = [][]byte{senderAcct[:], {byte(afrz.FreezeAsset)}} logic.TestApps(t, []string{"", senderBalance}, txntest.Group(&afrz, &appl), 9, ledger) logic.TestApps(t, []string{"", holdingAccess}, txntest.Group(&afrz, &appl), 9, ledger, - logic.NewExpect(1, "unavailable Holding "+senderAcct.String())) + logic.Exp(1, "unavailable Holding "+senderAcct.String())) }) } @@ -550,12 +550,12 @@ int 1 appl.ApplicationArgs = [][]byte{senderAcct[:]} logic.TestApps(t, []string{"", payToArg}, txntest.Group(&keyreg, &appl), 9, ledger) logic.TestApps(t, []string{"", payToArg}, txntest.Group(&keyreg, &appl), 8, ledger, - logic.NewExpect(1, "invalid Account reference "+senderAcct.String())) + logic.Exp(1, "invalid Account reference "+senderAcct.String())) // confirm you can't just pay _anybody_. receiverAcct is not in use at all. appl.ApplicationArgs = [][]byte{receiverAcct[:]} logic.TestApps(t, []string{"", payToArg}, txntest.Group(&keyreg, &appl), 9, ledger, - logic.NewExpect(1, "invalid Account reference "+receiverAcct.String())) + logic.Exp(1, "invalid Account reference "+receiverAcct.String())) }) t.Run("pay", func(t *testing.T) { @@ -569,17 +569,17 @@ int 1 appl.ApplicationArgs = [][]byte{senderAcct[:]} logic.TestApps(t, []string{"", payToArg}, txntest.Group(&pay, &appl), 9, ledger) logic.TestApps(t, []string{"", payToArg}, txntest.Group(&pay, &appl), 8, ledger, - logic.NewExpect(1, "invalid Account reference "+senderAcct.String())) + logic.Exp(1, "invalid Account reference "+senderAcct.String())) appl.ApplicationArgs = [][]byte{receiverAcct[:]} logic.TestApps(t, []string{"", payToArg}, txntest.Group(&pay, &appl), 9, ledger) logic.TestApps(t, []string{"", payToArg}, txntest.Group(&pay, &appl), 8, ledger, - logic.NewExpect(1, "invalid Account reference "+receiverAcct.String())) + logic.Exp(1, "invalid Account reference "+receiverAcct.String())) // confirm you can't just pay _anybody_. otherAcct is not in use at all. appl.ApplicationArgs = [][]byte{otherAcct[:]} logic.TestApps(t, []string{"", payToArg}, txntest.Group(&pay, &appl), 9, ledger, - logic.NewExpect(1, "invalid Account reference "+otherAcct.String())) + logic.Exp(1, "invalid Account reference "+otherAcct.String())) }) t.Run("axfer", func(t *testing.T) { @@ -595,20 +595,20 @@ int 1 appl.ApplicationArgs = [][]byte{senderAcct[:], {asa1}} logic.TestApps(t, []string{"", payToArg}, txntest.Group(&axfer, &appl), 9, ledger) logic.TestApps(t, []string{"", payToArg}, txntest.Group(&axfer, &appl), 8, ledger, - logic.NewExpect(1, "invalid Account reference "+senderAcct.String())) + logic.Exp(1, "invalid Account reference "+senderAcct.String())) // but can't axfer to sender, because appAcct doesn't have holding access for the asa logic.TestApps(t, []string{"", axferToArgs}, txntest.Group(&axfer, &appl), 9, ledger, - logic.NewExpect(1, "unavailable Holding")) + logic.Exp(1, "unavailable Holding")) // and to the receiver appl.ApplicationArgs = [][]byte{receiverAcct[:], {asa1}} logic.TestApps(t, []string{payToArg}, txntest.Group(&appl, &axfer), 9, ledger) logic.TestApps(t, []string{axferToArgs}, txntest.Group(&appl, &axfer), 9, ledger, - logic.NewExpect(0, "unavailable Holding")) + logic.Exp(0, "unavailable Holding")) // and to the clawback appl.ApplicationArgs = [][]byte{otherAcct[:], {asa1}} logic.TestApps(t, []string{"", payToArg}, txntest.Group(&axfer, &appl), 9, ledger) logic.TestApps(t, []string{"", axferToArgs}, txntest.Group(&axfer, &appl), 9, ledger, - logic.NewExpect(1, "unavailable Holding")) + logic.Exp(1, "unavailable Holding")) // Those axfers become possible by adding the asa to the appl's ForeignAssets appl.ForeignAssets = []basics.AssetIndex{asa1} @@ -622,18 +622,18 @@ int 1 // but can't axfer a different asset appl.ApplicationArgs = [][]byte{senderAcct[:], {asa2}} logic.TestApps(t, []string{"", axferToArgs}, txntest.Group(&axfer, &appl), 9, ledger, - logic.NewExpect(1, fmt.Sprintf("unavailable Asset %d", asa2))) + logic.Exp(1, fmt.Sprintf("unavailable Asset %d", asa2))) // or correct asset to an unknown address appl.ApplicationArgs = [][]byte{unusedAcct[:], {asa1}} logic.TestApps(t, []string{"", axferToArgs}, txntest.Group(&axfer, &appl), 9, ledger, - logic.NewExpect(1, "invalid Account reference")) + logic.Exp(1, "invalid Account reference")) // appl can acfg the asset from tx0 (which requires asset available, not holding) appl.ApplicationArgs = [][]byte{{asa1}} logic.TestApps(t, []string{"", acfgArg}, txntest.Group(&axfer, &appl), 9, ledger) appl.ApplicationArgs = [][]byte{{asa2}} // but not asa2 logic.TestApps(t, []string{"", acfgArg}, txntest.Group(&axfer, &appl), 9, ledger, - logic.NewExpect(1, fmt.Sprintf("unavailable Asset %d", asa2))) + logic.Exp(1, fmt.Sprintf("unavailable Asset %d", asa2))) // Now, confirm that access to account from a pay in one tx, and asa // from another don't allow inner axfer in the third (because there's no @@ -655,7 +655,7 @@ int 1 ledger.NewHolding(payAcct, asa1, 1, false) appl.ApplicationArgs = [][]byte{payAcct[:], {asa1}} logic.TestApps(t, []string{"", "", axferToArgs}, txntest.Group(&axfer, &pay, &appl), 9, ledger, - logic.NewExpect(2, "unavailable Holding "+payAcct.String())) + logic.Exp(2, "unavailable Holding "+payAcct.String())) }) t.Run("afrz", func(t *testing.T) { @@ -676,19 +676,19 @@ int 1 // can't axfer to the afrz sender because appAcct holding is not available from afrz appl.ApplicationArgs = [][]byte{senderAcct[:], {asa1}} logic.TestApps(t, []string{"", axferToArgs}, txntest.Group(&afrz, &appl), 9, ledger, - logic.NewExpect(1, "unavailable Holding "+appAcct.String())) + logic.Exp(1, "unavailable Holding "+appAcct.String())) appl.ForeignAssets = []basics.AssetIndex{asa1} // _still_ can't axfer to sender because afrz sender's holding does NOT // become available (not note that complaint is now about that account) logic.TestApps(t, []string{"", axferToArgs}, txntest.Group(&afrz, &appl), 9, ledger, - logic.NewExpect(1, "unavailable Holding "+senderAcct.String())) + logic.Exp(1, "unavailable Holding "+senderAcct.String())) // and not to the receiver which isn't in afrz appl.ApplicationArgs = [][]byte{receiverAcct[:], {asa1}} logic.TestApps(t, []string{payToArg}, txntest.Group(&appl, &afrz), 9, ledger, - logic.NewExpect(0, "invalid Account reference "+receiverAcct.String())) + logic.Exp(0, "invalid Account reference "+receiverAcct.String())) logic.TestApps(t, []string{axferToArgs}, txntest.Group(&appl, &afrz), 9, ledger, - logic.NewExpect(0, "invalid Account reference "+receiverAcct.String())) + logic.Exp(0, "invalid Account reference "+receiverAcct.String())) // otherAcct is the afrz target, it's holding and account are available appl.ApplicationArgs = [][]byte{otherAcct[:], {asa1}} @@ -698,11 +698,11 @@ int 1 // but still can't axfer a different asset appl.ApplicationArgs = [][]byte{otherAcct[:], {asa2}} logic.TestApps(t, []string{"", axferToArgs}, txntest.Group(&afrz, &appl), 9, ledger, - logic.NewExpect(1, fmt.Sprintf("unavailable Asset %d", asa2))) + logic.Exp(1, fmt.Sprintf("unavailable Asset %d", asa2))) appl.ForeignAssets = []basics.AssetIndex{asa2} // once added to appl's foreign array, the appl still lacks access to other's holding logic.TestApps(t, []string{"", axferToArgs}, txntest.Group(&afrz, &appl), 9, ledger, - logic.NewExpect(1, "unavailable Holding "+otherAcct.String())) + logic.Exp(1, "unavailable Holding "+otherAcct.String())) // appl can acfg the asset from tx0 (which requires asset available, not holding) appl.ForeignAssets = []basics.AssetIndex{} @@ -710,7 +710,7 @@ int 1 logic.TestApps(t, []string{"", acfgArg}, txntest.Group(&afrz, &appl), 9, ledger) appl.ApplicationArgs = [][]byte{{asa2}} // but not asa2 logic.TestApps(t, []string{"", acfgArg}, txntest.Group(&afrz, &appl), 9, ledger, - logic.NewExpect(1, fmt.Sprintf("unavailable Asset %d", asa2))) + logic.Exp(1, fmt.Sprintf("unavailable Asset %d", asa2))) }) @@ -728,10 +728,10 @@ int 1 appl.ApplicationArgs = [][]byte{otherAcct[:], {asa1}} logic.TestApps(t, []string{"", payToArg}, txntest.Group(&appl0, &appl), 9, ledger) logic.TestApps(t, []string{"", payToArg}, txntest.Group(&appl0, &appl), 8, ledger, // version 8 does not get sharing - logic.NewExpect(1, "invalid Account reference "+otherAcct.String())) + logic.Exp(1, "invalid Account reference "+otherAcct.String())) // appl can (almost) axfer asa1 to the otherAcct because both are in tx0 logic.TestApps(t, []string{"", axferToArgs}, txntest.Group(&appl0, &appl), 9, ledger, - logic.NewExpect(1, "axfer Sender: unavailable Holding")) + logic.Exp(1, "axfer Sender: unavailable Holding")) // but it can't take access it's OWN asa1, unless added to ForeignAssets appl.ForeignAssets = []basics.AssetIndex{asa1} logic.TestApps(t, []string{"", axferToArgs}, txntest.Group(&appl0, &appl), 9, ledger) @@ -741,11 +741,11 @@ int 1 // can't be used at all. appl.ApplicationArgs = [][]byte{otherAcct[:], {asa2}} logic.TestApps(t, []string{"", axferToArgs}, txntest.Group(&appl0, &appl), 9, ledger, - logic.NewExpect(1, "unavailable Asset 202")) + logic.Exp(1, "unavailable Asset 202")) // And adding asa2 does not fix this problem, because the other x 202 holding is unavailable appl.ForeignAssets = []basics.AssetIndex{asa2} logic.TestApps(t, []string{"", axferToArgs}, txntest.Group(&appl0, &appl), 9, ledger, - logic.NewExpect(1, "axfer AssetReceiver: unavailable Holding "+otherAcct.String()+" x 202")) + logic.Exp(1, "axfer AssetReceiver: unavailable Holding "+otherAcct.String()+" x 202")) // Now, conduct similar tests, but with the apps performing the // pays/axfers invoked from an outer app. Use various versions to check @@ -781,20 +781,20 @@ int 1 // when the inner program is v8, it can't perform the pay appl.ApplicationArgs = [][]byte{{88}, otherAcct[:], {asa1}} logic.TestApps(t, []string{"", innerCall}, txntest.Group(&appl0, &appl), 9, ledger, - logic.NewExpect(1, "invalid Account reference "+otherAcct.String())) + logic.Exp(1, "invalid Account reference "+otherAcct.String())) // unless the caller passes in the account, but it can't pass the // account because that also would give the called app access to the // passed account's local state (which isn't available to the caller) innerCallWithAccount := fmt.Sprintf(innerCallTemplate, "addr "+otherAcct.String()+"; itxn_field Accounts") logic.TestApps(t, []string{"", innerCallWithAccount}, txntest.Group(&appl0, &appl), 9, ledger, - logic.NewExpect(1, "appl ApplicationID: unavailable Local State "+otherAcct.String())) + logic.Exp(1, "appl ApplicationID: unavailable Local State "+otherAcct.String())) // the caller can't fix by passing 88 as a foreign app, because doing so // is not much different than the current situation: 88 is being called, // it's already available. innerCallWithBoth := fmt.Sprintf(innerCallTemplate, "addr "+otherAcct.String()+"; itxn_field Accounts; int 88; itxn_field Applications") logic.TestApps(t, []string{"", innerCallWithBoth}, txntest.Group(&appl0, &appl), 9, ledger, - logic.NewExpect(1, "appl ApplicationID: unavailable Local State "+otherAcct.String())) + logic.Exp(1, "appl ApplicationID: unavailable Local State "+otherAcct.String())) // the caller *can* do it if it originally had access to that 88 holding. appl0.ForeignApps = []basics.AppIndex{88} @@ -807,7 +807,7 @@ int 1 appl.ApplicationArgs = [][]byte{{11}, otherAcct[:], {asa1}} appl0.ForeignApps = []basics.AppIndex{11} logic.TestApps(t, []string{"", innerCallWithBoth}, txntest.Group(&appl0, &appl), 9, ledger, - logic.NewExpect(1, "appl ForeignApps: unavailable Local State "+otherAcct.String())) + logic.Exp(1, "appl ForeignApps: unavailable Local State "+otherAcct.String())) }) diff --git a/go.mod b/go.mod index cb5ce71426..f490570eb6 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,6 @@ require ( golang.org/x/sys v0.7.0 golang.org/x/text v0.9.0 gopkg.in/sohlich/elogrus.v3 v3.0.0-20180410122755-1fa29e2f2009 - gopkg.in/yaml.v3 v3.0.1 ) require ( @@ -72,4 +71,5 @@ require ( golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/ledger/apptxn_test.go b/ledger/apptxn_test.go index 28a5b10404..a2d7dba115 100644 --- a/ledger/apptxn_test.go +++ b/ledger/apptxn_test.go @@ -869,6 +869,156 @@ func TestInnerRekey(t *testing.T) { }) } +// TestInnerAppCreateAndOptin tests a weird way to create an app and opt it into +// an ASA all from one top-level transaction. Part of the trick is to use an +// inner helper app. The app being created rekeys itself to the inner app, +// which funds the outer app and opts it into the ASA. It could have worked +// differently - the inner app could have just funded the outer app, and then +// the outer app could have opted-in. But this technique tests something +// interesting, that the inner app can perform an opt-in on the outer app, which +// tests that the newly created app's holdings are available. In practice, the +// helper shold rekey it back, but we don't bother here. +func TestInnerAppCreateAndOptin(t *testing.T) { + partitiontest.PartitionTest(t) + t.Parallel() + + genBalances, addrs, _ := ledgertesting.NewTestGenesis() + + // v31 allows inner appl and inner rekey + ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) { + dl := NewDoubleLedger(t, genBalances, cv, cfg) + defer dl.Close() + + createasa := txntest.Txn{ + Type: "acfg", + Sender: addrs[0], + AssetParams: basics.AssetParams{Total: 2, UnitName: "$"}, + } + asaID := dl.txn(&createasa).ApplyData.ConfigAsset + require.NotZero(t, asaID) + + // helper app, is called during the creation of an app. When such an + // app is created, it rekeys itself to this helper and calls it. The + // helpers opts the caller into an ASA, and funds the MBR the caller + // needs for that optin. + helper := dl.fundedApp(addrs[0], 1_000_000, + main(` + itxn_begin + int axfer; itxn_field TypeEnum + int `+strconv.Itoa(int(asaID))+`; itxn_field XferAsset + txn Sender; itxn_field Sender // call as the caller! (works because of rekey by caller) + txn Sender; itxn_field AssetReceiver // 0 to self == opt-in + itxn_next + int pay; itxn_field TypeEnum // pay 200kmAlgo to the caller, for MBR + int 200000; itxn_field Amount + txn Sender; itxn_field Receiver + itxn_submit +`)) + // Don't use `main` here, we want to do the work during creation. Rekey + // to the helper and invoke it, trusting it to opt us into the ASA. + createapp := txntest.Txn{ + Type: "appl", + Sender: addrs[0], + Fee: 3 * 1000, // to pay for self, call to helper, and helper's axfer + ApprovalProgram: ` + itxn_begin + int appl; itxn_field TypeEnum + addr ` + helper.Address().String() + `; itxn_field RekeyTo + int ` + strconv.Itoa(int(helper)) + `; itxn_field ApplicationID + txn Assets 0; itxn_field Assets + itxn_submit + int 1 +`, + ForeignApps: []basics.AppIndex{helper}, + ForeignAssets: []basics.AssetIndex{asaID}, + } + appID := dl.txn(&createapp).ApplyData.ApplicationID + require.NotZero(t, appID) + }) +} + +// TestParentGlobals tests that a newly created app can call an inner app, and +// the inner app will have access to the parent globals, even if the originally +// created app ID isn't passed down, because the rule is that "pending" created +// apps are available, starting from v38 +func TestParentGlobals(t *testing.T) { + partitiontest.PartitionTest(t) + t.Parallel() + + genBalances, addrs, _ := ledgertesting.NewTestGenesis() + + // v38 allows parent access, but we start with v31 to make sure we don't mistakenly change it + ledgertesting.TestConsensusRange(t, 31, 0, func(t *testing.T, ver int, cv protocol.ConsensusVersion, cfg config.Local) { + dl := NewDoubleLedger(t, genBalances, cv, cfg) + defer dl.Close() + + // helper app, is called during the creation of an app. this app tries + // to access its parent's globals, by using `global CallerApplicationID` + helper := dl.fundedApp(addrs[0], 1_000_000, + main(` + global CallerApplicationID + byte "X" + app_global_get_ex; pop; pop; // we only care that it didn't panic +`)) + + // Don't use `main` here, we want to do the work during creation. + createProgram := ` + itxn_begin + int appl; itxn_field TypeEnum + int ` + strconv.Itoa(int(helper)) + `; itxn_field ApplicationID + itxn_submit + int 1 +` + createapp := txntest.Txn{ + Type: "appl", + Sender: addrs[0], + Fee: 2 * 1000, // to pay for self and call to helper + ApprovalProgram: createProgram, + ForeignApps: []basics.AppIndex{helper}, + } + var creator basics.AppIndex + if ver >= 38 { + creator = dl.txn(&createapp).ApplyData.ApplicationID + require.NotZero(t, creator) + } else { + dl.txn(&createapp, "unavailable App") + } + + // Now, test the same pattern, but do it all inside of yet another outer + // app, to show that the parent is available even if it was, itself + // created as an inner. To do so, we also need to get 0.2 MBR to the + // outer app, since it will be creating the "middle" app. + + outerAppAddress := (creator + 3).Address() // creator called an inner, so next is creator+2, then fund + outer := txntest.Txn{ + Type: "appl", + Sender: addrs[0], + Fee: 3 * 1000, // to pay for self, call to inner create, and its call to helper + ApprovalProgram: ` + itxn_begin + int appl; itxn_field TypeEnum + byte 0x` + hex.EncodeToString(createapp.SignedTxn().Txn.ApprovalProgram) + `; itxn_field ApprovalProgram + byte 0x` + hex.EncodeToString(createapp.SignedTxn().Txn.ClearStateProgram) + `; itxn_field ClearStateProgram + itxn_submit + int 1 +`, + ForeignApps: []basics.AppIndex{creator, helper}, + } + fund := txntest.Txn{ + Type: "pay", + Amount: 200_000, + Sender: addrs[0], + Receiver: outerAppAddress, + } + if ver >= 38 { + dl.txgroup("", &fund, &outer) + } else { + dl.txn(&createapp, "unavailable App") + } + + }) +} + func TestNote(t *testing.T) { partitiontest.PartitionTest(t) t.Parallel() diff --git a/ledger/double_test.go b/ledger/double_test.go index 1c53e54b09..16d38e7681 100644 --- a/ledger/double_test.go +++ b/ledger/double_test.go @@ -77,7 +77,10 @@ func (dl *DoubleLedger) txn(tx *txntest.Txn, problem ...string) (stib *transacti dl.eval = nil } else { vb := dl.endBlock() - stib = &vb.Block().Payset[0] + // It should have a stib, but don't panic here because of an earlier problem. + if len(vb.Block().Payset) > 0 { + stib = &vb.Block().Payset[0] + } } }() } diff --git a/scripts/configure_dev.sh b/scripts/configure_dev.sh index c1190bf5bd..df28dd5cc2 100755 --- a/scripts/configure_dev.sh +++ b/scripts/configure_dev.sh @@ -86,6 +86,7 @@ elif [ "${OS}" = "darwin" ]; then install_or_upgrade automake install_or_upgrade python3 install_or_upgrade lnav + install_or_upgrade diffutils lnav -i "$SCRIPTPATH/algorand_node_log.json" fi elif [ "${OS}" = "windows" ]; then diff --git a/scripts/get_golang_version.sh b/scripts/get_golang_version.sh index 4e3525a548..7036e716ae 100755 --- a/scripts/get_golang_version.sh +++ b/scripts/get_golang_version.sh @@ -4,7 +4,7 @@ # and parsed as an array to check against the system's golang version depending # upon the context in which the project is being built. # -# "dev" is to be used to satisfy the minium requirement we have to successfully +# "dev" is to be used to satisfy the minimum requirement we have to successfully # build the project. # # The default is to return the pinned version needed for our production builds. diff --git a/scripts/travis/codegen_verification.sh b/scripts/travis/codegen_verification.sh index 9ac11f1724..356b8444e8 100755 --- a/scripts/travis/codegen_verification.sh +++ b/scripts/travis/codegen_verification.sh @@ -61,5 +61,16 @@ else echo Enlistment is clean fi +echo Checking Tidiness... +make tidy +if [[ -n $(git status --porcelain) ]]; then + echo Dirty after go mod tidy - did you forget to run make tidy? + git status -s + git --no-pager diff + exit 1 +else + echo All tidy +fi + # test binary compatibility "${SCRIPTPATH}/../../test/platform/test_linux_amd64_compatibility.sh" diff --git a/tools/block-generator/README.md b/tools/block-generator/README.md index 4b2fd9b5a6..93e62d546f 100644 --- a/tools/block-generator/README.md +++ b/tools/block-generator/README.md @@ -5,6 +5,7 @@ This tool is used for testing Conduit import performance. It does this by genera ## Scenario Configuration Block generator uses a YAML config file to describe the composition of each randomly generated block. There are three levels of configuration: + 1. Setup 2. Transaction type distribution 3. Transaction type specific configuration @@ -12,7 +13,8 @@ Block generator uses a YAML config file to describe the composition of each rand At the time of writing, the block generator supports **payment** and **asset** transactions. The settings are hopefully, more or less, obvious. Distributions are specified as fractions of 1.0, and the sum of all options must add up to 1.0. Here is an example which uses all of the current options. Notice that the synthetic blocks are not required to follow algod limits, in this case the block size is specified as 19999: -``` + +```yml name: "Mixed (19,999)" genesis_accounts: 10000 genesis_account_balance: 1000000000000 @@ -37,6 +39,7 @@ asset_delete_fraction: 0 ## Modes The block generator can run in one of two _modes_: + 1. standalone **daemon** 2. test suite **runner** @@ -44,7 +47,8 @@ The block generator can run in one of two _modes_: In standalone daemon mode, a block-generator process starts and exposes the mock algod endpoints for **/genesis** and **/v2/blocks/{block}**. If you choose to query them manually, it only supports fetching blocks sequentially. This is due to the fact that it generates a pseudorandom stream of transactions and after each random transaction the state increments to the next. -Here is the help output for **daemon**: +Here is the help output for **daemon**: + ```bash ~$ ./block-generator daemon -h Start the generator daemon in standalone mode. @@ -60,12 +64,13 @@ Flags: ### runner -The runner mode is well suited for runing the same set of tests consistently across many scenarios and for different releases. The runner mode automates this process by starting the **daemon** with many different configurations, managing a postgres database, and running a separate Conduit process configured to use them. +The runner mode is well suited for running the same set of tests consistently across many scenarios and for different releases. The runner mode automates this process by starting the **daemon** with many different configurations, managing a postgres database, and running a separate Conduit process configured to use them. The results of the testing are written to the directory specified by the **--report-directory** option, and include many different metrics. In addition to the report, the Conduit log is written to this directory. The files are named according to the scenario file, and end in "report" or "log". Here is an example report from running with a test duration of "1h": -``` + +```json test_duration_seconds:3600 test_duration_actual_seconds:3600.056457 transaction_pay_total:30024226 @@ -95,6 +100,7 @@ final_uptime_seconds:3600.06 ``` Here is the help output for **runner**: + ```bash ~$ ./block-generator runner -h Run an automated test suite using the block-generator daemon and a provided conduit binary. Results are captured to a specified output directory. @@ -117,15 +123,17 @@ Flags: --validate If set the validator will run after test-duration has elapsed to verify data is correct. An extra line in each report indicates validator success or failure. ``` -## Example Scenario Run using Conduit and Postgres - `run_runner.sh` +## Example Run using Conduit and Postgres in **bash** via `run_runner.sh` A typical **runner** scenario involves: + * a [scenario configuration](#scenario-configuration) file, e.g. [test_config.yml](./test_config.yml) * access to a `conduit` binary to query the block generator's mock Algod endpoint and ingest the synthetic blocks * a datastore -such as a postgres database- to collect `conduit`'s output * a `conduit` config file to define its import/export behavior `run_runner.sh` makes the following choices for the previous bullet points: + * it can accept any scenario as its second argument, but defaults to [test_config.yml](./test_config.yml) when this isn't provided (this is a scenario with a lifetime of ~30 seconds) * knows how to import through a mock Algod running on port 11112 (which is the port the runner avails) * sets up a dockerized postgres database to receive conduit's output @@ -137,16 +145,17 @@ First you'll need to get a `conduit` binary. For example you can follow the [dev Assume you've navigated to the `tools/block-generator` directory of the `go-algorand` repo, and: + * saved the conduit binary to `tools/block-generator/conduit` * created a block generator scenario config at `tools/block-generator/scenario.yml` Then you can execute the following command to run the scenario: + ```sh ./run_runner.sh ./conduit scenario.yml ``` ### Scenario Report -If all goes well, the run will generate a directory `tools/block-generator/OUTPUT_RUN_RUNNER_TEST` and in that directory you can see the statistics -of the run in `scenario.report`. - +If all goes well, the run will generate a directory `tmp/OUTPUT_RUN_RUNNER_TEST` +and in that directory you can see the statisticsn of the run in `scenario.report`. diff --git a/tools/block-generator/generator/generate.go b/tools/block-generator/generator/generate.go index 8a619fa4dd..48df2b06c6 100644 --- a/tools/block-generator/generator/generate.go +++ b/tools/block-generator/generator/generate.go @@ -130,7 +130,7 @@ func MakeGenerator(dbround uint64, bkGenesis bookkeeping.Genesis, config Generat rewardsRate: 0, rewardsRecalculationRound: 0, reportData: make(map[TxTypeID]TxData), - nextdbround: dbround, + roundOffset: dbround, } gen.feeSink[31] = 1 @@ -242,8 +242,7 @@ type generator struct { // ledger ledger *ledger.Ledger - // next_account_round in the preloaded database - nextdbround uint64 + roundOffset uint64 } type assetData struct { @@ -286,7 +285,7 @@ func (g *generator) WriteReport(output io.Writer) error { func (g *generator) WriteStatus(output io.Writer) error { response := model.NodeStatusResponse{ - LastRound: g.round + g.nextdbround, + LastRound: g.round + g.roundOffset, } return json.NewEncoder(output).Encode(response) } @@ -378,24 +377,21 @@ func (g *generator) finishRound(txnCount uint64) { // WriteBlock generates a block full of new transactions and writes it to the writer. func (g *generator) WriteBlock(output io.Writer, round uint64) error { - if round < g.nextdbround { + if round < g.roundOffset { return fmt.Errorf("cannot generate block for round %d, already in database", round) } - if round-g.nextdbround != g.round { - return fmt.Errorf("generator only supports sequential block access. Expected %d but received request for %d", g.round+g.nextdbround, round) + if round-g.roundOffset != g.round { + return fmt.Errorf("generator only supports sequential block access. Expected %d but received request for %d", g.round+g.roundOffset, round) } numTxnForBlock := g.txnForRound(g.round) // return genesis block. offset round for non-empty database - if round-g.nextdbround == 0 { + if round-g.roundOffset == 0 { // write the msgpack bytes for a block - block, cert, _ := g.ledger.BlockCert(basics.Round(round - g.nextdbround)) + block, _, _ := g.ledger.BlockCert(basics.Round(round - g.roundOffset)) // return the block with the requested round number block.BlockHeader.Round = basics.Round(round) - encodedblock := rpcs.EncodedBlockCert{ - Block: block, - Certificate: cert, - } + encodedblock := rpcs.EncodedBlockCert{Block: block} blk := protocol.EncodeMsgp(&encodedblock) // write the msgpack bytes for a block _, err := output.Write(blk) @@ -478,8 +474,8 @@ func (g *generator) WriteBlock(output io.Writer, round uint64) error { // WriteDeltas generates returns the deltas for payset. func (g *generator) WriteDeltas(output io.Writer, round uint64) error { - // offset round for non-empty database - if round-g.nextdbround == 0 { + // the first generated round has no statedelta. + if round-g.roundOffset == 0 { data, _ := encode(protocol.CodecHandle, ledgercore.StateDelta{}) _, err := output.Write(data) if err != nil { @@ -487,7 +483,7 @@ func (g *generator) WriteDeltas(output io.Writer, round uint64) error { } return nil } - delta, err := g.ledger.GetStateDeltaForRound(basics.Round(round - g.nextdbround)) + delta, err := g.ledger.GetStateDeltaForRound(basics.Round(round - g.roundOffset)) if err != nil { return fmt.Errorf("err getting state delta for round %d: %w", round, err) } diff --git a/tools/block-generator/go.mod b/tools/block-generator/go.mod new file mode 100644 index 0000000000..306627f71b --- /dev/null +++ b/tools/block-generator/go.mod @@ -0,0 +1,50 @@ +module github.com/algorand/go-algorand/tools/block-generator + +replace github.com/algorand/go-algorand => ../.. + +go 1.17 + +require ( + github.com/algorand/go-algorand v0.0.0-00010101000000-000000000000 + github.com/algorand/go-codec/codec v1.1.9 + github.com/algorand/go-deadlock v0.2.2 + github.com/lib/pq v1.10.9 + github.com/spf13/cobra v1.7.0 + github.com/stretchr/testify v1.8.3 + gopkg.in/yaml.v3 v3.0.1 +) + +require ( + github.com/DataDog/zstd v1.5.2 // indirect + github.com/algorand/avm-abi v0.2.0 // indirect + github.com/algorand/falcon v0.0.0-20220727072124-02a2a64c4414 // indirect + github.com/algorand/go-sumhash v0.1.0 // indirect + github.com/algorand/msgp v1.1.53 // indirect + github.com/algorand/oapi-codegen v1.12.0-algorand.0 // indirect + github.com/algorand/websocket v1.4.6 // indirect + github.com/aws/aws-sdk-go v1.33.0 // indirect + github.com/consensys/gnark-crypto v0.7.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 // indirect + github.com/dchest/siphash v1.2.1 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/mux v1.8.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jmespath/go-jmespath v0.3.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-sqlite3 v1.10.0 // indirect + github.com/miekg/dns v1.1.41 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/olivere/elastic v6.2.14+incompatible // indirect + github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/crypto v0.1.0 // indirect + golang.org/x/net v0.9.0 // indirect + golang.org/x/sys v0.7.0 // 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 new file mode 100644 index 0000000000..bd2732c8fc --- /dev/null +++ b/tools/block-generator/go.sum @@ -0,0 +1,948 @@ +cloud.google.com/go v0.26.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.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +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.0.0-20220727072124-02a2a64c4414 h1:nwYN+GQ7Z5OOfZwqBO1ma7DSlP7S1YrKWICOyjkwqrc= +github.com/algorand/falcon v0.0.0-20220727072124-02a2a64c4414/go.mod h1:OkQyHlGvS0kLNcIWbC21/uQcnbfwSOQm+wiqWwBG9pQ= +github.com/algorand/go-codec/codec v1.1.9 h1:el4HFSPZhP+YCgOZxeFGB/BqlNkaUIs55xcALulUTCM= +github.com/algorand/go-codec/codec v1.1.9/go.mod h1:YkEx5nmr/zuCeaDYOIhlDg92Lxju8tj2d2NrYqP7g7k= +github.com/algorand/go-deadlock v0.2.2 h1:L7AKATSUCzoeVuOgpTipfCEjdUu5ECmlje8R7lP9DOY= +github.com/algorand/go-deadlock v0.2.2/go.mod h1:Hat1OXKqKNUcN/iv74FjGhF4hsOE2l7gOgQ9ZVIq6Fk= +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/graphtrace v0.1.0/go.mod h1:HscLQrzBdH1BH+5oehs3ICd8SYcXvnSL9BjfTu8WHCc= +github.com/algorand/msgp v1.1.53 h1:D6HKLyvLE6ltfsf8Apsrc+kqYb/CcOZEAfh1DpkPrNg= +github.com/algorand/msgp v1.1.53/go.mod h1:5K3d58/poT5fPmtiwuQft6GjgSrVEM46KoXdLrID8ZU= +github.com/algorand/oapi-codegen v1.12.0-algorand.0 h1:W9PvED+wAJc+9EeXPONnA+0zE9UhynEqoDs4OgAxKhk= +github.com/algorand/oapi-codegen v1.12.0-algorand.0/go.mod h1:tIWJ9K/qrLDVDt5A1p82UmxZIEGxv2X+uoujdhEAL48= +github.com/algorand/websocket v1.4.6 h1:I0kV4EYwatuUrKtNiwzYYgojgwh6pksDmlqntKG2Woc= +github.com/algorand/websocket v1.4.6/go.mod h1:HJmdGzFtnlUQ4nTzZP6WrT29oGYf1t6Ybi64vROcT+M= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aws/aws-sdk-go v1.33.0 h1:Bq5Y6VTLbfnJp1IV8EL/qUU5qO1DYHda/zis/sqevkY= +github.com/aws/aws-sdk-go v1.33.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chrismcguire/gobberish v0.0.0-20150821175641-1d8adb509a0e h1:CHPYEbz71w8DqJ7DRIq+MXyCQsdibK08vdcQTY4ufas= +github.com/chrismcguire/gobberish v0.0.0-20150821175641-1d8adb509a0e/go.mod h1:6Xhs0ZlsRjXLIiSMLKafbZxML/j30pg9Z1priLuha5s= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +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/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/consensys/bavard v0.1.10/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.7.0 h1:rwdy8+ssmLYRqKp+ryRRgQJl/rCq2uv+n83cOydm5UE= +github.com/consensys/gnark-crypto v0.7.0/go.mod h1:KPSuJzyxkJA8xZ/+CV47tyqkr9MmpZA3PXivK4VPrVg= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/daixiang0/gci v0.3.2/go.mod h1:jaASoJmv/ykO9dAAPy31iJnreV19248qKDdVWf3QgC4= +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-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0= +github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= +github.com/dchest/siphash v1.2.1 h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4= +github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE= +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/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/getkin/kin-openapi v0.107.0/go.mod h1:9Dhr+FasATJZjS4iOLvB0hkaxgYdulrNYm2e9epLWOo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= +github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= +github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.7.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +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.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +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.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/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.4.1/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.1/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.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= +github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= +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/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +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/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +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/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/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/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo= +github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= +github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ= +github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= +github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc= +github.com/lestrrat-go/jwx v1.2.25/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY= +github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/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/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= +github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +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/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +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/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= +github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/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/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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +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 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/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.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +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-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/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-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/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.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +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.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/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-20200222125558-5a598a2470a0/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-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/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-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +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-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +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-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20201207232520-09787c993a3a/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 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/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-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/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-20210616094352-59db8d763f22/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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/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-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +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.1.0/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/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +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= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +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.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +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= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +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.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +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.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +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.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/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/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.0/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= +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-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/tools/block-generator/run_postgres.sh b/tools/block-generator/run_postgres.sh index 4817961220..2c8175bb9c 100755 --- a/tools/block-generator/run_postgres.sh +++ b/tools/block-generator/run_postgres.sh @@ -5,7 +5,7 @@ # ./block-generator runner \ # -d 5s \ # -i \ -# -c "host=localhost user=algorand password=algorand dbname=algorand port=15432 sslmode=disable" \ +# -c "host=localhost user=algorand password=algorand dbname=generator_db port=15432 sslmode=disable" \ # -r results \ # -s scenarios/config.payment.small.yml @@ -28,7 +28,7 @@ function start_postgres() { -e POSTGRES_PASSWORD=algorand \ -e PGPASSWORD=algorand \ -p $POSTGRES_PORT:5432 \ - postgres + postgres:13-alpine sleep 5 @@ -42,8 +42,8 @@ function shutdown() { trap shutdown EXIT pushd $(dirname "$0") > /dev/null -echo "Starting postgres container at: \n\t\"host=localhost user=algorand password=algorand dbname=algorand port=15432\"" +echo "Starting postgres container at: \n\t\"host=localhost user=algorand password=algorand dbname=generator_db port=15432\"" start_postgres echo "Sleeping, use Ctrl-C to end test." -sleep 1000000000000000 +sleep 100000000 diff --git a/tools/block-generator/run_runner.sh b/tools/block-generator/run_runner.sh index 3c73035f32..5e83966318 100755 --- a/tools/block-generator/run_runner.sh +++ b/tools/block-generator/run_runner.sh @@ -4,6 +4,8 @@ set -e +OUTPUT=../../tmp/OUTPUT_RUN_RUNNER_TEST + CONDUIT_BINARY=$1 if [ -z "$CONDUIT_BINARY" ]; then echo "path to conduit binary is required" @@ -13,8 +15,8 @@ fi POSTGRES_CONTAINER=generator-test-container POSTGRES_PORT=15432 POSTGRES_DATABASE=generator_db -CONFIG=${4:-"$(dirname $0)/test_config.yml"} -echo "Using config file: $CONFIG" +SCENARIO=${2:-"$(dirname $0)/test_config.yml"} +echo "Using scenario config file: $SCENARIO" function start_postgres() { docker rm -f $POSTGRES_CONTAINER > /dev/null 2>&1 || true @@ -27,7 +29,7 @@ function start_postgres() { -e POSTGRES_PASSWORD=algorand \ -e PGPASSWORD=algorand \ -p $POSTGRES_PORT:5432 \ - postgres + postgres:13-alpine sleep 5 @@ -40,7 +42,7 @@ function shutdown() { trap shutdown EXIT -rm -rf OUTPUT_RUN_RUNNER_TEST > /dev/null 2>&1 +rm -rf $OUTPUT > /dev/null 2>&1 echo "Building generator." pushd $(dirname "$0") > /dev/null go build @@ -50,10 +52,9 @@ start_postgres echo "Starting test runner" $(dirname "$0")/block-generator runner \ --conduit-binary "$CONDUIT_BINARY" \ - --report-directory OUTPUT_RUN_RUNNER_TEST \ + --report-directory $OUTPUT \ --test-duration 30s \ --log-level trace \ --postgres-connection-string "host=localhost user=algorand password=algorand dbname=generator_db port=15432 sslmode=disable" \ - --scenario ${CONFIG} \ - --db-round ${2:-0} \ - --genesis-file ${3:-""} \ + --scenario ${SCENARIO} \ + --reset-db diff --git a/tools/block-generator/run_tests.sh b/tools/block-generator/run_tests.sh index 7916f45267..fcfc7279e0 100755 --- a/tools/block-generator/run_tests.sh +++ b/tools/block-generator/run_tests.sh @@ -93,5 +93,5 @@ echo "Log Level: $LOG_LEVEL" -c "$CONNECTION_STRING" \ --report-directory "$REPORT_DIR" \ --log-level "$LOG_LEVEL" \ - --reset + --reset-report-dir diff --git a/tools/block-generator/runner/run.go b/tools/block-generator/runner/run.go index 5e237bd660..2e1f970c5c 100644 --- a/tools/block-generator/runner/run.go +++ b/tools/block-generator/runner/run.go @@ -55,8 +55,8 @@ type Args struct { ResetReportDir bool RunValidation bool KeepDataDir bool - NextDBRound uint64 GenesisFile string + ResetDB bool } type config struct { @@ -122,17 +122,32 @@ func (r *Args) run() error { next.ServeHTTP(w, r) }) } + // get next db round + var nextRound uint64 + var err error + if r.ResetDB { + if err = util.EmptyDB(r.PostgresConnectionString); err != nil { + return fmt.Errorf("emptyDB err: %w", err) + } + nextRound = 0 + } else { + nextRound, err = util.GetNextRound(r.PostgresConnectionString) + if err != nil && err == util.ErrorNotInitialized { + nextRound = 0 + } else if err != nil { + return fmt.Errorf("getNextRound err: %w", err) + } + } // Start services algodNet := fmt.Sprintf("localhost:%d", 11112) metricsNet := fmt.Sprintf("localhost:%d", r.MetricsPort) - generatorShutdownFunc, _ := startGenerator(r.Path, r.NextDBRound, r.GenesisFile, algodNet, blockMiddleware) + generatorShutdownFunc, _ := startGenerator(r.Path, nextRound, r.GenesisFile, algodNet, blockMiddleware) defer func() { // Shutdown generator. if err := generatorShutdownFunc(); err != nil { fmt.Printf("failed to shutdown generator: %s\n", err) } }() - // get conduit config template t, err := template.New("conduit").Parse(conduitConfigTmpl) if err != nil { @@ -157,7 +172,7 @@ func (r *Args) run() error { } // Start conduit - conduitShutdownFunc, err := startConduit(dataDir, r.ConduitBinary, r.NextDBRound) + conduitShutdownFunc, err := startConduit(dataDir, r.ConduitBinary, nextRound) if err != nil { return fmt.Errorf("failed to start Conduit: %w", err) } diff --git a/tools/block-generator/runner/runner.go b/tools/block-generator/runner/runner.go index 580179a2e3..32598b9246 100644 --- a/tools/block-generator/runner/runner.go +++ b/tools/block-generator/runner/runner.go @@ -50,11 +50,11 @@ func init() { RunnerCmd.Flags().StringVarP(&runnerArgs.ReportDirectory, "report-directory", "r", "", "Location to place test reports.") RunnerCmd.Flags().StringVarP(&runnerArgs.LogLevel, "log-level", "l", "error", "LogLevel to use when starting Conduit. [panic, fatal, error, warn, info, debug, trace]") RunnerCmd.Flags().StringVarP(&runnerArgs.CPUProfilePath, "cpuprofile", "", "", "Path where Conduit writes its CPU profile.") - RunnerCmd.Flags().BoolVarP(&runnerArgs.ResetReportDir, "reset", "", false, "If set any existing report directory will be deleted before running tests.") + RunnerCmd.Flags().BoolVarP(&runnerArgs.ResetReportDir, "reset-report-dir", "", false, "If set any existing report directory will be deleted before running tests.") RunnerCmd.Flags().BoolVarP(&runnerArgs.RunValidation, "validate", "", false, "If set the validator will run after test-duration has elapsed to verify data is correct. An extra line in each report indicates validator success or failure.") RunnerCmd.Flags().BoolVarP(&runnerArgs.KeepDataDir, "keep-data-dir", "k", false, "If set the validator will not delete the data directory after tests complete.") - RunnerCmd.Flags().Uint64VarP(&runnerArgs.NextDBRound, "next-db-round", "n", 0, "next round on db. It is the next_account_round from Indexer's metastate table.") RunnerCmd.Flags().StringVarP(&runnerArgs.GenesisFile, "genesis-file", "f", "", "file path to the genesis associated with the db snapshot") + RunnerCmd.Flags().BoolVarP(&runnerArgs.ResetDB, "reset-db", "", false, "If set database will be deleted before running tests.") RunnerCmd.MarkFlagRequired("scenario") RunnerCmd.MarkFlagRequired("conduit-binary") diff --git a/tools/block-generator/scenarios/config.mixed.jumbo.yml b/tools/block-generator/scenarios/config.mixed.jumbo.yml index d02ee4045d..630ab8deec 100644 --- a/tools/block-generator/scenarios/config.mixed.jumbo.yml +++ b/tools/block-generator/scenarios/config.mixed.jumbo.yml @@ -1,7 +1,7 @@ name: "Mixed (jumbo)" genesis_accounts: 10000 genesis_account_balance: 1000000000000 -tx_per_block: 19999 +tx_per_block: 25000 # transaction distribution tx_pay_fraction: 0.3 diff --git a/tools/block-generator/scenarios/config.payment.full.yml b/tools/block-generator/scenarios/config.payment.full.yml index 22aa0e9701..8143c22bf4 100644 --- a/tools/block-generator/scenarios/config.payment.full.yml +++ b/tools/block-generator/scenarios/config.payment.full.yml @@ -1,6 +1,6 @@ name: "Pay (full)" -genesis_accounts: 10 -genesis_account_balance: 1000000000000000 +genesis_accounts: 10000 +genesis_account_balance: 1000000000000 tx_per_block: 5000 # transaction distribution diff --git a/tools/block-generator/scenarios/config.payment.jumbo.yml b/tools/block-generator/scenarios/config.payment.jumbo.yml index 2d1f0dba2f..23f0a92d66 100644 --- a/tools/block-generator/scenarios/config.payment.jumbo.yml +++ b/tools/block-generator/scenarios/config.payment.jumbo.yml @@ -1,7 +1,7 @@ name: "Pay (jumbo)" -genesis_accounts: 10 -genesis_account_balance: 1000000000000000 -tx_per_block: 19999 +genesis_accounts: 10000 +genesis_account_balance: 1000000000000 +tx_per_block: 25000 # transaction distribution tx_pay_fraction: 1.0 diff --git a/tools/block-generator/scenarios/config.payment.small.yml b/tools/block-generator/scenarios/config.payment.small.yml index e250b2f016..7f01232dbf 100644 --- a/tools/block-generator/scenarios/config.payment.small.yml +++ b/tools/block-generator/scenarios/config.payment.small.yml @@ -1,6 +1,6 @@ name: "Pay (small)" -genesis_accounts: 10 -genesis_account_balance: 1000000000000000 +genesis_accounts: 10000 +genesis_account_balance: 1000000000000 tx_per_block: 100 # transaction distribution diff --git a/tools/block-generator/util/util.go b/tools/block-generator/util/util.go index ad7c73baa5..b36fca9eeb 100644 --- a/tools/block-generator/util/util.go +++ b/tools/block-generator/util/util.go @@ -17,10 +17,19 @@ package util import ( + "database/sql" + "encoding/json" + "errors" "fmt" "os" + "strings" + // import postgres driver + _ "github.com/lib/pq" ) +// ErrorNotInitialized is returned when the database is not initialized. +var ErrorNotInitialized error = errors.New("database not initialized") + // MaybeFail exits if there was an error. func MaybeFail(err error, errfmt string, params ...interface{}) { if err == nil { @@ -30,3 +39,40 @@ func MaybeFail(err error, errfmt string, params ...interface{}) { fmt.Fprintf(os.Stderr, "\nError: %v\n", err) os.Exit(1) } + +// GetNextRound returns the next account round from the metastate table. +func GetNextRound(postgresConnectionString string) (uint64, error) { + conn, err := sql.Open("postgres", postgresConnectionString) + if err != nil { + return 0, fmt.Errorf("postgres connection string did not work: %w", err) + } + defer conn.Close() + query := `SELECT v FROM metastate WHERE k='state';` + var state []uint8 + if err = conn.QueryRow(query).Scan(&state); err != nil { + if strings.Contains(err.Error(), `relation "metastate" does not exist`) { + return 0, ErrorNotInitialized + } + return 0, fmt.Errorf("unable to get next db round: %w", err) + } + kv := make(map[string]uint64) + err = json.Unmarshal(state, &kv) + if err != nil { + return 0, fmt.Errorf("unable to get next account round: %w", err) + } + return kv["next_account_round"], nil +} + +// EmptyDB empties the database. +func EmptyDB(postgresConnectionString string) error { + conn, err := sql.Open("postgres", postgresConnectionString) + if err != nil { + return fmt.Errorf("postgres connection string did not work: %w", err) + } + defer conn.Close() + query := `DROP SCHEMA public CASCADE; CREATE SCHEMA public;` + if _, err = conn.Exec(query); err != nil { + return fmt.Errorf("unable to reset postgres DB: %w", err) + } + return nil +}