diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 023e926059..3ce911b5a0 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -45,7 +45,7 @@ jobs: cache: true - name: Build - run: make build + run: make -j8 build - name: Run benchmark on current branch run: | @@ -85,14 +85,14 @@ jobs: This branch with compared with the base branch ${{ github.event.pull_request.base.label }} commit ${{ github.event.pull_request.base.sha }} The command `for i in {1..N}; do go test ./... -run=XXX -bench=. -benchmem -shuffle=on; done` was used. Bench tests were run a total of ${{ steps.settings.outputs.benchmark_repetitions }} times on each branch. - +
Collapsed results for better readability

${{ env.BENCHSTAT }} - +

-
+ edit-mode: replace diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ffe55f37d..9601b694a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,10 +40,10 @@ jobs: cache: true - name: Build - run: make build + run: make -j8 build - name: Test - run: make test + run: make ci - name: Upload coverage report uses: codecov/codecov-action@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f3bedbed81..b51740600f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -57,7 +57,7 @@ jobs: - name: Run Tests run: | - make test + make ci make lint-github-actions - name: Config git diff --git a/Makefile b/Makefile index e954fbdd5f..5e588c85a1 100644 --- a/Makefile +++ b/Makefile @@ -29,32 +29,45 @@ ifneq ($(linters),) LINTERS = -E $(linters) endif +.PHONY: build +build: build-tools ./runtime/cmd/parse/parse ./runtime/cmd/parse/parse.wasm ./runtime/cmd/check/check ./runtime/cmd/main/main -.PHONY: test -test: +./runtime/cmd/parse/parse: + go build -o $@ ./runtime/cmd/parse + +./runtime/cmd/parse/parse.wasm: + GOARCH=wasm GOOS=js go build -o $@ ./runtime/cmd/parse + +./runtime/cmd/check/check: + go build -o $@ ./runtime/cmd/check + +./runtime/cmd/main/main: + go build -o $@ ./runtime/cmd/main + +.PHONY: build-tools +build-tools: build-analysis build-batch-script + +.PHONY: build-analysis +build-analysis: + (cd ./tools/analysis && go build .) + +.PHONY: build-batch-script +build-batch-script: + (cd ./tools/batch-script && go build .) + +.PHONY: ci +ci: # test all packages - GO111MODULE=on go test -coverprofile=coverage.txt -covermode=atomic -parallel 8 -race -coverpkg $(COVERPKGS) ./... + go test -coverprofile=coverage.txt -covermode=atomic -parallel 8 -race -coverpkg $(COVERPKGS) ./... + # run interpreter smoke tests. results from run above are reused, so no tests runs are duplicated + go test -count=5 ./runtime/tests/interpreter/... -runSmokeTests=true -validateAtree=false # remove coverage of empty functions from report sed -i -e 's/^.* 0 0$$//' coverage.txt -.PHONY: fast-test -fast-test: +.PHONY: test +test: # test all packages - GO111MODULE=on go test -parallel 8 ./... - -.PHONY: build -build: - go build -o ./runtime/cmd/parse/parse ./runtime/cmd/parse - GOARCH=wasm GOOS=js go build -o ./runtime/cmd/parse/parse.wasm ./runtime/cmd/parse - go build -o ./runtime/cmd/check/check ./runtime/cmd/check - go build -o ./runtime/cmd/main/main ./runtime/cmd/main - make build-tools - -.PHONY: build-tools -build-tools: - (cd ./tools/analysis && go build . && cd -) - (cd ./tools/batch-script && go build . && cd -) - (cd ./tools/constructorcheck && make plugin && cd -) + go test -parallel 8 ./... .PHONY: lint-github-actions lint-github-actions: build-linter @@ -64,7 +77,6 @@ lint-github-actions: build-linter lint: build-linter tools/golangci-lint/golangci-lint run $(LINTERS) --timeout=5m -v ./... - .PHONY: fix-lint fix-lint: build-linter tools/golangci-lint/golangci-lint run -v --fix --timeout=5m $(LINTERS) ./... @@ -73,13 +85,13 @@ fix-lint: build-linter build-linter: tools/golangci-lint/golangci-lint tools/maprange/maprange.so tools/unkeyed/unkeyed.so tools/constructorcheck/constructorcheck.so tools/maprange/maprange.so: - (cd tools/maprange && $(MAKE) plugin) + (cd tools/maprange && $(MAKE)) tools/unkeyed/unkeyed.so: - (cd tools/unkeyed && $(MAKE) plugin) + (cd tools/unkeyed && $(MAKE)) tools/constructorcheck/constructorcheck.so: - (cd tools/constructorcheck && $(MAKE) plugin) + (cd tools/constructorcheck && $(MAKE)) tools/golangci-lint/golangci-lint: (cd tools/golangci-lint && $(MAKE)) diff --git a/docs/images/create_release.png b/docs/images/create_release.png new file mode 100644 index 0000000000..586e83649d Binary files /dev/null and b/docs/images/create_release.png differ diff --git a/docs/images/release_action.png b/docs/images/release_action.png index d46e23a992..30a4559e40 100644 Binary files a/docs/images/release_action.png and b/docs/images/release_action.png differ diff --git a/docs/images/release_tag.png b/docs/images/release_tag.png new file mode 100644 index 0000000000..3330f27d2f Binary files /dev/null and b/docs/images/release_tag.png differ diff --git a/docs/language/accounts.mdx b/docs/language/accounts.mdx index 74a00e3f58..b70c84a58b 100644 --- a/docs/language/accounts.mdx +++ b/docs/language/accounts.mdx @@ -124,6 +124,7 @@ to the `prepare` phase of the transaction. fun borrow(from: StoragePath): T? fun link(_ newCapabilityPath: CapabilityPath, target: Path): Capability? + fun linkAccount(_ newCapabilityPath: PrivatePath): Capability<&AuthAccount>? fun getCapability(_ path: CapabilityPath): Capability fun getLinkTarget(_ path: CapabilityPath): Path? fun unlink(_ path: CapabilityPath) diff --git a/docs/language/attachments.md b/docs/language/attachments.md index 2e2c03c344..223e942741 100644 --- a/docs/language/attachments.md +++ b/docs/language/attachments.md @@ -4,7 +4,7 @@ title: Attachments ⚠️ This section describes a feature that is not yet released on Mainnet. -It will be available following the next Mainnet Spork. +It will be deployed to Testnet in its next major upgrade. Attachments are a feature of Cadence designed to allow developers to extend a struct or resource type diff --git a/docs/language/built-in-functions.mdx b/docs/language/built-in-functions.mdx index 8c1b87655e..52f18790f1 100644 --- a/docs/language/built-in-functions.mdx +++ b/docs/language/built-in-functions.mdx @@ -37,10 +37,30 @@ fun unsafeRandom(): UInt64 Returns a pseudo-random number. - NOTE: The use of this function is unsafe if not used correctly. + NOTE: + Smart contract developers should be mindful about the limitations of unsafeRandom. + The stream of random numbers produced is potentially unsafe in the following two regards: + + 1. The sequence of random numbers is potentially predictable by transactions within the same block + and by other smart contracts calling into your smart contract. + 2. A transaction calling into your smart contract can potentially bias the sequence of random numbers which + your smart contract internally generates. + + We are working towards removing these limitations incrementally. Once these points are addressed, + Flow’s randomness is safe and we will remove the "unsafe" qualifier. + + Nevertheless, there is an additional safety-relevant aspect that developers need to be mindful about: + + * A transaction can atomically revert all its action at any time. Therefore, it is possible for a transaction calling into + your smart contract to post-select favourable results and revert the transaction for unfavourable results. + ([example](https://consensys.github.io/smart-contract-best-practices/development-recommendations/general/public-data/)) + + This limitation is inherent to any smart contract platform that allows transactions to roll back atomically and cannot be + solved through safe randomness alone. Providing additional Cadence language primitives to simplify this challenge for + developers is on our roadmap as well. Nevertheless, with safe randomness (points 1 and 2 above resolved), developers can prevent + clients from post-select favourable outcomes using approaches such as described in the + [example](https://consensys.github.io/smart-contract-best-practices/development-recommendations/general/public-data/). - Follow [best practices](https://consensys.github.io/smart-contract-best-practices/development-recommendations/general/public-data/) - to prevent security issues when using this function. ## RLP diff --git a/docs/language/run-time-types.md b/docs/language/run-time-types.md index f0d8306902..45fca64450 100644 --- a/docs/language/run-time-types.md +++ b/docs/language/run-time-types.md @@ -93,7 +93,7 @@ fun InterfaceType(_ identifier: String): Type? fun RestrictedType(identifier: String?, restrictions: [String]): Type? ``` -Given a type identifer (as well as a list of identifiers for restricting interfaces +Given a type identifier (as well as a list of identifiers for restricting interfaces in the case of `RestrictedType`), these functions will look up nominal types and produce their run-time equivalents. If the provided identifiers do not correspond to any types, or (in the case of `RestrictedType`) the provided combination of diff --git a/docs/releasing.md b/docs/releasing.md index a1bd423c88..7edfcde625 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -1,6 +1,6 @@ # Release Process -Assume releasing Cadence version `v0.21.2` from `master` branch. +Assume releasing Cadence version `v0.21.2` from `master` branch. Also, assume the latest deployed version on the live networks is `v0.21.0`. ## Using GitHub Actions @@ -20,10 +20,10 @@ Check for breaking changes can be done using the [BackwardCompatibilityCheck](ht github action. - + Run the workflow by providing `master` as the `Current branch/tag` and `v0.21.0` which is the latest deployed version on the live networks, as the `Base branch/tag`. -Since the release would be based on the current master branch, the compatibility check would compare the current `master` +Since the release would be based on the current master branch, the compatibility check would compare the current `master` branch against `v0.21.0` branch/tag. @@ -129,3 +129,24 @@ If it is deemed that there are no breaking changes, proceed to the [Releasing](# ``` - Finally, open a PR from `release/v0.21.2` branch to the base branch (`master` in this case), to include the version bump changes. + + +## Creating a new GitHub release + +Once the PR which updates the version got merged, a GitHub release can be created. + +Go to the overview of all tags and select "Create release": + + + +On the release page, click the "Generate release notes" button: + + + +Edit the pre-populated description, e.g. by summarizing multiple PRs that contributed to a single feature, +as readers might not be and should not have to be familiar with the implementation details. + +By default, the new release is set as the latest release. +Usually this is the case, but uncheck this e.g. when releasing a bugfix release for an older version. + +Finally, click "Publish release", and you are all done! 🎉 diff --git a/encoding/json/decode.go b/encoding/json/decode.go index f6288deeb4..6ea90c3933 100644 --- a/encoding/json/decode.go +++ b/encoding/json/decode.go @@ -216,6 +216,8 @@ func (d *Decoder) decodeJSON(v any) cadence.Value { return d.decodeEvent(valueJSON) case contractTypeStr: return d.decodeContract(valueJSON) + case linkTypeStr: + return d.decodeLink(valueJSON) case pathTypeStr: return d.decodePath(valueJSON) case typeTypeStr: @@ -822,6 +824,29 @@ func (d *Decoder) decodeEnum(valueJSON any) cadence.Enum { )) } +func (d *Decoder) decodeLink(valueJSON any) cadence.PathLink { + obj := toObject(valueJSON) + + targetPath, ok := d.decodeJSON(obj.Get(targetPathKey)).(cadence.Path) + if !ok { + panic(errors.NewDefaultUserError("invalid link: missing or invalid target path")) + } + + borrowType := obj.GetString(borrowTypeKey) + + common.UseMemory(d.gauge, common.MemoryUsage{ + Kind: common.MemoryKindRawString, + // no need to add 1 to account for empty string: string is metered in Link struct + Amount: uint64(len(borrowType)), + }) + + return cadence.NewMeteredLink( + d.gauge, + targetPath, + borrowType, + ) +} + func (d *Decoder) decodePath(valueJSON any) cadence.Path { obj := toObject(valueJSON) diff --git a/encoding/json/encode.go b/encoding/json/encode.go index 7c72b49819..e58c51478e 100644 --- a/encoding/json/encode.go +++ b/encoding/json/encode.go @@ -126,6 +126,11 @@ type jsonCompositeField struct { Name string `json:"name"` } +type jsonPathLinkValue struct { + TargetPath jsonValue `json:"targetPath"` + BorrowType string `json:"borrowType"` +} + type jsonPathValue struct { Domain string `json:"domain"` Identifier string `json:"identifier"` @@ -239,6 +244,7 @@ const ( resourceTypeStr = "Resource" eventTypeStr = "Event" contractTypeStr = "Contract" + linkTypeStr = "Link" pathTypeStr = "Path" typeTypeStr = "Type" capabilityTypeStr = "Capability" @@ -314,6 +320,8 @@ func Prepare(v cadence.Value) jsonValue { return prepareEvent(x) case cadence.Contract: return prepareContract(x) + case cadence.PathLink: + return prepareLink(x) case cadence.Path: return preparePath(x) case cadence.TypeValue: @@ -593,6 +601,16 @@ func prepareComposite(kind, id string, fieldTypes []cadence.Field, fields []cade } } +func prepareLink(x cadence.PathLink) jsonValue { + return jsonValueObject{ + Type: linkTypeStr, + Value: jsonPathLinkValue{ + TargetPath: preparePath(x.TargetPath), + BorrowType: x.BorrowType, + }, + } +} + func preparePath(x cadence.Path) jsonValue { return jsonValueObject{ Type: pathTypeStr, diff --git a/encoding/json/encoding_test.go b/encoding/json/encoding_test.go index e4517493f0..f8c42b7fb5 100644 --- a/encoding/json/encoding_test.go +++ b/encoding/json/encoding_test.go @@ -1645,6 +1645,35 @@ func TestEncodeContract(t *testing.T) { testAllEncodeAndDecode(t, simpleContract, resourceContract) } +func TestEncodeLink(t *testing.T) { + + t.Parallel() + + testEncodeAndDecode( + t, + cadence.NewPathLink( + cadence.NewPath("storage", "foo"), + "Bar", + ), + // language=json + ` + { + "type": "Link", + "value": { + "targetPath": { + "type": "Path", + "value": { + "domain": "storage", + "identifier": "foo" + } + }, + "borrowType": "Bar" + } + } + `, + ) +} + func TestEncodeSimpleTypes(t *testing.T) { t.Parallel() @@ -2999,7 +3028,7 @@ func TestDecodeInvalidType(t *testing.T) { assert.Equal(t, "failed to decode JSON-Cadence value: invalid type ID for built-in: ``", err.Error()) }) - t.Run("undefined type", func(t *testing.T) { + t.Run("invalid type ID", func(t *testing.T) { t.Parallel() // language=json @@ -3007,14 +3036,14 @@ func TestDecodeInvalidType(t *testing.T) { { "type": "Struct", "value": { - "id": "I.Foo", + "id": "I", "fields": [] } } ` _, err := json.Decode(nil, []byte(encodedValue)) require.Error(t, err) - assert.Equal(t, "failed to decode JSON-Cadence value: invalid type ID `I.Foo`: invalid identifier location type ID: missing qualified identifier", err.Error()) + assert.Equal(t, "failed to decode JSON-Cadence value: invalid type ID `I`: invalid identifier location type ID: missing location", err.Error()) }) t.Run("unknown location prefix", func(t *testing.T) { diff --git a/go.mod b/go.mod index 04abf713bc..9f69b8797a 100644 --- a/go.mod +++ b/go.mod @@ -12,10 +12,10 @@ require ( github.com/k0kubun/pp v3.0.1+incompatible github.com/leanovate/gopter v0.2.9 github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 - github.com/onflow/atree v0.4.0 + github.com/onflow/atree v0.5.0 github.com/rivo/uniseg v0.2.1-0.20211004051800-57c86be7915a github.com/schollz/progressbar/v3 v3.8.3 - github.com/stretchr/testify v1.7.3 + github.com/stretchr/testify v1.8.1 github.com/tidwall/pretty v1.2.1 github.com/turbolent/prettier v0.0.0-20220320183459-661cc755135d go.opentelemetry.io/otel v1.8.0 diff --git a/go.sum b/go.sum index 8498bc011b..d07665e9f8 100644 --- a/go.sum +++ b/go.sum @@ -54,8 +54,8 @@ github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= -github.com/onflow/atree v0.4.0 h1:+TbNisavAkukAKhgQ4plWnvR9o5+SkwPIsi3jaeAqKs= -github.com/onflow/atree v0.4.0/go.mod h1:7Qe1xaW0YewvouLXrugzMFUYXNoRQ8MT/UsVAWx1Ndo= +github.com/onflow/atree v0.5.0 h1:y3lh8hY2fUo8KVE2ALVcz0EiNTq0tXJ6YTXKYVDA+3E= +github.com/onflow/atree v0.5.0/go.mod h1:gBHU0M05qCbv9NN0kijLWMgC47gHVNBIp4KmsVFi0tc= github.com/pkg/term v1.1.0 h1:xIAAdCMh3QIAy+5FrE8Ad8XoDhEU4ufwbaSozViP9kk= github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -67,13 +67,15 @@ github.com/schollz/progressbar/v3 v3.8.3 h1:FnLGl3ewlDUP+YdSwveXBaXs053Mem/du+wr github.com/schollz/progressbar/v3 v3.8.3/go.mod h1:pWnVCjSBZsT2X3nx9HfRdnCDrpbevliMeoEVhStwHko= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 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.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.3 h1:dAm0YRdRQlWojc3CrCRgPBzG5f941d0zvAKu7qY4e+I= -github.com/stretchr/testify v1.7.3/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/texttheater/golang-levenshtein/levenshtein v0.0.0-20200805054039-cae8b0eaed6c h1:HelZ2kAFadG0La9d+4htN4HzQ68Bm2iM9qKMSMES6xg= github.com/texttheater/golang-levenshtein/levenshtein v0.0.0-20200805054039-cae8b0eaed6c/go.mod h1:JlzghshsemAMDGZLytTFY8C1JQxQPhnatWqNwUXjggo= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= diff --git a/npm-packages/cadence-parser/package.json b/npm-packages/cadence-parser/package.json index 40b5906fbc..970092b0f6 100644 --- a/npm-packages/cadence-parser/package.json +++ b/npm-packages/cadence-parser/package.json @@ -1,6 +1,6 @@ { "name": "@onflow/cadence-parser", - "version": "0.35.0", + "version": "0.37.0", "description": "The Cadence parser", "homepage": "https://github.com/onflow/cadence", "repository": { diff --git a/runtime/account_test.go b/runtime/account_test.go index cd27af20ee..3adf6d918e 100644 --- a/runtime/account_test.go +++ b/runtime/account_test.go @@ -1466,7 +1466,7 @@ func TestRuntimePublicKey(t *testing.T) { publicKey: "0102".decodeHex(), signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 ) - + var publickeyRef = &publicKey.publicKey as &[UInt8] publickeyRef[0] = 3 @@ -1524,7 +1524,7 @@ func TestAuthAccountContracts(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{{42}}, nil }, - getAccountContractCode: func(address Address, name string) ([]byte, error) { + getAccountContractCode: func(_ common.AddressLocation) ([]byte, error) { invoked = true return []byte{1, 2}, nil }, @@ -1566,7 +1566,7 @@ func TestAuthAccountContracts(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{{42}}, nil }, - getAccountContractCode: func(address Address, name string) ([]byte, error) { + getAccountContractCode: func(_ common.AddressLocation) ([]byte, error) { invoked = true return nil, nil }, @@ -1605,18 +1605,10 @@ func TestAuthAccountContracts(t *testing.T) { return []Address{{0, 0, 0, 0, 0, 0, 0, 0x42}}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -1628,7 +1620,7 @@ func TestAuthAccountContracts(t *testing.T) { nextTransactionLocation := newTransactionLocationGenerator() - // Deploy contract interface + // Deploy contract interface err := rt.ExecuteTransaction( Script{ Source: DeploymentTransaction("HelloInterface", []byte(` @@ -1706,18 +1698,10 @@ func TestAuthAccountContracts(t *testing.T) { return []Address{{0, 0, 0, 0, 0, 0, 0, 0x42}}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -1729,7 +1713,7 @@ func TestAuthAccountContracts(t *testing.T) { nextTransactionLocation := newTransactionLocationGenerator() - // Deploy contract interface + // Deploy contract interface err := rt.ExecuteTransaction( Script{ Source: DeploymentTransaction("HelloInterface", []byte(` @@ -1798,7 +1782,7 @@ func TestAuthAccountContracts(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{{0, 0, 0, 0, 0, 0, 0, 0x42}}, nil }, - getAccountContractCode: func(address Address, name string) ([]byte, error) { + getAccountContractCode: func(_ common.AddressLocation) ([]byte, error) { return nil, nil }, } @@ -1970,7 +1954,7 @@ func TestPublicAccountContracts(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{{42}}, nil }, - getAccountContractCode: func(address Address, name string) ([]byte, error) { + getAccountContractCode: func(_ common.AddressLocation) ([]byte, error) { invoked = true return []byte{1, 2}, nil }, @@ -2026,7 +2010,7 @@ func TestPublicAccountContracts(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{{42}}, nil }, - getAccountContractCode: func(address Address, name string) ([]byte, error) { + getAccountContractCode: func(_ common.AddressLocation) ([]byte, error) { invoked = true return nil, nil }, @@ -2354,18 +2338,10 @@ func TestRuntimeAccountLink(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) (err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) (err error) { accountCodes[location] = code return nil }, @@ -2425,18 +2401,11 @@ func TestRuntimeAccountLink(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) (err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) (err error) { accountCodes[location] = code return nil }, @@ -2452,7 +2421,7 @@ func TestRuntimeAccountLink(t *testing.T) { setupTransaction := []byte(` transaction { prepare(acct: AuthAccount) { - acct.linkAccount(/public/foo) + acct.linkAccount(/private/foo) } } `) @@ -2468,10 +2437,11 @@ func TestRuntimeAccountLink(t *testing.T) { ) require.Error(t, err) - assert.ErrorContains(t, err, "value of type `AuthAccount` has no member `linkAccount`") + var accountLinkingForbiddenErr interpreter.AccountLinkingForbiddenError + assert.ErrorAs(t, err, &accountLinkingForbiddenErr) }) - t.Run("enabled, pragma", func(t *testing.T) { + t.Run("publish and claim", func(t *testing.T) { t.Parallel() @@ -2485,6 +2455,7 @@ func TestRuntimeAccountLink(t *testing.T) { accountCodes := map[Location][]byte{} var logs []string + var events []cadence.Event signerAccount := address1 @@ -2497,24 +2468,20 @@ func TestRuntimeAccountLink(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) (err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) (err error) { accountCodes[location] = code return nil }, log: func(message string) { logs = append(logs, message) }, + emitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, } nextTransactionLocation := newTransactionLocationGenerator() @@ -2526,7 +2493,8 @@ func TestRuntimeAccountLink(t *testing.T) { transaction { prepare(acct: AuthAccount) { - acct.linkAccount(/public/foo) + let cap = acct.linkAccount(/private/foo)! + log(acct.inbox.publish(cap, name: "foo", recipient: 0x2)) } } `) @@ -2544,14 +2512,32 @@ func TestRuntimeAccountLink(t *testing.T) { ) require.NoError(t, err) - // Access + require.Len(t, events, 2) + + require.Equal(t, + string(stdlib.AccountLinkedEventType.ID()), + events[0].EventType.ID(), + ) + require.Equal(t, + []cadence.Value{ + cadence.NewAddress(common.MustBytesToAddress([]byte{0x1})), + cadence.NewPath("private", "foo"), + }, + events[0].Fields, + ) + + require.Equal(t, + string(stdlib.AccountInboxPublishedEventType.ID()), + events[1].EventType.ID(), + ) + + // Claim accessTransaction := []byte(` transaction { prepare(acct: AuthAccount) { - let ref = getAccount(0x1) - .getCapability<&AuthAccount>(/public/foo) - .borrow()! + let cap = acct.inbox.claim<&AuthAccount>("foo", provider: 0x1)! + let ref = cap.borrow()! log(ref.address) } } @@ -2571,12 +2557,12 @@ func TestRuntimeAccountLink(t *testing.T) { require.NoError(t, err) require.Equal(t, - []string{"0x0000000000000001"}, + []string{"()", "0x0000000000000001"}, logs, ) }) - t.Run("publish and claim", func(t *testing.T) { + t.Run("enabled, contract, missing pragma", func(t *testing.T) { t.Parallel() @@ -2585,14 +2571,13 @@ func TestRuntimeAccountLink(t *testing.T) { AccountLinkingEnabled: true, }) - address1 := common.MustBytesToAddress([]byte{0x1}) - address2 := common.MustBytesToAddress([]byte{0x2}) + address := common.MustBytesToAddress([]byte{0x1}) accountCodes := map[Location][]byte{} var logs []string var events []cadence.Event - signerAccount := address1 + signerAccount := address runtimeInterface := &testRuntimeInterface{ getCode: func(location Location) (bytes []byte, err error) { @@ -2603,18 +2588,10 @@ func TestRuntimeAccountLink(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) (err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) (err error) { accountCodes[location] = code return nil }, @@ -2629,24 +2606,118 @@ func TestRuntimeAccountLink(t *testing.T) { nextTransactionLocation := newTransactionLocationGenerator() + // Deploy contract + err := runtime.ExecuteTransaction( + Script{ + Source: DeploymentTransaction( + "AccountLinker", + []byte(` + // should have no influence + #allowAccountLinking + + pub contract AccountLinker { + + pub fun link(_ account: AuthAccount) { + account.linkAccount(/private/foo) + } + } + `, + ), + ), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + // Set up account setupTransaction := []byte(` - #allowAccountLinking + import AccountLinker from 0x1 transaction { - prepare(acct: AuthAccount) { - let cap = acct.linkAccount(/private/foo)! - log(acct.inbox.publish(cap, name: "foo", recipient: 0x2)) + prepare(signer: AuthAccount) { + AccountLinker.link(signer) } } `) - signerAccount = address1 + err = runtime.ExecuteTransaction( + Script{ + Source: setupTransaction, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.Error(t, err) + + var accountLinkingForbiddenErr interpreter.AccountLinkingForbiddenError + assert.ErrorAs(t, err, &accountLinkingForbiddenErr) + }) + + t.Run("enabled, contract, pragma in tx", func(t *testing.T) { + + t.Parallel() + + runtime := NewInterpreterRuntime(Config{ + AtreeValidationEnabled: true, + AccountLinkingEnabled: true, + }) + + address := common.MustBytesToAddress([]byte{0x1}) + + accountCodes := map[Location][]byte{} + var logs []string + var events []cadence.Event + + signerAccount := address + + runtimeInterface := &testRuntimeInterface{ + getCode: func(location Location) (bytes []byte, err error) { + return accountCodes[location], nil + }, + storage: newTestLedger(nil, nil), + getSigningAccounts: func() ([]Address, error) { + return []Address{signerAccount}, nil + }, + resolveLocation: singleIdentifierLocationResolver(t), + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + return accountCodes[location], nil + }, + updateAccountContractCode: func(location common.AddressLocation, code []byte) (err error) { + accountCodes[location] = code + return nil + }, + log: func(message string) { + logs = append(logs, message) + }, + emitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + } + + nextTransactionLocation := newTransactionLocationGenerator() + // Deploy contract err := runtime.ExecuteTransaction( Script{ - Source: setupTransaction, + Source: DeploymentTransaction( + "AccountLinker", + []byte(` + pub contract AccountLinker { + + pub fun link(_ account: AuthAccount) { + account.linkAccount(/private/foo) + } + } + `, + ), + ), }, Context{ Interface: runtimeInterface, @@ -2655,23 +2726,25 @@ func TestRuntimeAccountLink(t *testing.T) { ) require.NoError(t, err) - // Claim + // Set up account + + setupTransaction := []byte(` + #allowAccountLinking + + import AccountLinker from 0x1 - accessTransaction := []byte(` transaction { - prepare(acct: AuthAccount) { - let cap = acct.inbox.claim<&AuthAccount>("foo", provider: 0x1)! - let ref = cap.borrow()! - log(ref.address) + prepare(signer: AuthAccount) { + AccountLinker.link(signer) } } `) - signerAccount = address2 + events = nil err = runtime.ExecuteTransaction( Script{ - Source: accessTransaction, + Source: setupTransaction, }, Context{ Interface: runtimeInterface, @@ -2680,9 +2753,126 @@ func TestRuntimeAccountLink(t *testing.T) { ) require.NoError(t, err) + require.Len(t, events, 1) + require.Equal(t, - []string{"()", "0x0000000000000001"}, - logs, + string(stdlib.AccountLinkedEventType.ID()), + events[0].EventType.ID(), + ) + require.Equal(t, + []cadence.Value{ + cadence.NewAddress(common.MustBytesToAddress([]byte{0x1})), + cadence.NewPath("private", "foo"), + }, + events[0].Fields, ) }) + + t.Run("enabled, contract, pragma in script", func(t *testing.T) { + + t.Parallel() + + runtime := NewInterpreterRuntime(Config{ + AtreeValidationEnabled: true, + AccountLinkingEnabled: true, + }) + + address := common.MustBytesToAddress([]byte{0x1}) + + accountCodes := map[Location][]byte{} + var logs []string + var events []cadence.Event + + signerAccount := address + + runtimeInterface := &testRuntimeInterface{ + getCode: func(location Location) (bytes []byte, err error) { + return accountCodes[location], nil + }, + storage: newTestLedger(nil, nil), + getSigningAccounts: func() ([]Address, error) { + return []Address{signerAccount}, nil + }, + resolveLocation: singleIdentifierLocationResolver(t), + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + return accountCodes[location], nil + }, + updateAccountContractCode: func(location common.AddressLocation, code []byte) (err error) { + accountCodes[location] = code + return nil + }, + log: func(message string) { + logs = append(logs, message) + }, + emitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + } + + nextTransactionLocation := newTransactionLocationGenerator() + + // Deploy contract + err := runtime.ExecuteTransaction( + Script{ + Source: DeploymentTransaction( + "AccountLinker", + []byte(` + pub contract AccountLinker { + + pub fun link(_ account: AuthAccount) { + account.linkAccount(/private/foo) + } + } + `, + ), + ), + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // Set up account + + setupTransaction := []byte(` + #allowAccountLinking + + import AccountLinker from 0x1 + + pub fun main() { + AccountLinker.link(getAuthAccount(0x1)) + } + `) + + events = nil + + _, err = runtime.ExecuteScript( + Script{ + Source: setupTransaction, + }, + Context{ + Interface: runtimeInterface, + Location: common.ScriptLocation{}, + }, + ) + require.NoError(t, err) + + require.Len(t, events, 1) + + require.Equal(t, + string(stdlib.AccountLinkedEventType.ID()), + events[0].EventType.ID(), + ) + require.Equal(t, + []cadence.Value{ + cadence.NewAddress(common.MustBytesToAddress([]byte{0x1})), + cadence.NewPath("private", "foo"), + }, + events[0].Fields, + ) + }) + } diff --git a/runtime/attachments_test.go b/runtime/attachments_test.go index 6ded7869b1..8a5cadfaac 100644 --- a/runtime/attachments_test.go +++ b/runtime/attachments_test.go @@ -98,19 +98,11 @@ func TestAccountAttachmentSaveAndLoad(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{[8]byte{0, 0, 0, 0, 0, 0, 0, 1}}, nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, @@ -197,19 +189,11 @@ func TestAccountAttachmentExportFailure(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{[8]byte{0, 0, 0, 0, 0, 0, 0, 1}}, nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, @@ -287,19 +271,11 @@ func TestAccountAttachmentExport(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{[8]byte{0, 0, 0, 0, 0, 0, 0, 1}}, nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, @@ -374,19 +350,11 @@ func TestAccountAttachedExport(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{[8]byte{0, 0, 0, 0, 0, 0, 0, 1}}, nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, @@ -489,19 +457,11 @@ func TestAccountAttachmentSaveAndBorrow(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{[8]byte{0, 0, 0, 0, 0, 0, 0, 1}}, nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, @@ -613,19 +573,11 @@ func TestAccountAttachmentCapability(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{[8]byte{0, 0, 0, 0, 0, 0, 0, 1}}, nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, @@ -644,19 +596,11 @@ func TestAccountAttachmentCapability(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{[8]byte{0, 0, 0, 0, 0, 0, 0, 2}}, nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, diff --git a/runtime/common/addresslocation.go b/runtime/common/addresslocation.go index 5b13c16f7e..f283f87078 100644 --- a/runtime/common/addresslocation.go +++ b/runtime/common/addresslocation.go @@ -85,6 +85,10 @@ func (l AddressLocation) Description() string { ) } +func (l AddressLocation) ID() string { + return fmt.Sprintf("%s.%s", AddressLocationPrefix, l) +} + func (l AddressLocation) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Type string @@ -140,9 +144,7 @@ func decodeAddressLocationTypeID(gauge MemoryGauge, typeID string) (AddressLocat panic(errors.NewUnreachableError()) case 1: return newError("missing location") - case 2: - return newError("missing qualified identifier") - case 3, 4: + case 2, 3, 4: break default: // strings.SplitN will never return more than 4 parts @@ -177,6 +179,11 @@ func decodeAddressLocationTypeID(gauge MemoryGauge, typeID string) (AddressLocat var qualifiedIdentifier string switch partCount { + case 2: + // If there are only 2 parts, + // then `` is empty, + // and both the contract name and the qualified identifier are empty (default)s + case 3: // If there are only 3 parts, // then `` is both the contract name and the qualified identifier. diff --git a/runtime/common/addresslocation_test.go b/runtime/common/addresslocation_test.go index 9337e15ed0..fdea7c4087 100644 --- a/runtime/common/addresslocation_test.go +++ b/runtime/common/addresslocation_test.go @@ -65,6 +65,19 @@ func TestAddressLocationTypeID(t *testing.T) { ) } +func TestAddressLocationID(t *testing.T) { + + t.Parallel() + + location, _, err := decodeAddressLocationTypeID(nil, "A.0000000000000001.Bar.Baz") + require.NoError(t, err) + + assert.Equal(t, + "A.0000000000000001.Bar", + location.ID(), + ) +} + func TestDecodeAddressLocationTypeID(t *testing.T) { t.Parallel() @@ -85,12 +98,38 @@ func TestDecodeAddressLocationTypeID(t *testing.T) { require.EqualError(t, err, "invalid address location type ID: missing location") }) - t.Run("missing qualified identifier", func(t *testing.T) { + t.Run("missing qualified identifier part", func(t *testing.T) { + + t.Parallel() + + location, qualifiedIdentifier, err := decodeAddressLocationTypeID(nil, "A.0000000000000001") + require.NoError(t, err) + + assert.Equal(t, + AddressLocation{ + Address: MustBytesToAddress([]byte{1}), + Name: "", + }, + location, + ) + assert.Equal(t, "", qualifiedIdentifier) + }) + + t.Run("empty qualified identifier", func(t *testing.T) { t.Parallel() - _, _, err := decodeAddressLocationTypeID(nil, "A.0000000000000001") - require.EqualError(t, err, "invalid address location type ID: missing qualified identifier") + location, qualifiedIdentifier, err := decodeAddressLocationTypeID(nil, "A.0000000000000001.") + require.NoError(t, err) + + assert.Equal(t, + AddressLocation{ + Address: MustBytesToAddress([]byte{1}), + Name: "", + }, + location, + ) + assert.Equal(t, "", qualifiedIdentifier) }) t.Run("invalid prefix", func(t *testing.T) { diff --git a/runtime/common/computationkind.go b/runtime/common/computationkind.go index cf02d9f80a..90b96e858e 100644 --- a/runtime/common/computationkind.go +++ b/runtime/common/computationkind.go @@ -109,7 +109,7 @@ const ( _ _ _ - _ + ComputationKindEncodeValue _ _ _ diff --git a/runtime/common/computationkind_string.go b/runtime/common/computationkind_string.go index 37dfb948d2..9ed621d72f 100644 --- a/runtime/common/computationkind_string.go +++ b/runtime/common/computationkind_string.go @@ -21,6 +21,7 @@ func _() { _ = x[ComputationKindCreateDictionaryValue-1040] _ = x[ComputationKindTransferDictionaryValue-1041] _ = x[ComputationKindDestroyDictionaryValue-1042] + _ = x[ComputationKindEncodeValue-1080] _ = x[ComputationKindSTDLIBPanic-1100] _ = x[ComputationKindSTDLIBAssert-1101] _ = x[ComputationKindSTDLIBUnsafeRandom-1102] @@ -34,8 +35,9 @@ const ( _ComputationKind_name_2 = "CreateCompositeValueTransferCompositeValueDestroyCompositeValue" _ComputationKind_name_3 = "CreateArrayValueTransferArrayValueDestroyArrayValue" _ComputationKind_name_4 = "CreateDictionaryValueTransferDictionaryValueDestroyDictionaryValue" - _ComputationKind_name_5 = "STDLIBPanicSTDLIBAssertSTDLIBUnsafeRandom" - _ComputationKind_name_6 = "STDLIBRLPDecodeStringSTDLIBRLPDecodeList" + _ComputationKind_name_5 = "EncodeValue" + _ComputationKind_name_6 = "STDLIBPanicSTDLIBAssertSTDLIBUnsafeRandom" + _ComputationKind_name_7 = "STDLIBRLPDecodeStringSTDLIBRLPDecodeList" ) var ( @@ -43,8 +45,8 @@ var ( _ComputationKind_index_2 = [...]uint8{0, 20, 42, 63} _ComputationKind_index_3 = [...]uint8{0, 16, 34, 51} _ComputationKind_index_4 = [...]uint8{0, 21, 44, 66} - _ComputationKind_index_5 = [...]uint8{0, 11, 23, 41} - _ComputationKind_index_6 = [...]uint8{0, 21, 40} + _ComputationKind_index_6 = [...]uint8{0, 11, 23, 41} + _ComputationKind_index_7 = [...]uint8{0, 21, 40} ) func (i ComputationKind) String() string { @@ -63,12 +65,14 @@ func (i ComputationKind) String() string { case 1040 <= i && i <= 1042: i -= 1040 return _ComputationKind_name_4[_ComputationKind_index_4[i]:_ComputationKind_index_4[i+1]] + case i == 1080: + return _ComputationKind_name_5 case 1100 <= i && i <= 1102: i -= 1100 - return _ComputationKind_name_5[_ComputationKind_index_5[i]:_ComputationKind_index_5[i+1]] + return _ComputationKind_name_6[_ComputationKind_index_6[i]:_ComputationKind_index_6[i+1]] case 1108 <= i && i <= 1109: i -= 1108 - return _ComputationKind_name_6[_ComputationKind_index_6[i]:_ComputationKind_index_6[i+1]] + return _ComputationKind_name_7[_ComputationKind_index_7[i]:_ComputationKind_index_7[i+1]] default: return "ComputationKind(" + strconv.FormatInt(int64(i), 10) + ")" } diff --git a/runtime/common/identifierlocation.go b/runtime/common/identifierlocation.go index d17ef49398..ce07bdf579 100644 --- a/runtime/common/identifierlocation.go +++ b/runtime/common/identifierlocation.go @@ -20,6 +20,7 @@ package common import ( "encoding/json" + "fmt" "strings" "github.com/onflow/cadence/runtime/errors" @@ -64,6 +65,10 @@ func (l IdentifierLocation) Description() string { return string(l) } +func (l IdentifierLocation) ID() string { + return fmt.Sprintf("%s.%s", IdentifierLocationPrefix, l) +} + func (l IdentifierLocation) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Type string @@ -98,11 +103,8 @@ func decodeIdentifierLocationTypeID(_ MemoryGauge, typeID string) (IdentifierLoc parts := strings.SplitN(typeID, ".", 3) pieceCount := len(parts) - switch pieceCount { - case 1: + if pieceCount == 1 { return newError("missing location") - case 2: - return newError("missing qualified identifier") } prefix := parts[0] @@ -117,7 +119,11 @@ func decodeIdentifierLocationTypeID(_ MemoryGauge, typeID string) (IdentifierLoc } location := IdentifierLocation(parts[1]) - qualifiedIdentifier := parts[2] + + var qualifiedIdentifier string + if pieceCount > 2 { + qualifiedIdentifier = parts[2] + } return location, qualifiedIdentifier, nil } diff --git a/runtime/common/identifierlocation_test.go b/runtime/common/identifierlocation_test.go index 6e19e09971..35a5d833cb 100644 --- a/runtime/common/identifierlocation_test.go +++ b/runtime/common/identifierlocation_test.go @@ -58,6 +58,19 @@ func TestIdentifierLocation_TypeID(t *testing.T) { ) } +func TestIdentifierLocation_ID(t *testing.T) { + + t.Parallel() + + location, _, err := decodeIdentifierLocationTypeID(nil, "I.foo.Bar.Baz") + require.NoError(t, err) + + assert.Equal(t, + "I.foo", + location.ID(), + ) +} + func TestDecodeIdentifierLocationTypeID(t *testing.T) { t.Parallel() @@ -78,15 +91,35 @@ func TestDecodeIdentifierLocationTypeID(t *testing.T) { require.EqualError(t, err, "invalid identifier location type ID: missing location") }) - t.Run("missing qualified identifier", func(t *testing.T) { + t.Run("missing qualified identifier part", func(t *testing.T) { + + t.Parallel() + + location, qualifiedIdentifier, err := decodeIdentifierLocationTypeID(nil, "I.test") + require.NoError(t, err) + + assert.Equal(t, + IdentifierLocation("test"), + location, + ) + assert.Equal(t, "", qualifiedIdentifier) + }) + + t.Run("empty qualified identifier", func(t *testing.T) { t.Parallel() - _, _, err := decodeIdentifierLocationTypeID(nil, "I.test") - require.EqualError(t, err, "invalid identifier location type ID: missing qualified identifier") + location, qualifiedIdentifier, err := decodeIdentifierLocationTypeID(nil, "I.test.") + require.NoError(t, err) + + assert.Equal(t, + IdentifierLocation("test"), + location, + ) + assert.Equal(t, "", qualifiedIdentifier) }) - t.Run("missing qualified identifier", func(t *testing.T) { + t.Run("invalid prefix", func(t *testing.T) { t.Parallel() diff --git a/runtime/common/location.go b/runtime/common/location.go index c3c815b688..bb22061874 100644 --- a/runtime/common/location.go +++ b/runtime/common/location.go @@ -36,6 +36,9 @@ type Location interface { QualifiedIdentifier(typeID TypeID) string // Description returns a human-readable description. For example, it can be used in error messages Description() string + // ID returns a string representation of the location, including the location prefix. + // This is helpful to differentiate a location, e.g in the context of code coverage. + ID() string } // LocationsInSameAccount returns true if both locations are nil, diff --git a/runtime/common/repllocation.go b/runtime/common/repllocation.go index 632c737d7d..fd626bc28a 100644 --- a/runtime/common/repllocation.go +++ b/runtime/common/repllocation.go @@ -71,6 +71,10 @@ func (l REPLLocation) Description() string { return REPLLocationPrefix } +func (l REPLLocation) ID() string { + return REPLLocationPrefix +} + func (l REPLLocation) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Type string @@ -102,11 +106,6 @@ func decodeREPLLocationTypeID(typeID string) (REPLLocation, string, error) { parts := strings.SplitN(typeID, ".", 2) - pieceCount := len(parts) - if pieceCount == 1 { - return newError("missing qualified identifier") - } - prefix := parts[0] if prefix != REPLLocationPrefix { @@ -118,7 +117,11 @@ func decodeREPLLocationTypeID(typeID string) (REPLLocation, string, error) { ) } - qualifiedIdentifier := parts[1] + pieceCount := len(parts) + var qualifiedIdentifier string + if pieceCount > 1 { + qualifiedIdentifier = parts[1] + } return REPLLocation{}, qualifiedIdentifier, nil } diff --git a/runtime/common/repllocation_test.go b/runtime/common/repllocation_test.go index 7c6d9718f5..a153610ee1 100644 --- a/runtime/common/repllocation_test.go +++ b/runtime/common/repllocation_test.go @@ -57,6 +57,19 @@ func TestREPLLocation_TypeID(t *testing.T) { ) } +func TestREPLLocation_ID(t *testing.T) { + + t.Parallel() + + location, _, err := decodeREPLLocationTypeID("REPL.Bar.Baz") + require.NoError(t, err) + + assert.Equal(t, + "REPL", + location.ID(), + ) +} + func TestDecodeREPLLocationTypeID(t *testing.T) { t.Parallel() @@ -69,15 +82,35 @@ func TestDecodeREPLLocationTypeID(t *testing.T) { require.EqualError(t, err, "invalid REPL location type ID: missing prefix") }) - t.Run("missing qualified identifier", func(t *testing.T) { + t.Run("missing qualified identifier part", func(t *testing.T) { + + t.Parallel() + + location, qualifiedIdentifier, err := decodeREPLLocationTypeID("REPL") + require.NoError(t, err) + + assert.Equal(t, + REPLLocation{}, + location, + ) + assert.Equal(t, "", qualifiedIdentifier) + }) + + t.Run("empty qualified identifier", func(t *testing.T) { t.Parallel() - _, _, err := decodeREPLLocationTypeID("REPL") - require.EqualError(t, err, "invalid REPL location type ID: missing qualified identifier") + location, qualifiedIdentifier, err := decodeREPLLocationTypeID("REPL.") + require.NoError(t, err) + + assert.Equal(t, + REPLLocation{}, + location, + ) + assert.Equal(t, "", qualifiedIdentifier) }) - t.Run("missing qualified identifier", func(t *testing.T) { + t.Run("invalid prefix", func(t *testing.T) { t.Parallel() diff --git a/runtime/common/scriptlocation.go b/runtime/common/scriptlocation.go index ef1f911c06..2942d9d101 100644 --- a/runtime/common/scriptlocation.go +++ b/runtime/common/scriptlocation.go @@ -70,6 +70,10 @@ func (l ScriptLocation) Description() string { return fmt.Sprintf("script with ID %s", hex.EncodeToString(l[:])) } +func (l ScriptLocation) ID() string { + return fmt.Sprintf("%s.%s", ScriptLocationPrefix, l) +} + func (l ScriptLocation) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Type string diff --git a/runtime/common/scriptlocation_test.go b/runtime/common/scriptlocation_test.go index 365ae28846..82a4f21d30 100644 --- a/runtime/common/scriptlocation_test.go +++ b/runtime/common/scriptlocation_test.go @@ -58,6 +58,22 @@ func TestScriptLocationTypeID(t *testing.T) { ) } +func TestScriptLocationID(t *testing.T) { + + t.Parallel() + + location, _, err := decodeScriptLocationTypeID( + nil, + "s.0102000000000000000000000000000000000000000000000000000000000000.Bar.Baz", + ) + require.NoError(t, err) + + assert.Equal(t, + "s.0102000000000000000000000000000000000000000000000000000000000000", + location.ID(), + ) +} + func TestDecodeScriptLocationTypeID(t *testing.T) { t.Parallel() @@ -89,10 +105,10 @@ func TestDecodeScriptLocationTypeID(t *testing.T) { ScriptLocation{0x1, 0x2}, location, ) - assert.Empty(t, qualifiedIdentifier) + assert.Equal(t, "", qualifiedIdentifier) }) - t.Run("missing qualified identifier", func(t *testing.T) { + t.Run("invalid prefix", func(t *testing.T) { t.Parallel() diff --git a/runtime/common/stringlocation.go b/runtime/common/stringlocation.go index 124cfc3d44..17532f665e 100644 --- a/runtime/common/stringlocation.go +++ b/runtime/common/stringlocation.go @@ -20,6 +20,7 @@ package common import ( "encoding/json" + "fmt" "strings" "github.com/onflow/cadence/runtime/errors" @@ -64,6 +65,10 @@ func (l StringLocation) Description() string { return string(l) } +func (l StringLocation) ID() string { + return fmt.Sprintf("%s.%s", StringLocationPrefix, l) +} + func (l StringLocation) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Type string @@ -98,11 +103,8 @@ func decodeStringLocationTypeID(gauge MemoryGauge, typeID string) (StringLocatio parts := strings.SplitN(typeID, ".", 3) pieceCount := len(parts) - switch pieceCount { - case 1: + if pieceCount == 1 { return newError("missing location") - case 2: - return newError("missing qualified identifier") } prefix := parts[0] @@ -117,7 +119,10 @@ func decodeStringLocationTypeID(gauge MemoryGauge, typeID string) (StringLocatio } location := NewStringLocation(gauge, parts[1]) - qualifiedIdentifier := parts[2] + var qualifiedIdentifier string + if pieceCount > 2 { + qualifiedIdentifier = parts[2] + } return location, qualifiedIdentifier, nil } diff --git a/runtime/common/stringlocation_test.go b/runtime/common/stringlocation_test.go index 8fc378314d..d2c9ffd93d 100644 --- a/runtime/common/stringlocation_test.go +++ b/runtime/common/stringlocation_test.go @@ -58,6 +58,19 @@ func TestStringLocation_TypeID(t *testing.T) { ) } +func TestStringLocation_ID(t *testing.T) { + + t.Parallel() + + location, _, err := decodeStringLocationTypeID(nil, "S.foo.Bar.Baz") + require.NoError(t, err) + + assert.Equal(t, + "S.foo", + location.ID(), + ) +} + func TestDecodeStringLocationTypeID(t *testing.T) { t.Parallel() @@ -78,15 +91,35 @@ func TestDecodeStringLocationTypeID(t *testing.T) { require.EqualError(t, err, "invalid string location type ID: missing location") }) - t.Run("missing qualified identifier", func(t *testing.T) { + t.Run("missing qualified identifier part", func(t *testing.T) { + + t.Parallel() + + location, qualifiedIdentifier, err := decodeStringLocationTypeID(nil, "S.test") + require.NoError(t, err) + + assert.Equal(t, + StringLocation("test"), + location, + ) + assert.Equal(t, "", qualifiedIdentifier) + }) + + t.Run("empty qualified identifier", func(t *testing.T) { t.Parallel() - _, _, err := decodeStringLocationTypeID(nil, "S.test") - require.EqualError(t, err, "invalid string location type ID: missing qualified identifier") + location, qualifiedIdentifier, err := decodeStringLocationTypeID(nil, "S.test.") + require.NoError(t, err) + + assert.Equal(t, + StringLocation("test"), + location, + ) + assert.Equal(t, "", qualifiedIdentifier) }) - t.Run("missing qualified identifier", func(t *testing.T) { + t.Run("invalid prefix", func(t *testing.T) { t.Parallel() diff --git a/runtime/common/transactionlocation.go b/runtime/common/transactionlocation.go index 30da5bbd28..29ed8d230e 100644 --- a/runtime/common/transactionlocation.go +++ b/runtime/common/transactionlocation.go @@ -70,6 +70,10 @@ func (l TransactionLocation) Description() string { return fmt.Sprintf("transaction with ID %s", hex.EncodeToString(l[:])) } +func (l TransactionLocation) ID() string { + return fmt.Sprintf("%s.%s", TransactionLocationPrefix, l) +} + func (l TransactionLocation) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Type string diff --git a/runtime/common/transactionlocation_test.go b/runtime/common/transactionlocation_test.go index d9ad931164..77e41b6980 100644 --- a/runtime/common/transactionlocation_test.go +++ b/runtime/common/transactionlocation_test.go @@ -58,6 +58,22 @@ func TestTransactionLocation_TypeID(t *testing.T) { ) } +func TestTransactionLocation_ID(t *testing.T) { + + t.Parallel() + + location, _, err := decodeTransactionLocationTypeID( + nil, + "t.0102000000000000000000000000000000000000000000000000000000000000.Bar.Baz", + ) + require.NoError(t, err) + + assert.Equal(t, + "t.0102000000000000000000000000000000000000000000000000000000000000", + location.ID(), + ) +} + func TestDecodeTransactionLocationTypeID(t *testing.T) { t.Parallel() @@ -89,10 +105,10 @@ func TestDecodeTransactionLocationTypeID(t *testing.T) { TransactionLocation{0x1, 0x2}, location, ) - assert.Empty(t, qualifiedIdentifier) + assert.Equal(t, "", qualifiedIdentifier) }) - t.Run("missing qualified identifier", func(t *testing.T) { + t.Run("invalid prefix", func(t *testing.T) { t.Parallel() diff --git a/runtime/contract_test.go b/runtime/contract_test.go index 1b90d4450e..07ea41f7ea 100644 --- a/runtime/contract_test.go +++ b/runtime/contract_test.go @@ -177,24 +177,24 @@ func TestRuntimeContract(t *testing.T) { log: func(message string) { loggedMessages = append(loggedMessages, message) }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - require.Equal(t, tc.name, name) - assert.Equal(t, signerAddress, address) + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { + require.Equal(t, tc.name, location.Name) + assert.Equal(t, signerAddress, location.Address) deployedCode = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - if name == tc.name { + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + if location.Name == tc.name { return deployedCode, nil } return nil, nil }, - removeAccountContractCode: func(address Address, name string) error { - require.Equal(t, tc.name, name) - assert.Equal(t, signerAddress, address) + removeAccountContractCode: func(location common.AddressLocation) error { + require.Equal(t, tc.name, location.Name) + assert.Equal(t, signerAddress, location.Address) deployedCode = nil @@ -662,27 +662,15 @@ func TestRuntimeImportMultipleContracts(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{common.MustBytesToAddress([]byte{0x1})}, nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, - removeAccountContractCode: func(address Address, name string) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + removeAccountContractCode: func(location common.AddressLocation) error { delete(accountCodes, location) return nil }, diff --git a/runtime/contract_update_test.go b/runtime/contract_update_test.go index 8a803bc528..24610c3d1b 100644 --- a/runtime/contract_update_test.go +++ b/runtime/contract_update_test.go @@ -58,18 +58,10 @@ func TestContractUpdateWithDependencies(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -268,18 +260,10 @@ func TestContractUpdateWithPrecedingIdentifiers(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, diff --git a/runtime/contract_update_validation_test.go b/runtime/contract_update_validation_test.go index 7aac70d9b8..2048097a42 100644 --- a/runtime/contract_update_validation_test.go +++ b/runtime/contract_update_validation_test.go @@ -93,26 +93,14 @@ func newContractDeploymentTransactor(t *testing.T) func(code string) error { return []Address{common.MustBytesToAddress([]byte{0x42})}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - removeAccountContractCode: func(address Address, name string) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + removeAccountContractCode: func(location common.AddressLocation) error { delete(accountCodes, location) return nil }, @@ -2163,26 +2151,14 @@ func TestRuntimeContractUpdateConformanceChanges(t *testing.T) { return []Address{address}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - removeAccountContractCode: func(address Address, name string) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + removeAccountContractCode: func(location common.AddressLocation) error { delete(accountCodes, location) return nil }, @@ -2280,26 +2256,14 @@ func TestRuntimeContractUpdateProgramCaching(t *testing.T) { return []Address{address}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - removeAccountContractCode: func(address Address, name string) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + removeAccountContractCode: func(location common.AddressLocation) error { delete(accountCodes, location) return nil }, diff --git a/runtime/convertValues.go b/runtime/convertValues.go index ecdf78428f..e5393c31d1 100644 --- a/runtime/convertValues.go +++ b/runtime/convertValues.go @@ -211,6 +211,8 @@ func exportValueWithInterpreter( ) case interpreter.AddressValue: return cadence.NewMeteredAddress(inter, v), nil + case interpreter.PathLinkValue: + return exportPathLinkValue(v, inter), nil case interpreter.PathValue: return exportPathValue(inter, v), nil case interpreter.TypeValue: @@ -583,6 +585,12 @@ func exportDictionaryValue( return dictionary.WithType(exportType), err } +func exportPathLinkValue(v interpreter.PathLinkValue, inter *interpreter.Interpreter) cadence.PathLink { + path := exportPathValue(inter, v.TargetPath) + ty := string(inter.MustConvertStaticToSemaType(v.Type).ID()) + return cadence.NewMeteredLink(inter, path, ty) +} + func exportPathValue(gauge common.MemoryGauge, v interpreter.PathValue) cadence.Path { domain := v.Domain.Identifier() common.UseMemory(gauge, common.MemoryUsage{ @@ -802,6 +810,8 @@ func (i valueImporter) importValue(value cadence.Value, expectedType sema.Type) return nil, errors.NewDefaultUserError("cannot import contract") case cadence.Function: return nil, errors.NewDefaultUserError("cannot import function") + case cadence.PathLink: + return nil, errors.NewDefaultUserError("cannot import link") default: // This means the implementation has unhandled types. // Hence, return an internal error diff --git a/runtime/convertValues_test.go b/runtime/convertValues_test.go index 00d2128772..cde658a38f 100644 --- a/runtime/convertValues_test.go +++ b/runtime/convertValues_test.go @@ -824,6 +824,17 @@ func TestImportValue(t *testing.T) { Identifier: "foo", }, }, + { + label: "Link (invalid)", + value: cadence.PathLink{ + TargetPath: cadence.Path{ + Domain: "storage", + Identifier: "test", + }, + BorrowType: "Int", + }, + expected: nil, + }, { label: "Capability (invalid)", value: cadence.StorageCapability{ @@ -2094,6 +2105,91 @@ func TestExportStorageCapabilityValue(t *testing.T) { }) } +func TestExportPathLinkValue(t *testing.T) { + + t.Parallel() + + t.Run("Int", func(t *testing.T) { + + link := interpreter.PathLinkValue{ + TargetPath: interpreter.PathValue{ + Domain: common.PathDomainStorage, + Identifier: "foo", + }, + Type: interpreter.PrimitiveStaticTypeInt, + } + + actual, err := exportValueWithInterpreter( + link, + newTestInterpreter(t), + interpreter.EmptyLocationRange, + seenReferences{}, + ) + require.NoError(t, err) + + expected := cadence.PathLink{ + TargetPath: cadence.Path{ + Domain: "storage", + Identifier: "foo", + }, + BorrowType: "Int", + } + + assert.Equal(t, expected, actual) + }) + + t.Run("Struct", func(t *testing.T) { + + const code = ` + struct S {} + ` + program, err := parser.ParseProgram(nil, []byte(code), parser.Config{}) + require.NoError(t, err) + + checker, err := sema.NewChecker( + program, + TestLocation, + nil, + &sema.Config{ + AccessCheckMode: sema.AccessCheckModeNotSpecifiedUnrestricted, + }, + ) + require.NoError(t, err) + + err = checker.Check() + require.NoError(t, err) + + inter := newTestInterpreter(t) + inter.Program = interpreter.ProgramFromChecker(checker) + + capability := interpreter.PathLinkValue{ + TargetPath: interpreter.PathValue{ + Domain: common.PathDomainStorage, + Identifier: "foo", + }, + Type: interpreter.NewCompositeStaticTypeComputeTypeID(inter, TestLocation, "S"), + } + + actual, err := exportValueWithInterpreter( + capability, + inter, + interpreter.EmptyLocationRange, + seenReferences{}, + ) + require.NoError(t, err) + + expected := cadence.PathLink{ + TargetPath: cadence.Path{ + Domain: "storage", + Identifier: "foo", + }, + BorrowType: "S.test.S", + } + + assert.Equal(t, expected, actual) + }) +} + func TestExportCompositeValueWithFunctionValueField(t *testing.T) { t.Parallel() diff --git a/runtime/coverage.go b/runtime/coverage.go index a3dc369091..cd01067ddb 100644 --- a/runtime/coverage.go +++ b/runtime/coverage.go @@ -38,6 +38,10 @@ type LocationCoverage struct { // AddLineHit increments the hit count for the given line. func (c *LocationCoverage) AddLineHit(line int) { + // Lines below 1 are dropped. + if line < 1 { + return + } c.LineHits[line]++ } @@ -100,13 +104,13 @@ func NewLocationCoverage(lineHits map[int]int) *LocationCoverage { } // CoverageReport collects coverage information per location. -// It keeps track of inspected programs per location, and can -// also exclude locations from coverage collection. +// It keeps track of inspected locations, and can also exclude +// locations from coverage collection. type CoverageReport struct { // Contains a *LocationCoverage per location. Coverage map[common.Location]*LocationCoverage `json:"-"` - // Contains an *ast.Program per location. - Programs map[common.Location]*ast.Program `json:"-"` + // Contains locations whose programs are already inspected. + Locations map[common.Location]struct{} `json:"-"` // Contains locations excluded from coverage collection. ExcludedLocations map[common.Location]struct{} `json:"-"` } @@ -127,13 +131,13 @@ func (r *CoverageReport) IsLocationExcluded(location Location) bool { // AddLineHit increments the hit count for the given line, on the given // location. The method call is a NO-OP in two cases: // - If the location is excluded from coverage collection -// - If the location's *ast.Program, has not been inspected +// - If the location has not been inspected for its statements func (r *CoverageReport) AddLineHit(location Location, line int) { if r.IsLocationExcluded(location) { return } - if !r.IsProgramInspected(location) { + if !r.IsLocationInspected(location) { return } @@ -142,15 +146,19 @@ func (r *CoverageReport) AddLineHit(location Location, line int) { } // InspectProgram inspects the elements of the given *ast.Program, and counts its -// statements. If inspection is successful, the *ast.Program is marked as inspected. +// statements. If inspection is successful, the location is marked as inspected. // If the given location is excluded from coverage collection, the method call // results in a NO-OP. func (r *CoverageReport) InspectProgram(location Location, program *ast.Program) { if r.IsLocationExcluded(location) { return } - r.Programs[location] = program + r.Locations[location] = struct{}{} lineHits := make(map[int]int, 0) + recordLine := func(hasPosition ast.HasPosition) { + line := hasPosition.StartPosition().Line + lineHits[line] = 0 + } var depth int inspector := ast.NewInspector(program) @@ -170,8 +178,22 @@ func (r *CoverageReport) InspectProgram(location Location, program *ast.Program) // However, also track local (i.e. non-top level) variable declarations. if (isStatement && !isDeclaration) || (isVariableDeclaration && depth > 2) { - line := element.StartPosition().Line - lineHits[line] = 0 + recordLine(element) + } + + functionBlock, isFunctionBlock := element.(*ast.FunctionBlock) + // Track also pre/post conditions defined inside functions. + if isFunctionBlock { + if functionBlock.PreConditions != nil { + for _, condition := range *functionBlock.PreConditions { + recordLine(condition.Test) + } + } + if functionBlock.PostConditions != nil { + for _, condition := range *functionBlock.PostConditions { + recordLine(condition.Test) + } + } } } else { depth-- @@ -180,63 +202,201 @@ func (r *CoverageReport) InspectProgram(location Location, program *ast.Program) return true }) - locationCoverage := NewLocationCoverage(lineHits) - r.Coverage[location] = locationCoverage + r.Coverage[location] = NewLocationCoverage(lineHits) } -// IsProgramInspected checks whether the *ast.Program on the given -// location, has been inspected or not. -func (r *CoverageReport) IsProgramInspected(location Location) bool { - _, isInspected := r.Programs[location] +// IsLocationInspected checks whether the given location, +// has been inspected or not. +func (r *CoverageReport) IsLocationInspected(location Location) bool { + _, isInspected := r.Locations[location] return isInspected } -// CoveredStatementsPercentage returns a string representation of -// the covered statements percentage. It is defined as the ratio -// of total covered lines over total statements, for all locations. -func (r *CoverageReport) CoveredStatementsPercentage() string { +// Percentage returns a string representation of the covered statements +// percentage. It is defined as the ratio of total covered lines over +// total statements, for all locations. +func (r *CoverageReport) Percentage() string { + totalStatements := r.Statements() + totalCoveredLines := r.Hits() + return fmt.Sprintf( + "%0.1f%%", + 100*float64(totalCoveredLines)/float64(totalStatements), + ) +} + +// String returns a human-friendly message for the covered +// statements percentage. +func (r *CoverageReport) String() string { + return fmt.Sprintf("Coverage: %v of statements", r.Percentage()) +} + +// Reset flushes the collected coverage information for all locations +// and inspected locations. Excluded locations remain intact. +func (r *CoverageReport) Reset() { + for location := range r.Coverage { // nolint:maprange + delete(r.Coverage, location) + } + for location := range r.Locations { // nolint:maprange + delete(r.Locations, location) + } +} + +// Merge adds all the collected coverage information to the +// calling object. Excluded locations are also taken into +// account. +func (r *CoverageReport) Merge(other CoverageReport) { + for location, locationCoverage := range other.Coverage { // nolint:maprange + r.Coverage[location] = locationCoverage + } + for location, v := range other.Locations { // nolint:maprange + r.Locations[location] = v + } + for location, v := range other.ExcludedLocations { // nolint:maprange + r.ExcludedLocations[location] = v + } +} + +// ExcludedLocationIDs returns the ID of each excluded location. This +// is helpful in order to marshal/unmarshal a CoverageReport, without +// losing any valuable information. +func (r *CoverageReport) ExcludedLocationIDs() []string { + excludedLocationIDs := make([]string, 0, len(r.ExcludedLocations)) + for location := range r.ExcludedLocations { // nolint:maprange + excludedLocationIDs = append(excludedLocationIDs, location.ID()) + } + return excludedLocationIDs +} + +// TotalLocations returns the count of locations included in +// the CoverageReport. This implies that these locations are: +// - inspected, +// - not marked as exlucded. +func (r *CoverageReport) TotalLocations() int { + return len(r.Coverage) +} + +// Statements returns the total count of statements, for all the +// locations included in the CoverageReport. +func (r *CoverageReport) Statements() int { totalStatements := 0 - totalCoveredLines := 0 for _, locationCoverage := range r.Coverage { // nolint:maprange totalStatements += locationCoverage.Statements + } + return totalStatements +} + +// Hits returns the total count of covered lines, for all the +// locations included in the CoverageReport. +func (r *CoverageReport) Hits() int { + totalCoveredLines := 0 + for _, locationCoverage := range r.Coverage { // nolint:maprange totalCoveredLines += locationCoverage.CoveredLines() } - percentage := fmt.Sprintf( + return totalCoveredLines +} + +// Misses returns the total count of non-covered lines, for all +// the locations included in the CoverageReport. +func (r *CoverageReport) Misses() int { + return r.Statements() - r.Hits() +} + +// Summary returns a CoverageReportSummary object, containing +// key metrics for a CoverageReport, such as: +// - Total Locations, +// - Total Statements, +// - Total Hits, +// - Total Misses, +// - Overall Coverage Percentage. +func (r *CoverageReport) Summary() CoverageReportSummary { + return CoverageReportSummary{ + Locations: r.TotalLocations(), + Statements: r.Statements(), + Hits: r.Hits(), + Misses: r.Misses(), + Coverage: r.Percentage(), + } +} + +// Diff computes the incremental diff between the calling object and +// a new CoverageReport. The returned result is a CoverageReportSummary +// object. +// +// CoverageReportSummary{ +// Locations: 0, +// Statements: 0, +// Hits: 2, +// Misses: -2, +// Coverage: "100.0%", +// } +// +// The above diff is interpreted as follows: +// - No diff in locations, +// - No diff in statements, +// - Hits increased by 2, +// - Misses decreased by 2, +// - Coverage Δ increased by 100.0%. +func (r *CoverageReport) Diff(other CoverageReport) CoverageReportSummary { + baseCoverage := 100 * float64(r.Hits()) / float64(r.Statements()) + newCoverage := 100 * float64(other.Hits()) / float64(other.Statements()) + coverageDelta := fmt.Sprintf( "%0.1f%%", - 100*float64(totalCoveredLines)/float64(totalStatements), + 100*(newCoverage-baseCoverage)/baseCoverage, ) - return fmt.Sprintf("Coverage: %v of statements", percentage) + return CoverageReportSummary{ + Locations: other.TotalLocations() - r.TotalLocations(), + Statements: other.Statements() - r.Statements(), + Hits: other.Hits() - r.Hits(), + Misses: other.Misses() - r.Misses(), + Coverage: coverageDelta, + } +} + +// CoverageReportSummary contains key metrics that are derived +// from a CoverageReport object, such as: +// - Total Locations, +// - Total Statements, +// - Total Hits, +// - Total Misses, +// - Overall Coverage Percentage. +// This metrics can be utilized in various ways, such as a CI +// plugin/app. +type CoverageReportSummary struct { + Locations int `json:"locations"` + Statements int `json:"statements"` + Hits int `json:"hits"` + Misses int `json:"misses"` + Coverage string `json:"coverage"` } // NewCoverageReport creates and returns a *CoverageReport. func NewCoverageReport() *CoverageReport { return &CoverageReport{ Coverage: map[common.Location]*LocationCoverage{}, - Programs: map[common.Location]*ast.Program{}, + Locations: map[common.Location]struct{}{}, ExcludedLocations: map[common.Location]struct{}{}, } } -// MarshalJSON serializes each common.Location/*LocationCoverage -// key/value pair on the *CoverageReport.Coverage map. -func (r *CoverageReport) MarshalJSON() ([]byte, error) { - type Alias CoverageReport +type crAlias CoverageReport - // To avoid the overhead of having the Percentage & MissedLines - // as fields in the LocationCoverage struct, we simply populate - // this LC struct, with the corresponding methods, upon marshalling. - type LC struct { - LineHits map[int]int `json:"line_hits"` - MissedLines []int `json:"missed_lines"` - Statements int `json:"statements"` - Percentage string `json:"percentage"` - } +// To avoid the overhead of having the Percentage & MissedLines +// as fields in the LocationCoverage struct, we simply populate +// this lcAlias struct, with the corresponding methods, upon marshalling. +type lcAlias struct { + LineHits map[int]int `json:"line_hits"` + MissedLines []int `json:"missed_lines"` + Statements int `json:"statements"` + Percentage string `json:"percentage"` +} - coverage := make(map[string]LC, len(r.Coverage)) +// MarshalJSON serializes each common.Location/*LocationCoverage +// key/value pair on the *CoverageReport.Coverage map, as well +// as the IDs on the *CoverageReport.ExcludedLocations map. +func (r *CoverageReport) MarshalJSON() ([]byte, error) { + coverage := make(map[string]lcAlias, len(r.Coverage)) for location, locationCoverage := range r.Coverage { // nolint:maprange - typeID := location.TypeID(nil, "") - locationID := typeID[:len(typeID)-1] - coverage[string(locationID)] = LC{ + coverage[location.ID()] = lcAlias{ LineHits: locationCoverage.LineHits, MissedLines: locationCoverage.MissedLines(), Statements: locationCoverage.Statements, @@ -244,10 +404,56 @@ func (r *CoverageReport) MarshalJSON() ([]byte, error) { } } return json.Marshal(&struct { - Coverage map[string]LC `json:"coverage"` - *Alias + Coverage map[string]lcAlias `json:"coverage"` + ExcludedLocations []string `json:"excluded_locations"` + *crAlias }{ - Coverage: coverage, - Alias: (*Alias)(r), + Coverage: coverage, + ExcludedLocations: r.ExcludedLocationIDs(), + crAlias: (*crAlias)(r), }) } + +// UnmarshalJSON deserializes a JSON structure and populates +// the calling object with the respective *CoverageReport.Coverage & +// *CoverageReport.ExcludedLocations maps. +func (r *CoverageReport) UnmarshalJSON(data []byte) error { + cr := &struct { + Coverage map[string]lcAlias `json:"coverage"` + ExcludedLocations []string `json:"excluded_locations"` + *crAlias + }{ + crAlias: (*crAlias)(r), + } + + if err := json.Unmarshal(data, cr); err != nil { + return err + } + + for locationID, locationCoverage := range cr.Coverage { // nolint:maprange + location, _, err := common.DecodeTypeID(nil, locationID) + if err != nil { + return err + } + if location == nil { + return fmt.Errorf("invalid Location ID: %s", locationID) + } + r.Coverage[location] = &LocationCoverage{ + LineHits: locationCoverage.LineHits, + Statements: locationCoverage.Statements, + } + r.Locations[location] = struct{}{} + } + for _, locationID := range cr.ExcludedLocations { + location, _, err := common.DecodeTypeID(nil, locationID) + if err != nil { + return err + } + if location == nil { + return fmt.Errorf("invalid Location ID: %s", locationID) + } + r.ExcludedLocations[location] = struct{}{} + } + + return nil +} diff --git a/runtime/coverage_test.go b/runtime/coverage_test.go index 09ebc6474e..9d4a36a7d4 100644 --- a/runtime/coverage_test.go +++ b/runtime/coverage_test.go @@ -29,6 +29,7 @@ import ( "github.com/onflow/cadence" "github.com/onflow/cadence/runtime/common" "github.com/onflow/cadence/runtime/parser" + "github.com/onflow/cadence/runtime/stdlib" ) func TestNewLocationCoverage(t *testing.T) { @@ -64,6 +65,8 @@ func TestLocationCoverageAddLineHit(t *testing.T) { lineHits := map[int]int{3: 0, 4: 0, 5: 0, 7: 0, 9: 0, 11: 0} locationCoverage := NewLocationCoverage(lineHits) + // Lines below 1 are dropped. + locationCoverage.AddLineHit(0) locationCoverage.AddLineHit(3) locationCoverage.AddLineHit(3) locationCoverage.AddLineHit(7) @@ -102,6 +105,7 @@ func TestLocationCoverageCoveredLines(t *testing.T) { } func TestLocationCoverageMissedLines(t *testing.T) { + t.Parallel() lineHits := map[int]int{3: 0, 4: 0, 5: 0, 7: 0, 9: 0, 11: 0} @@ -137,33 +141,532 @@ func TestLocationCoveragePercentage(t *testing.T) { assert.Equal(t, "100.0%", locationCoverage.Percentage()) } -func TestNewCoverageReport(t *testing.T) { +func TestNewCoverageReport(t *testing.T) { + + t.Parallel() + + coverageReport := NewCoverageReport() + + assert.Equal(t, 0, len(coverageReport.Coverage)) + assert.Equal(t, 0, len(coverageReport.Locations)) + assert.Equal(t, 0, len(coverageReport.ExcludedLocations)) +} + +func TestCoverageReportExcludeLocation(t *testing.T) { + + t.Parallel() + + coverageReport := NewCoverageReport() + + location := common.StringLocation("FooContract") + coverageReport.ExcludeLocation(location) + // We do not allow duplicate locations + coverageReport.ExcludeLocation(location) + + assert.Equal(t, 1, len(coverageReport.ExcludedLocations)) + assert.Equal(t, true, coverageReport.IsLocationExcluded(location)) +} + +func TestCoverageReportInspectProgram(t *testing.T) { + + t.Parallel() + + script := []byte(` + pub fun answer(): Int { + var i = 0 + while i < 42 { + i = i + 1 + } + return i + } + `) + + program, err := parser.ParseProgram(nil, script, parser.Config{}) + require.NoError(t, err) + + coverageReport := NewCoverageReport() + + location := common.StringLocation("AnswerScript") + coverageReport.InspectProgram(location, program) + + assert.Equal(t, 1, len(coverageReport.Coverage)) + assert.Equal(t, 1, len(coverageReport.Locations)) + assert.Equal(t, true, coverageReport.IsLocationInspected(location)) +} + +func TestCoverageReportInspectProgramForExcludedLocation(t *testing.T) { + + t.Parallel() + + script := []byte(` + pub fun answer(): Int { + var i = 0 + while i < 42 { + i = i + 1 + } + return i + } + `) + + program, err := parser.ParseProgram(nil, script, parser.Config{}) + require.NoError(t, err) + + coverageReport := NewCoverageReport() + + location := common.StringLocation("AnswerScript") + coverageReport.ExcludeLocation(location) + coverageReport.InspectProgram(location, program) + + assert.Equal(t, 0, len(coverageReport.Coverage)) + assert.Equal(t, 0, len(coverageReport.Locations)) + assert.Equal(t, false, coverageReport.IsLocationInspected(location)) +} + +func TestCoverageReportAddLineHit(t *testing.T) { + + t.Parallel() + + script := []byte(` + pub fun answer(): Int { + var i = 0 + while i < 42 { + i = i + 1 + } + return i + } + `) + + program, err := parser.ParseProgram(nil, script, parser.Config{}) + require.NoError(t, err) + + coverageReport := NewCoverageReport() + + location := common.StringLocation("AnswerScript") + coverageReport.InspectProgram(location, program) + + coverageReport.AddLineHit(location, 3) + coverageReport.AddLineHit(location, 3) + coverageReport.AddLineHit(location, 5) + + locationCoverage := coverageReport.Coverage[location] + + assert.Equal( + t, + map[int]int{3: 2, 4: 0, 5: 1, 7: 0}, + locationCoverage.LineHits, + ) + assert.Equal( + t, + []int{4, 7}, + locationCoverage.MissedLines(), + ) + assert.Equal(t, 4, locationCoverage.Statements) + assert.Equal(t, "50.0%", locationCoverage.Percentage()) + assert.Equal(t, 2, locationCoverage.CoveredLines()) +} + +func TestCoverageReportWithFlowLocation(t *testing.T) { + + t.Parallel() + + script := []byte(` + pub fun answer(): Int { + var i = 0 + while i < 42 { + i = i + 1 + } + return i + } + `) + + program, err := parser.ParseProgram(nil, script, parser.Config{}) + require.NoError(t, err) + + coverageReport := NewCoverageReport() + + location := stdlib.FlowLocation{} + coverageReport.InspectProgram(location, program) + + actual, err := json.Marshal(coverageReport) + require.NoError(t, err) + + expected := ` + { + "coverage": { + "flow": { + "line_hits": { + "3": 0, + "4": 0, + "5": 0, + "7": 0 + }, + "missed_lines": [3, 4, 5, 7], + "statements": 4, + "percentage": "0.0%" + } + }, + "excluded_locations": [] + } + ` + require.JSONEq(t, expected, string(actual)) +} + +func TestCoverageReportWithREPLLocation(t *testing.T) { + + t.Parallel() + + script := []byte(` + pub fun answer(): Int { + var i = 0 + while i < 42 { + i = i + 1 + } + return i + } + `) + + program, err := parser.ParseProgram(nil, script, parser.Config{}) + require.NoError(t, err) + + coverageReport := NewCoverageReport() + + location := common.REPLLocation{} + coverageReport.InspectProgram(location, program) + + actual, err := json.Marshal(coverageReport) + require.NoError(t, err) + + expected := ` + { + "coverage": { + "REPL": { + "line_hits": { + "3": 0, + "4": 0, + "5": 0, + "7": 0 + }, + "missed_lines": [3, 4, 5, 7], + "statements": 4, + "percentage": "0.0%" + } + }, + "excluded_locations": [] + } + ` + require.JSONEq(t, expected, string(actual)) +} + +func TestCoverageReportWithScriptLocation(t *testing.T) { + + t.Parallel() + + script := []byte(` + pub fun answer(): Int { + var i = 0 + while i < 42 { + i = i + 1 + } + return i + } + `) + + program, err := parser.ParseProgram(nil, script, parser.Config{}) + require.NoError(t, err) + + coverageReport := NewCoverageReport() + + location := common.ScriptLocation{0x1, 0x2} + coverageReport.InspectProgram(location, program) + + actual, err := json.Marshal(coverageReport) + require.NoError(t, err) + + expected := ` + { + "coverage": { + "s.0102000000000000000000000000000000000000000000000000000000000000": { + "line_hits": { + "3": 0, + "4": 0, + "5": 0, + "7": 0 + }, + "missed_lines": [3, 4, 5, 7], + "statements": 4, + "percentage": "0.0%" + } + }, + "excluded_locations": [] + } + ` + require.JSONEq(t, expected, string(actual)) +} + +func TestCoverageReportWithStringLocation(t *testing.T) { + + t.Parallel() + + script := []byte(` + pub fun answer(): Int { + var i = 0 + while i < 42 { + i = i + 1 + } + return i + } + `) + + program, err := parser.ParseProgram(nil, script, parser.Config{}) + require.NoError(t, err) + + coverageReport := NewCoverageReport() + + location := common.StringLocation("AnswerScript") + coverageReport.InspectProgram(location, program) + + actual, err := json.Marshal(coverageReport) + require.NoError(t, err) + + expected := ` + { + "coverage": { + "S.AnswerScript": { + "line_hits": { + "3": 0, + "4": 0, + "5": 0, + "7": 0 + }, + "missed_lines": [3, 4, 5, 7], + "statements": 4, + "percentage": "0.0%" + } + }, + "excluded_locations": [] + } + ` + require.JSONEq(t, expected, string(actual)) +} + +func TestCoverageReportWithIdentifierLocation(t *testing.T) { + + t.Parallel() + + script := []byte(` + pub fun answer(): Int { + var i = 0 + while i < 42 { + i = i + 1 + } + return i + } + `) + + program, err := parser.ParseProgram(nil, script, parser.Config{}) + require.NoError(t, err) + + coverageReport := NewCoverageReport() + + location := common.IdentifierLocation("Answer") + coverageReport.InspectProgram(location, program) + + actual, err := json.Marshal(coverageReport) + require.NoError(t, err) + + expected := ` + { + "coverage": { + "I.Answer": { + "line_hits": { + "3": 0, + "4": 0, + "5": 0, + "7": 0 + }, + "missed_lines": [3, 4, 5, 7], + "statements": 4, + "percentage": "0.0%" + } + }, + "excluded_locations": [] + } + ` + require.JSONEq(t, expected, string(actual)) +} + +func TestCoverageReportWithTransactionLocation(t *testing.T) { + + t.Parallel() + + script := []byte(` + pub fun answer(): Int { + var i = 0 + while i < 42 { + i = i + 1 + } + return i + } + `) + + program, err := parser.ParseProgram(nil, script, parser.Config{}) + require.NoError(t, err) + + coverageReport := NewCoverageReport() + + location := common.TransactionLocation{0x1, 0x2} + coverageReport.InspectProgram(location, program) + + actual, err := json.Marshal(coverageReport) + require.NoError(t, err) + + expected := ` + { + "coverage": { + "t.0102000000000000000000000000000000000000000000000000000000000000": { + "line_hits": { + "3": 0, + "4": 0, + "5": 0, + "7": 0 + }, + "missed_lines": [3, 4, 5, 7], + "statements": 4, + "percentage": "0.0%" + } + }, + "excluded_locations": [] + } + ` + require.JSONEq(t, expected, string(actual)) +} + +func TestCoverageReportWithAddressLocation(t *testing.T) { + + t.Parallel() + + script := []byte(` + pub fun answer(): Int { + var i = 0 + while i < 42 { + i = i + 1 + } + return i + } + `) + + program, err := parser.ParseProgram(nil, script, parser.Config{}) + require.NoError(t, err) + + coverageReport := NewCoverageReport() + + location := common.AddressLocation{ + Address: common.MustBytesToAddress([]byte{1, 2}), + Name: "Answer", + } + coverageReport.InspectProgram(location, program) + + actual, err := json.Marshal(coverageReport) + require.NoError(t, err) + + expected := ` + { + "coverage": { + "A.0000000000000102.Answer": { + "line_hits": { + "3": 0, + "4": 0, + "5": 0, + "7": 0 + }, + "missed_lines": [3, 4, 5, 7], + "statements": 4, + "percentage": "0.0%" + } + }, + "excluded_locations": [] + } + ` + require.JSONEq(t, expected, string(actual)) +} + +func TestCoverageReportReset(t *testing.T) { + + t.Parallel() + + script := []byte(` + pub fun answer(): Int { + var i = 0 + while i < 42 { + i = i + 1 + } + return i + } + `) + + program, err := parser.ParseProgram(nil, script, parser.Config{}) + require.NoError(t, err) + + coverageReport := NewCoverageReport() + + location := common.StringLocation("AnswerScript") + coverageReport.InspectProgram(location, program) + coverageReport.AddLineHit(location, 3) + coverageReport.AddLineHit(location, 3) + coverageReport.AddLineHit(location, 5) + + excludedLocation := common.StringLocation("XLocation") + coverageReport.ExcludeLocation(excludedLocation) + + assert.Equal(t, 1, len(coverageReport.Coverage)) + assert.Equal(t, 1, len(coverageReport.Locations)) + assert.Equal(t, 1, len(coverageReport.ExcludedLocations)) + assert.Equal(t, true, coverageReport.IsLocationInspected(location)) + assert.Equal(t, true, coverageReport.IsLocationExcluded(excludedLocation)) + + coverageReport.Reset() + + assert.Equal(t, 0, len(coverageReport.Coverage)) + assert.Equal(t, 0, len(coverageReport.Locations)) + assert.Equal(t, 1, len(coverageReport.ExcludedLocations)) + assert.Equal(t, false, coverageReport.IsLocationInspected(location)) + assert.Equal(t, true, coverageReport.IsLocationExcluded(excludedLocation)) +} + +func TestCoverageReportAddLineHitForExcludedLocation(t *testing.T) { t.Parallel() coverageReport := NewCoverageReport() + location := common.StringLocation("AnswerScript") + coverageReport.ExcludeLocation(location) + + coverageReport.AddLineHit(location, 3) + coverageReport.AddLineHit(location, 5) + assert.Equal(t, 0, len(coverageReport.Coverage)) - assert.Equal(t, 0, len(coverageReport.Programs)) - assert.Equal(t, 0, len(coverageReport.ExcludedLocations)) + assert.Equal(t, 0, len(coverageReport.Locations)) + assert.Equal(t, false, coverageReport.IsLocationInspected(location)) } -func TestCoverageReportExcludeLocation(t *testing.T) { +func TestCoverageReportAddLineHitForNonInspectedProgram(t *testing.T) { t.Parallel() coverageReport := NewCoverageReport() - location := common.StringLocation("FooContract") - coverageReport.ExcludeLocation(location) - // We do not allow duplicate locations - coverageReport.ExcludeLocation(location) + location := common.StringLocation("AnswerScript") - assert.Equal(t, 1, len(coverageReport.ExcludedLocations)) - assert.Equal(t, true, coverageReport.IsLocationExcluded(location)) + coverageReport.AddLineHit(location, 3) + coverageReport.AddLineHit(location, 5) + + assert.Equal(t, 0, len(coverageReport.Coverage)) + assert.Equal(t, 0, len(coverageReport.Locations)) + assert.Equal(t, false, coverageReport.IsLocationInspected(location)) } -func TestCoverageReportInspectProgram(t *testing.T) { +func TestCoverageReportPercentage(t *testing.T) { t.Parallel() @@ -184,13 +687,36 @@ func TestCoverageReportInspectProgram(t *testing.T) { location := common.StringLocation("AnswerScript") coverageReport.InspectProgram(location, program) + coverageReport.AddLineHit(location, 3) + coverageReport.AddLineHit(location, 4) - assert.Equal(t, 1, len(coverageReport.Coverage)) - assert.Equal(t, 1, len(coverageReport.Programs)) - assert.Equal(t, true, coverageReport.IsProgramInspected(location)) + actual, err := json.Marshal(coverageReport) + require.NoError(t, err) + + expected := ` + { + "coverage": { + "S.AnswerScript": { + "line_hits": { + "3": 1, + "4": 1, + "5": 0, + "7": 0 + }, + "missed_lines": [5, 7], + "statements": 4, + "percentage": "50.0%" + } + }, + "excluded_locations": [] + } + ` + require.JSONEq(t, expected, string(actual)) + + assert.Equal(t, "50.0%", coverageReport.Percentage()) } -func TestCoverageReportInspectProgramForExcludedLocation(t *testing.T) { +func TestCoverageReportString(t *testing.T) { t.Parallel() @@ -210,15 +736,42 @@ func TestCoverageReportInspectProgramForExcludedLocation(t *testing.T) { coverageReport := NewCoverageReport() location := common.StringLocation("AnswerScript") - coverageReport.ExcludeLocation(location) coverageReport.InspectProgram(location, program) + coverageReport.AddLineHit(location, 3) + coverageReport.AddLineHit(location, 4) + coverageReport.AddLineHit(location, 5) - assert.Equal(t, 0, len(coverageReport.Coverage)) - assert.Equal(t, 0, len(coverageReport.Programs)) - assert.Equal(t, false, coverageReport.IsProgramInspected(location)) + actual, err := json.Marshal(coverageReport) + require.NoError(t, err) + + expected := ` + { + "coverage": { + "S.AnswerScript": { + "line_hits": { + "3": 1, + "4": 1, + "5": 1, + "7": 0 + }, + "missed_lines": [7], + "statements": 4, + "percentage": "75.0%" + } + }, + "excluded_locations": [] + } + ` + require.JSONEq(t, expected, string(actual)) + + assert.Equal( + t, + "Coverage: 75.0% of statements", + coverageReport.String(), + ) } -func TestCoverageReportAddLineHit(t *testing.T) { +func TestCoverageReportDiff(t *testing.T) { t.Parallel() @@ -239,59 +792,354 @@ func TestCoverageReportAddLineHit(t *testing.T) { location := common.StringLocation("AnswerScript") coverageReport.InspectProgram(location, program) - coverageReport.AddLineHit(location, 3) - coverageReport.AddLineHit(location, 3) - coverageReport.AddLineHit(location, 5) + coverageReport.AddLineHit(location, 4) - locationCoverage := coverageReport.Coverage[location] + summary := coverageReport.Summary() + + actual, err := json.Marshal(summary) + require.NoError(t, err) + + expected := ` + { + "coverage": "50.0%", + "hits": 2, + "locations": 1, + "misses": 2, + "statements": 4 + } + ` + require.JSONEq(t, expected, string(actual)) + + otherCoverageReport := NewCoverageReport() + otherCoverageReport.InspectProgram(location, program) + otherCoverageReport.AddLineHit(location, 3) + otherCoverageReport.AddLineHit(location, 4) + otherCoverageReport.AddLineHit(location, 5) + otherCoverageReport.AddLineHit(location, 5) + otherCoverageReport.AddLineHit(location, 7) + + diff := coverageReport.Diff(*otherCoverageReport) + + actual, err = json.Marshal(diff) + require.NoError(t, err) + + expected = ` + { + "coverage": "100.0%", + "hits": 2, + "locations": 0, + "misses": -2, + "statements": 0 + } + ` + require.JSONEq(t, expected, string(actual)) +} + +func TestCoverageReportMerge(t *testing.T) { + + t.Parallel() + + integerTraitsScript := []byte(` + pub let specialNumbers: {Int: String} = { + 1729: "Harshad", + 8128: "Harmonic", + 41041: "Carmichael" + } + + pub fun addSpecialNumber(_ n: Int, _ trait: String) { + specialNumbers[n] = trait + } + + pub fun getIntegerTrait(_ n: Int): String { + if n < 0 { + return "Negative" + } else if n == 0 { + return "Zero" + } else if n < 10 { + return "Small" + } else if n < 100 { + return "Big" + } else if n < 1000 { + return "Huge" + } + + if specialNumbers.containsKey(n) { + return specialNumbers[n]! + } + + return "Enormous" + } + `) + + program, err := parser.ParseProgram(nil, integerTraitsScript, parser.Config{}) + require.NoError(t, err) + + coverageReport := NewCoverageReport() + + location := common.StringLocation("IntegerTraits") + coverageReport.InspectProgram(location, program) + + factorialScript := []byte(` + pub fun factorial(_ n: Int): Int { + pre { + n >= 0: + "factorial is only defined for integers greater than or equal to zero" + } + post { + result >= 1: + "the result must be greater than or equal to 1" + } + + if n < 1 { + return 1 + } + + return n * factorial(n - 1) + } + `) + + otherProgram, err := parser.ParseProgram(nil, factorialScript, parser.Config{}) + require.NoError(t, err) + + otherCoverageReport := NewCoverageReport() + + otherLocation := common.StringLocation("Factorial") + otherCoverageReport.InspectProgram(otherLocation, otherProgram) + + excludedLocation := common.StringLocation("FooContract") + otherCoverageReport.ExcludeLocation(excludedLocation) + + coverageReport.Merge(*otherCoverageReport) + + actual, err := json.Marshal(coverageReport) + require.NoError(t, err) + + expected := ` + { + "coverage": { + "S.Factorial": { + "line_hits": { + "12": 0, + "13": 0, + "16": 0, + "4": 0, + "8": 0 + }, + "missed_lines": [4, 8, 12, 13, 16], + "statements": 5, + "percentage": "0.0%" + }, + "S.IntegerTraits": { + "line_hits": { + "13": 0, + "14": 0, + "15": 0, + "16": 0, + "17": 0, + "18": 0, + "19": 0, + "20": 0, + "21": 0, + "22": 0, + "25": 0, + "26": 0, + "29": 0, + "9": 0 + }, + "missed_lines": [9, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 25, 26, 29], + "statements": 14, + "percentage": "0.0%" + } + }, + "excluded_locations": ["S.FooContract"] + } + ` + require.JSONEq(t, expected, string(actual)) +} + +func TestCoverageReportUnmarshalJSON(t *testing.T) { + + t.Parallel() + + data := ` + { + "coverage": { + "S.Factorial": { + "line_hits": { + "12": 0, + "13": 0, + "16": 0, + "4": 0, + "8": 0 + }, + "missed_lines": [4, 8, 12, 13, 16], + "statements": 5, + "percentage": "0.0%" + }, + "S.IntegerTraits": { + "line_hits": { + "13": 0, + "14": 0, + "15": 0, + "16": 0, + "17": 0, + "18": 0, + "19": 0, + "20": 0, + "21": 0, + "22": 0, + "25": 0, + "26": 0, + "29": 0, + "9": 0 + }, + "missed_lines": [9, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 25, 26, 29], + "statements": 14, + "percentage": "0.0%" + } + }, + "excluded_locations": ["I.Test"] + } + ` + + coverageReport := NewCoverageReport() + err := json.Unmarshal([]byte(data), coverageReport) + require.NoError(t, err) + + assert.Equal(t, 2, coverageReport.TotalLocations()) + + factorialLocation := common.StringLocation("Factorial") assert.Equal( t, - map[int]int{3: 2, 4: 0, 5: 1, 7: 0}, - locationCoverage.LineHits, + 5, + coverageReport.Coverage[factorialLocation].Statements, ) assert.Equal( t, - []int{4, 7}, - locationCoverage.MissedLines(), + "0.0%", + coverageReport.Coverage[factorialLocation].Percentage(), + ) + assert.EqualValues( + t, + []int{4, 8, 12, 13, 16}, + coverageReport.Coverage[factorialLocation].MissedLines(), + ) + assert.Equal( + t, + map[int]int{4: 0, 8: 0, 12: 0, 13: 0, 16: 0}, + coverageReport.Coverage[factorialLocation].LineHits, ) - assert.Equal(t, 4, locationCoverage.Statements) - assert.Equal(t, "50.0%", locationCoverage.Percentage()) - assert.Equal(t, 2, locationCoverage.CoveredLines()) -} -func TestCoverageReportAddLineHitForExcludedLocation(t *testing.T) { + actual, err := json.Marshal(coverageReport) + require.NoError(t, err) - t.Parallel() + require.JSONEq(t, data, string(actual)) - coverageReport := NewCoverageReport() + integerTraitsLocation := common.StringLocation("IntegerTraits") - location := common.StringLocation("AnswerScript") - coverageReport.ExcludeLocation(location) + assert.Equal( + t, + coverageReport.Coverage[integerTraitsLocation].Statements, + 14, + ) + assert.Equal( + t, + "0.0%", + coverageReport.Coverage[integerTraitsLocation].Percentage(), + ) + assert.EqualValues( + t, + []int{9, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 25, 26, 29}, + coverageReport.Coverage[integerTraitsLocation].MissedLines(), + ) + assert.EqualValues( + t, + map[int]int{9: 0, 13: 0, 14: 0, 15: 0, 16: 0, 17: 0, 18: 0, 19: 0, 20: 0, 21: 0, 22: 0, 25: 0, 26: 0, 29: 0}, + coverageReport.Coverage[integerTraitsLocation].LineHits, + ) - coverageReport.AddLineHit(location, 3) - coverageReport.AddLineHit(location, 5) + assert.Equal( + t, + 2, + len(coverageReport.Locations), + ) - assert.Equal(t, 0, len(coverageReport.Coverage)) - assert.Equal(t, 0, len(coverageReport.Programs)) - assert.Equal(t, false, coverageReport.IsProgramInspected(location)) + assert.Equal( + t, + []string{"I.Test"}, + coverageReport.ExcludedLocationIDs(), + ) } -func TestCoverageReportAddLineHitForNonInspectedProgram(t *testing.T) { +func TestCoverageReportUnmarshalJSONWithFormatError(t *testing.T) { t.Parallel() + data := "My previous coverage report.txt" + coverageReport := NewCoverageReport() + err := coverageReport.UnmarshalJSON([]byte(data)) + require.Error(t, err) +} - location := common.StringLocation("AnswerScript") +func TestCoverageReportUnmarshalJSONWithDecodeLocationError(t *testing.T) { - coverageReport.AddLineHit(location, 3) - coverageReport.AddLineHit(location, 5) + t.Parallel() - assert.Equal(t, 0, len(coverageReport.Coverage)) - assert.Equal(t, 0, len(coverageReport.Programs)) - assert.Equal(t, false, coverageReport.IsProgramInspected(location)) + data := ` + { + "coverage": { + "X.Factorial": { + "line_hits": { + "12": 0, + "13": 0, + "16": 0, + "4": 0, + "8": 0 + }, + "missed_lines": [4, 8, 12, 13, 16], + "statements": 5, + "percentage": "0.0%" + } + }, + "excluded_locations": ["I.Test"] + } + ` + + coverageReport := NewCoverageReport() + err := json.Unmarshal([]byte(data), coverageReport) + require.ErrorContains(t, err, "invalid Location ID: X.Factorial") +} + +func TestCoverageReportUnmarshalJSONWithDecodeExcludedLocationError(t *testing.T) { + + t.Parallel() + + data := ` + { + "coverage": { + "S.Factorial": { + "line_hits": { + "12": 0, + "13": 0, + "16": 0, + "4": 0, + "8": 0 + }, + "missed_lines": [4, 8, 12, 13, 16], + "statements": 5, + "percentage": "0.0%" + } + }, + "excluded_locations": ["XI.Test"] + } + ` + + coverageReport := NewCoverageReport() + err := json.Unmarshal([]byte(data), coverageReport) + require.ErrorContains(t, err, "invalid Location ID: XI.Test") } func TestRuntimeCoverage(t *testing.T) { @@ -332,6 +1180,23 @@ func TestRuntimeCoverage(t *testing.T) { return "Enormous" } + + pub fun factorial(_ n: Int): Int { + pre { + n >= 0: + "factorial is only defined for integers greater than or equal to zero" + } + post { + result >= 1: + "the result must be greater than or equal to 1" + } + + if n < 1 { + return 1 + } + + return n * factorial(n - 1) + } `) script := []byte(` @@ -358,6 +1223,9 @@ func TestRuntimeCoverage(t *testing.T) { addSpecialNumber(78557, "Sierpinski") assert("Sierpinski" == getIntegerTrait(78557)) + factorial(5) + factorial(0) + return 42 } `) @@ -410,10 +1278,15 @@ func TestRuntimeCoverage(t *testing.T) { "25": 5, "26": 4, "29": 1, + "34": 7, + "38": 7, + "42": 7, + "43": 2, + "46": 5, "9": 1 }, "missed_lines": [], - "statements": 14, + "statements": 19, "percentage": "100.0%" }, "s.0000000000000000000000000000000000000000000000000000000000000000": { @@ -424,13 +1297,16 @@ func TestRuntimeCoverage(t *testing.T) { "22": 1, "23": 1, "25": 1, + "26": 1, + "28": 1, "5": 1 }, "missed_lines": [], - "statements": 7, + "statements": 9, "percentage": "100.0%" } - } + }, + "excluded_locations": [] } ` require.JSONEq(t, expected, string(actual)) @@ -438,7 +1314,7 @@ func TestRuntimeCoverage(t *testing.T) { assert.Equal( t, "Coverage: 100.0% of statements", - coverageReport.CoveredStatementsPercentage(), + coverageReport.String(), ) } @@ -566,7 +1442,8 @@ func TestRuntimeCoverageWithExcludedLocation(t *testing.T) { "statements": 14, "percentage": "100.0%" } - } + }, + "excluded_locations": ["s.0000000000000000000000000000000000000000000000000000000000000000"] } ` require.JSONEq(t, expected, string(actual)) @@ -574,6 +1451,6 @@ func TestRuntimeCoverageWithExcludedLocation(t *testing.T) { assert.Equal( t, "Coverage: 100.0% of statements", - coverageReport.CoveredStatementsPercentage(), + coverageReport.String(), ) } diff --git a/runtime/deployedcontract_test.go b/runtime/deployedcontract_test.go index e514234212..e97b07b383 100644 --- a/runtime/deployedcontract_test.go +++ b/runtime/deployedcontract_test.go @@ -73,10 +73,7 @@ func TestDeployedContracts(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{{42}}, nil }, - getAccountContractCode: func(address Address, name string) ([]byte, error) { - location := common.AddressLocation{ - Address: address, Name: name, - } + getAccountContractCode: func(location common.AddressLocation) ([]byte, error) { return accountCodes[location], nil }, getAccountContractNames: func(_ Address) ([]string, error) { @@ -89,10 +86,7 @@ func TestDeployedContracts(t *testing.T) { emitEvent: func(_ cadence.Event) error { return nil }, - updateAccountContractCode: func(address common.Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, diff --git a/runtime/deployment_test.go b/runtime/deployment_test.go index 52a5b96673..e29292c155 100644 --- a/runtime/deployment_test.go +++ b/runtime/deployment_test.go @@ -161,10 +161,10 @@ func TestRuntimeTransactionWithContractDeployment(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{{42}}, nil }, - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, diff --git a/runtime/environment.go b/runtime/environment.go index 61437c8858..7f38f901b2 100644 --- a/runtime/environment.go +++ b/runtime/environment.go @@ -127,6 +127,7 @@ func (e *interpreterEnvironment) newInterpreterConfig() *interpreter.Config { MemoryGauge: e, BaseActivation: e.baseActivation, OnEventEmitted: e.newOnEventEmittedHandler(), + OnAccountLinked: e.newOnAccountLinkedHandler(), InjectedCompositeFieldsHandler: e.newInjectedCompositeFieldsHandler(), UUIDHandler: e.newUUIDHandler(), ContractValueHandler: e.newContractValueHandler(), @@ -259,8 +260,8 @@ func (e *interpreterEnvironment) GetAccountContractNames(address common.Address) return e.runtimeInterface.GetAccountContractNames(address) } -func (e *interpreterEnvironment) GetAccountContractCode(address common.Address, name string) ([]byte, error) { - return e.runtimeInterface.GetAccountContractCode(address, name) +func (e *interpreterEnvironment) GetAccountContractCode(location common.AddressLocation) ([]byte, error) { + return e.runtimeInterface.GetAccountContractCode(location) } func (e *interpreterEnvironment) CreateAccount(payer common.Address) (address common.Address, err error) { @@ -273,17 +274,11 @@ func (e *interpreterEnvironment) EmitEvent( values []interpreter.Value, locationRange interpreter.LocationRange, ) { - eventFields := make([]exportableValue, 0, len(values)) - - for _, value := range values { - eventFields = append(eventFields, newExportableValue(value, inter)) - } - emitEventFields( inter, locationRange, eventType, - eventFields, + newExportableValues(inter, values), e.runtimeInterface.EmitEvent, ) } @@ -301,24 +296,23 @@ func (e *interpreterEnvironment) RevokeAccountKey(address common.Address, index return e.runtimeInterface.RevokeAccountKey(address, index) } -func (e *interpreterEnvironment) UpdateAccountContractCode(address common.Address, name string, code []byte) error { - return e.runtimeInterface.UpdateAccountContractCode(address, name, code) +func (e *interpreterEnvironment) UpdateAccountContractCode(location common.AddressLocation, code []byte) error { + return e.runtimeInterface.UpdateAccountContractCode(location, code) } -func (e *interpreterEnvironment) RemoveAccountContractCode(address common.Address, name string) error { - return e.runtimeInterface.RemoveAccountContractCode(address, name) +func (e *interpreterEnvironment) RemoveAccountContractCode(location common.AddressLocation) error { + return e.runtimeInterface.RemoveAccountContractCode(location) } -func (e *interpreterEnvironment) RecordContractRemoval(address common.Address, name string) { - e.storage.recordContractUpdate(address, name, nil) +func (e *interpreterEnvironment) RecordContractRemoval(location common.AddressLocation) { + e.storage.recordContractUpdate(location, nil) } func (e *interpreterEnvironment) RecordContractUpdate( - address common.Address, - name string, + location common.AddressLocation, contractValue *interpreter.CompositeValue, ) { - e.storage.recordContractUpdate(address, name, contractValue) + e.storage.recordContractUpdate(location, contractValue) } func (e *interpreterEnvironment) TemporarilyRecordCode(location common.AddressLocation, code []byte) { @@ -564,10 +558,7 @@ func (e *interpreterEnvironment) getProgram( func (e *interpreterEnvironment) getCode(location common.Location) (code []byte, err error) { if addressLocation, ok := location.(common.AddressLocation); ok { errors.WrapPanic(func() { - code, err = e.runtimeInterface.GetAccountContractCode( - addressLocation.Address, - addressLocation.Name, - ) + code, err = e.runtimeInterface.GetAccountContractCode(addressLocation) }) } else { errors.WrapPanic(func() { @@ -617,7 +608,7 @@ func (e *interpreterEnvironment) newOnStatementHandler() interpreter.OnStatement return func(inter *interpreter.Interpreter, statement ast.Statement) { location := inter.Location - if !e.coverageReport.IsProgramInspected(location) { + if !e.coverageReport.IsLocationInspected(location) { program := inter.Program.Program e.coverageReport.InspectProgram(location, program) } @@ -765,6 +756,26 @@ func (e *interpreterEnvironment) newOnEventEmittedHandler() interpreter.OnEventE } } +func (e *interpreterEnvironment) newOnAccountLinkedHandler() interpreter.OnAccountLinkedFunc { + return func( + inter *interpreter.Interpreter, + locationRange interpreter.LocationRange, + addressValue interpreter.AddressValue, + pathValue interpreter.PathValue, + ) error { + e.EmitEvent( + inter, + stdlib.AccountLinkedEventType, + []interpreter.Value{ + addressValue, + pathValue, + }, + locationRange, + ) + return nil + } +} + func (e *interpreterEnvironment) newInjectedCompositeFieldsHandler() interpreter.InjectedCompositeFieldsHandlerFunc { return func( inter *interpreter.Interpreter, diff --git a/runtime/error_test.go b/runtime/error_test.go index 02998ec546..bc46431590 100644 --- a/runtime/error_test.go +++ b/runtime/error_test.go @@ -388,11 +388,7 @@ func TestRuntimeError(t *testing.T) { } return }, - getAccountContractCode: func(address Address, name string) ([]byte, error) { - location := common.AddressLocation{ - Name: name, - Address: address, - } + getAccountContractCode: func(location common.AddressLocation) ([]byte, error) { code := codes[location] return []byte(code), nil }, diff --git a/runtime/format/capability.go b/runtime/format/capability.go index af70a7341f..b5bc057e51 100644 --- a/runtime/format/capability.go +++ b/runtime/format/capability.go @@ -35,10 +35,3 @@ func StorageCapability(borrowType string, address string, path string) string { path, ) } - -func AccountCapability(address string) string { - return fmt.Sprintf( - "Capability(address: %s)", - address, - ) -} diff --git a/runtime/ft_test.go b/runtime/ft_test.go index 4358983860..f1d574017c 100644 --- a/runtime/ft_test.go +++ b/runtime/ft_test.go @@ -524,18 +524,10 @@ func BenchmarkRuntimeFungibleTokenTransfer(b *testing.B) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(b), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, diff --git a/runtime/import_test.go b/runtime/import_test.go index 76b3481166..9364254cf6 100644 --- a/runtime/import_test.go +++ b/runtime/import_test.go @@ -133,18 +133,10 @@ func TestCheckCyclicImports(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) ([]byte, error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) ([]byte, error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, diff --git a/runtime/interface.go b/runtime/interface.go index 9c8e805cda..e892df9497 100644 --- a/runtime/interface.go +++ b/runtime/interface.go @@ -79,11 +79,11 @@ type Interface interface { // RevokeAccountKey removes a key from an account by index. RevokeAccountKey(address Address, index int) (*AccountKey, error) // UpdateAccountContractCode updates the code associated with an account contract. - UpdateAccountContractCode(address Address, name string, code []byte) (err error) + UpdateAccountContractCode(location common.AddressLocation, code []byte) (err error) // GetAccountContractCode returns the code associated with an account contract. - GetAccountContractCode(address Address, name string) (code []byte, err error) + GetAccountContractCode(location common.AddressLocation) (code []byte, err error) // RemoveAccountContractCode removes the code associated with an account contract. - RemoveAccountContractCode(address Address, name string) (err error) + RemoveAccountContractCode(location common.AddressLocation) (err error) // GetSigningAccounts returns the signing accounts. GetSigningAccounts() ([]Address, error) // ProgramLog logs program logs. diff --git a/runtime/interpreter/config.go b/runtime/interpreter/config.go index bbf5540bb5..f2886ef8a5 100644 --- a/runtime/interpreter/config.go +++ b/runtime/interpreter/config.go @@ -64,4 +64,8 @@ type Config struct { AtreeStorageValidationEnabled bool // AtreeValueValidationEnabled determines if the validation of atree values is enabled AtreeValueValidationEnabled bool + // AccountLinkingAllowed determines if the account linking function is allowed to be used + AccountLinkingAllowed bool + // OnAccountLinked is triggered when an account is linked by the program + OnAccountLinked OnAccountLinkedFunc } diff --git a/runtime/interpreter/errors.go b/runtime/interpreter/errors.go index 8a23f449c8..ef6c86aed8 100644 --- a/runtime/interpreter/errors.go +++ b/runtime/interpreter/errors.go @@ -961,3 +961,18 @@ func (e InvalidAttachmentOperationTargetError) Error() string { e.Value, ) } + +// AccountLinkingForbiddenError is the error which is reported +// when a user uses the account link function, +// but account linking is not allowed +type AccountLinkingForbiddenError struct { + LocationRange +} + +var _ errors.UserError = AccountLinkingForbiddenError{} + +func (AccountLinkingForbiddenError) IsUserError() {} + +func (e AccountLinkingForbiddenError) Error() string { + return "account linking is not allowed" +} diff --git a/runtime/interpreter/interpreter.go b/runtime/interpreter/interpreter.go index aacddfc7d4..9e3393d525 100644 --- a/runtime/interpreter/interpreter.go +++ b/runtime/interpreter/interpreter.go @@ -112,6 +112,14 @@ type OnMeterComputationFunc func( intensity uint, ) +// OnAccountLinkedFunc is a function that is triggered when an account is linked by the program. +type OnAccountLinkedFunc func( + inter *Interpreter, + locationRange LocationRange, + address AddressValue, + path PathValue, +) error + // InjectedCompositeFieldsHandlerFunc is a function that handles storage reads. type InjectedCompositeFieldsHandlerFunc func( inter *Interpreter, @@ -3777,6 +3785,12 @@ func (interpreter *Interpreter) authAccountLinkAccountFunction(addressValue Addr func(invocation Invocation) Value { interpreter := invocation.Interpreter + if !interpreter.SharedState.Config.AccountLinkingAllowed { + panic(AccountLinkingForbiddenError{ + LocationRange: invocation.LocationRange, + }) + } + newCapabilityPath, ok := invocation.Arguments[0].(PathValue) if !ok { panic(errors.NewUnreachableError()) @@ -3802,6 +3816,19 @@ func (interpreter *Interpreter) authAccountLinkAccountFunction(addressValue Addr accountLinkValue, ) + onAccountLinked := interpreter.SharedState.Config.OnAccountLinked + if onAccountLinked != nil { + err := onAccountLinked( + interpreter, + invocation.LocationRange, + addressValue, + newCapabilityPath, + ) + if err != nil { + panic(err) + } + } + return NewSomeValueNonCopying( interpreter, NewStorageCapabilityValue( @@ -4746,3 +4773,31 @@ func (interpreter *Interpreter) DecodeTypeInfo(decoder *cbor.StreamDecoder) (atr func (interpreter *Interpreter) Storage() Storage { return interpreter.SharedState.Config.Storage } + +// ConfigureAccountLinkingAllowed configures if execution is allowed to use account linking, +// depending on the occurrence of the pragma declaration #allowAccountLinking. +// +// The pragma declaration must appear as a top-level declaration (i.e. not nested in the program), +// and must appear before all other declarations (i.e. at the top of the program). +// +// This requirement is also checked statically. +// +// This is a temporary feature, which is planned to get replaced by capability controllers, +// and a new Account type with entitlements. +func (interpreter *Interpreter) ConfigureAccountLinkingAllowed() { + config := interpreter.SharedState.Config + + config.AccountLinkingAllowed = false + + declarations := interpreter.Program.Program.Declarations() + if len(declarations) < 1 { + return + } + + pragmaDeclaration, isPragma := declarations[0].(*ast.PragmaDeclaration) + if !isPragma || !sema.IsAllowAccountLinkingPragma(pragmaDeclaration) { + return + } + + config.AccountLinkingAllowed = true +} diff --git a/runtime/interpreter/storage.go b/runtime/interpreter/storage.go index 1e3e795499..3eed4fea02 100644 --- a/runtime/interpreter/storage.go +++ b/runtime/interpreter/storage.go @@ -65,6 +65,7 @@ func ConvertStoredValue(gauge common.MemoryGauge, value atree.Value) (Value, err panic(errors.NewUnreachableError()) } return newArrayValueFromConstructor(gauge, staticType, value.Count(), func() *atree.Array { return value }), nil + case *atree.OrderedMap: typeInfo := value.Type() switch typeInfo := typeInfo.(type) { diff --git a/runtime/interpreter/value.go b/runtime/interpreter/value.go index 2ffff29b06..10fb8bd831 100644 --- a/runtime/interpreter/value.go +++ b/runtime/interpreter/value.go @@ -14948,7 +14948,10 @@ func (v *CompositeValue) Clone(interpreter *Interpreter) Value { return nil, nil, nil } - key := MustConvertStoredValue(interpreter, atreeKey).Clone(interpreter) + // The key is always interpreter.StringAtreeValue, + // an "atree-level string", not an interpreter.Value. + // Thus, we do not, and cannot, convert. + key := atreeKey value := MustConvertStoredValue(interpreter, atreeValue).Clone(interpreter) return key, value, nil diff --git a/runtime/missingmember_test.go b/runtime/missingmember_test.go index 9ba4704973..b1e427881e 100644 --- a/runtime/missingmember_test.go +++ b/runtime/missingmember_test.go @@ -2040,18 +2040,10 @@ pub contract ItemNFT: NonFungibleToken { return []Address{signerAddress}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -3860,18 +3852,10 @@ pub contract AuctionDutch { return []Address{signerAddress}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -4692,18 +4676,10 @@ pub contract ExampleMarketplace { return []Address{signerAddress}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, diff --git a/runtime/parser/comment.go b/runtime/parser/comment.go index 850446b09d..5dc763e1f4 100644 --- a/runtime/parser/comment.go +++ b/runtime/parser/comment.go @@ -29,12 +29,10 @@ func (p *parser) parseBlockComment() (endToken lexer.Token, ok bool) { switch p.current.Type { case lexer.TokenBlockCommentStart: p.next() - ok = false depth++ case lexer.TokenBlockCommentContent: p.next() - ok = false case lexer.TokenBlockCommentEnd: endToken = p.current diff --git a/runtime/predeclaredvalues_test.go b/runtime/predeclaredvalues_test.go index acd08dda45..069838164b 100644 --- a/runtime/predeclaredvalues_test.go +++ b/runtime/predeclaredvalues_test.go @@ -75,10 +75,10 @@ func TestRuntimePredeclaredValues(t *testing.T) { return []Address{common.MustBytesToAddress([]byte{0x1})}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, diff --git a/runtime/program_params_validation_test.go b/runtime/program_params_validation_test.go index 84516f7840..0ba6e4e0c4 100644 --- a/runtime/program_params_validation_test.go +++ b/runtime/program_params_validation_test.go @@ -605,11 +605,7 @@ func TestRuntimeTransactionParameterTypeValidation(t *testing.T) { runtimeInterface := &testRuntimeInterface{ storage: storage, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return contracts[location], nil }, meterMemory: func(_ common.MemoryUsage) error { diff --git a/runtime/resource_duplicate_test.go b/runtime/resource_duplicate_test.go index 061c4e1936..6e439a6a34 100644 --- a/runtime/resource_duplicate_test.go +++ b/runtime/resource_duplicate_test.go @@ -55,18 +55,10 @@ func TestRuntimeResourceDuplicationWithContractTransfer(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, diff --git a/runtime/resourcedictionary_test.go b/runtime/resourcedictionary_test.go index 7db007b87d..e43d231db1 100644 --- a/runtime/resourcedictionary_test.go +++ b/runtime/resourcedictionary_test.go @@ -114,14 +114,14 @@ func TestRuntimeResourceDictionaryValues(t *testing.T) { runtimeInterface := &testRuntimeInterface{ resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (bytes []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (bytes []byte, err error) { return accountCode, nil }, storage: newTestLedger(nil, nil), getSigningAccounts: func() ([]Address, error) { return []Address{Address(addressValue)}, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -467,7 +467,7 @@ func TestRuntimeResourceDictionaryValues_Nested(t *testing.T) { runtimeInterface := &testRuntimeInterface{ resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, getCode: func(_ Location) (bytes []byte, err error) { @@ -477,7 +477,7 @@ func TestRuntimeResourceDictionaryValues_Nested(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{Address(addressValue)}, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -661,10 +661,10 @@ func TestRuntimeResourceDictionaryValues_DictionaryTransfer(t *testing.T) { }, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) (err error) { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) (err error) { accountCode = code return nil }, @@ -798,10 +798,10 @@ func TestRuntimeResourceDictionaryValues_Removal(t *testing.T) { return []Address{signer}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) (err error) { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) (err error) { accountCode = code return nil }, @@ -912,10 +912,10 @@ func TestRuntimeSResourceDictionaryValues_Destruction(t *testing.T) { return []Address{signer}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -1053,10 +1053,10 @@ func TestRuntimeResourceDictionaryValues_Insertion(t *testing.T) { return []Address{signer}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -1206,10 +1206,10 @@ func TestRuntimeResourceDictionaryValues_ValueTransferAndDestroy(t *testing.T) { return signers, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -1340,14 +1340,14 @@ func BenchmarkRuntimeResourceDictionaryValues(b *testing.B) { runtimeInterface := &testRuntimeInterface{ resolveLocation: singleIdentifierLocationResolver(b), - getAccountContractCode: func(_ Address, _ string) (bytes []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (bytes []byte, err error) { return accountCode, nil }, storage: storage, getSigningAccounts: func() ([]Address, error) { return []Address{Address(addressValue)}, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, diff --git a/runtime/runtime.go b/runtime/runtime.go index 3cfdf350b1..9352d153f5 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -315,11 +315,11 @@ func (r *interpreterRuntime) NewTransactionExecutor(script Script, context Conte } func (r *interpreterRuntime) ExecuteTransaction(script Script, context Context) (err error) { - _, err = r.NewTransactionExecutor(script, context).Result() location := context.Location if _, ok := location.(common.TransactionLocation); !ok { return errors.NewUnexpectedError("invalid non-transaction location: %s", location) } + _, err = r.NewTransactionExecutor(script, context).Result() return err } diff --git a/runtime/runtime_memory_metering_test.go b/runtime/runtime_memory_metering_test.go index d88c218aff..196e4c0d77 100644 --- a/runtime/runtime_memory_metering_test.go +++ b/runtime/runtime_memory_metering_test.go @@ -77,7 +77,7 @@ func TestInterpreterAddressLocationMetering(t *testing.T) { meterMemory: func(usage common.MemoryUsage) error { return meter.MeterMemory(usage) }, - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, } @@ -145,19 +145,11 @@ func TestInterpreterElaborationImportMetering(t *testing.T) { return []Address{Address(addressValue)}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, @@ -795,7 +787,7 @@ func TestLogFunctionStringConversionMetering(t *testing.T) { meterMemory: func(usage common.MemoryUsage) error { return meter.MeterMemory(usage) }, - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCode, nil }, log: func(s string) { @@ -1071,3 +1063,149 @@ func TestMemoryMeteringErrors(t *testing.T) { assert.ErrorIs(t, err, testMemoryError{}) }) } + +func TestMeterEncoding(t *testing.T) { + + t.Parallel() + + t.Run("string", func(t *testing.T) { + + t.Parallel() + + rt := newTestInterpreterRuntime() + rt.defaultConfig.AtreeValidationEnabled = false + + address := common.MustBytesToAddress([]byte{0x1}) + storage := newTestLedger(nil, nil) + meter := newTestMemoryGauge() + + runtimeInterface := &testRuntimeInterface{ + storage: storage, + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil + }, + meterMemory: meter.MeterMemory, + } + + text := "A quick brown fox jumps over the lazy dog" + + err := rt.ExecuteTransaction( + Script{ + Source: []byte(fmt.Sprintf(` + transaction() { + prepare(acc: AuthAccount) { + var s = "%s" + acc.save(s, to:/storage/some_path) + } + }`, + text, + )), + }, + Context{ + Interface: runtimeInterface, + Location: common.TransactionLocation{}, + }, + ) + + require.NoError(t, err) + assert.Equal(t, 87, int(meter.getMemory(common.MemoryKindBytes))) + }) + + t.Run("string in loop", func(t *testing.T) { + + t.Parallel() + + rt := newTestInterpreterRuntime() + rt.defaultConfig.AtreeValidationEnabled = false + + address := common.MustBytesToAddress([]byte{0x1}) + storage := newTestLedger(nil, nil) + meter := newTestMemoryGauge() + + runtimeInterface := &testRuntimeInterface{ + storage: storage, + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil + }, + meterMemory: meter.MeterMemory, + } + + text := "A quick brown fox jumps over the lazy dog" + + err := rt.ExecuteTransaction( + Script{ + Source: []byte(fmt.Sprintf(` + transaction() { + prepare(acc: AuthAccount) { + var i = 0 + var s = "%s" + while i<1000 { + let path = StoragePath(identifier: "i".concat(i.toString()))! + acc.save(s, to: path) + i=i+1 + } + } + }`, + text, + )), + }, + Context{ + Interface: runtimeInterface, + Location: common.TransactionLocation{}, + }, + ) + + require.NoError(t, err) + assert.Equal(t, 62787, int(meter.getMemory(common.MemoryKindBytes))) + }) + + t.Run("composite", func(t *testing.T) { + + t.Parallel() + + rt := newTestInterpreterRuntime() + rt.defaultConfig.AtreeValidationEnabled = false + + address := common.MustBytesToAddress([]byte{0x1}) + storage := newTestLedger(nil, nil) + meter := newTestMemoryGauge() + + runtimeInterface := &testRuntimeInterface{ + storage: storage, + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil + }, + meterMemory: meter.MeterMemory, + } + + _, err := rt.ExecuteScript( + Script{ + Source: []byte(` + pub fun main() { + let acc = getAuthAccount(0x02) + var i = 0 + var f = Foo() + while i<1000 { + let path = StoragePath(identifier: "i".concat(i.toString()))! + acc.save(f, to: path) + i=i+1 + } + } + + pub struct Foo { + priv var id: Int + init() { + self.id = 123456789 + } + }`), + }, + Context{ + Interface: runtimeInterface, + Location: common.ScriptLocation{}, + }, + ) + + require.NoError(t, err) + assert.Equal(t, 76941, int(meter.getMemory(common.MemoryKindBytes))) + }) +} diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index dfe6404630..ffa1ccdf51 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -176,9 +176,9 @@ type testRuntimeInterface struct { getAccountKey func(address Address, index int) (*stdlib.AccountKey, error) removeAccountKey func(address Address, index int) (*stdlib.AccountKey, error) accountKeysCount func(address Address) (uint64, error) - updateAccountContractCode func(address Address, name string, code []byte) error - getAccountContractCode func(address Address, name string) (code []byte, err error) - removeAccountContractCode func(address Address, name string) (err error) + updateAccountContractCode func(location common.AddressLocation, code []byte) error + getAccountContractCode func(location common.AddressLocation) (code []byte, err error) + removeAccountContractCode func(location common.AddressLocation) (err error) getSigningAccounts func() ([]Address, error) log func(string) emitEvent func(cadence.Event) error @@ -375,12 +375,12 @@ func (i *testRuntimeInterface) RevokeAccountKey(address Address, index int) (*st return i.removeAccountKey(address, index) } -func (i *testRuntimeInterface) UpdateAccountContractCode(address Address, name string, code []byte) (err error) { +func (i *testRuntimeInterface) UpdateAccountContractCode(location common.AddressLocation, code []byte) (err error) { if i.updateAccountContractCode == nil { panic("must specify testRuntimeInterface.updateAccountContractCode") } - err = i.updateAccountContractCode(address, name, code) + err = i.updateAccountContractCode(location, code) if err != nil { return err } @@ -390,18 +390,18 @@ func (i *testRuntimeInterface) UpdateAccountContractCode(address Address, name s return nil } -func (i *testRuntimeInterface) GetAccountContractCode(address Address, name string) (code []byte, err error) { +func (i *testRuntimeInterface) GetAccountContractCode(location common.AddressLocation) (code []byte, err error) { if i.getAccountContractCode == nil { panic("must specify testRuntimeInterface.getAccountContractCode") } - return i.getAccountContractCode(address, name) + return i.getAccountContractCode(location) } -func (i *testRuntimeInterface) RemoveAccountContractCode(address Address, name string) (err error) { +func (i *testRuntimeInterface) RemoveAccountContractCode(location common.AddressLocation) (err error) { if i.removeAccountContractCode == nil { panic("must specify testRuntimeInterface.removeAccountContractCode") } - return i.removeAccountContractCode(address, name) + return i.removeAccountContractCode(location) } func (i *testRuntimeInterface) GetSigningAccounts() ([]Address, error) { @@ -1374,11 +1374,7 @@ func TestRuntimeTransactionWithArguments(t *testing.T) { return tc.authorizers, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return tc.contracts[location], nil }, log: func(message string) { @@ -3300,10 +3296,10 @@ func TestRuntimeContractAccount(t *testing.T) { return []Address{Address(addressValue)}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -3410,10 +3406,10 @@ func TestRuntimeInvokeContractFunction(t *testing.T) { return []Address{addressValue}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -3705,10 +3701,10 @@ func TestRuntimeContractNestedResource(t *testing.T) { return []Address{addressValue}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -3802,10 +3798,10 @@ func TestRuntimeStorageLoadedDestructionConcreteType(t *testing.T) { return []Address{addressValue}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(address Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -3897,10 +3893,10 @@ func TestRuntimeStorageLoadedDestructionAnyResource(t *testing.T) { return []Address{addressValue}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(address Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -3995,14 +3991,14 @@ func TestRuntimeStorageLoadedDestructionAfterRemoval(t *testing.T) { return []Address{addressValue}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(address Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, - removeAccountContractCode: func(_ Address, _ string) (err error) { + removeAccountContractCode: func(_ common.AddressLocation) (err error) { accountCode = nil return nil }, @@ -4232,18 +4228,10 @@ func TestRuntimeFungibleTokenUpdateAccountCode(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) (err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) (err error) { accountCodes[location] = code return nil }, @@ -4377,18 +4365,10 @@ func TestRuntimeFungibleTokenCreateAccount(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) (err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) (err error) { accountCodes[location] = code return nil }, @@ -4540,18 +4520,10 @@ func TestRuntimeInvokeStoredInterfaceFunction(t *testing.T) { return []Address{{0x1}}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -4861,10 +4833,10 @@ func TestRuntimeStoreIntegerTypes(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{addressValue.ToAddress()}, nil }, - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -4987,18 +4959,10 @@ func TestRuntimeResourceOwnerFieldUseComposite(t *testing.T) { return []Address{address}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -5191,19 +5155,11 @@ func TestRuntimeResourceOwnerFieldUseArray(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{address}, nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -5373,18 +5329,10 @@ func TestRuntimeResourceOwnerFieldUseDictionary(t *testing.T) { return []Address{address}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -5691,10 +5639,10 @@ func TestRuntimeContractWriteback(t *testing.T) { return []Address{Address(addressValue)}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) (err error) { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) (err error) { accountCode = code return nil }, @@ -5833,10 +5781,10 @@ func TestRuntimeStorageWriteback(t *testing.T) { return []Address{Address(addressValue)}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -6146,18 +6094,10 @@ func TestRuntimeDeployCodeCaching(t *testing.T) { return signerAddresses, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -6291,18 +6231,10 @@ func TestRuntimeUpdateCodeCaching(t *testing.T) { return signerAddresses, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -6534,18 +6466,10 @@ func TestRuntimeProgramsHitForToplevelPrograms(t *testing.T) { return signerAddresses, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -6722,10 +6646,10 @@ func TestRuntimeTransaction_ContractUpdate(t *testing.T) { }, }, nil }, - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -7150,19 +7074,11 @@ func TestRuntimeStackOverflow(t *testing.T) { return []Address{signerAddress}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = string(code) return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = []byte(accountCodes[location]) return code, nil }, @@ -7341,10 +7257,10 @@ func TestRuntimeInternalErrors(t *testing.T) { return []Address{addressValue}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return accountCode, nil }, - updateAccountContractCode: func(_ Address, _ string, code []byte) error { + updateAccountContractCode: func(_ common.AddressLocation, code []byte) error { accountCode = code return nil }, @@ -7524,10 +7440,11 @@ func TestRuntimeComputationMetring(t *testing.T) { t.Parallel() type test struct { - name string - code string - ok bool - expCompUsed uint + name string + code string + ok bool + hits uint + intensity uint } compLimit := uint(6) @@ -7538,8 +7455,9 @@ func TestRuntimeComputationMetring(t *testing.T) { code: ` while true {} `, - ok: false, - expCompUsed: compLimit, + ok: false, + hits: compLimit, + intensity: 6, }, { name: "Limited while loop", @@ -7549,24 +7467,36 @@ func TestRuntimeComputationMetring(t *testing.T) { i = i + 1 } `, - ok: false, - expCompUsed: compLimit, + ok: false, + hits: compLimit, + intensity: 6, }, { name: "statement + createArray + transferArray + too many for-in loop iterations", code: ` for i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] {} `, - ok: false, - expCompUsed: compLimit, + ok: false, + hits: compLimit, + intensity: 15, }, { - name: "statement + createArray + transferArray + some for-in loop iterations", + name: "statement + createArray + transferArray + two for-in loop iterations", code: ` for i in [1, 2] {} `, - ok: true, - expCompUsed: 5, + ok: true, + hits: 5, + intensity: 6, + }, + { + name: "statement + functionInvocation + encoding", + code: ` + acc.save("A quick brown fox jumps over the lazy dog", to:/storage/some_path) + `, + ok: true, + hits: 3, + intensity: 88, }, } @@ -7578,7 +7508,7 @@ func TestRuntimeComputationMetring(t *testing.T) { fmt.Sprintf( ` transaction { - prepare() { + prepare(acc: AuthAccount) { %s } } @@ -7590,19 +7520,22 @@ func TestRuntimeComputationMetring(t *testing.T) { runtime := newTestInterpreterRuntime() compErr := errors.New("computation exceeded limit") - var compUsed uint + var hits, totalIntensity uint meterComputationFunc := func(kind common.ComputationKind, intensity uint) error { - compUsed++ - if compUsed >= compLimit { + hits++ + totalIntensity += intensity + if hits >= compLimit { return compErr } return nil } + address := common.MustBytesToAddress([]byte{0x1}) + runtimeInterface := &testRuntimeInterface{ storage: newTestLedger(nil, nil), getSigningAccounts: func() ([]Address, error) { - return nil, nil + return []Address{address}, nil }, meterComputation: meterComputationFunc, } @@ -7628,7 +7561,8 @@ func TestRuntimeComputationMetring(t *testing.T) { require.ErrorAs(t, err.(Error).Unwrap(), &compErr) } - require.Equal(t, test.expCompUsed, compUsed) + assert.Equal(t, test.hits, hits) + assert.Equal(t, test.intensity, totalIntensity) }) } } @@ -7837,18 +7771,10 @@ func TestRuntimeTypeMismatchErrorMessage(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) (err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) (err error) { accountCodes[location] = code return nil }, diff --git a/runtime/script_executor.go b/runtime/script_executor.go index b430b804e4..ced232ac18 100644 --- a/runtime/script_executor.go +++ b/runtime/script_executor.go @@ -228,6 +228,8 @@ func (executor *interpreterScriptExecutor) scriptExecutionFunction() InterpretFu err = internalErr }) + inter.ConfigureAccountLinkingAllowed() + values, err := validateArgumentParams( inter, executor.environment, @@ -238,6 +240,7 @@ func (executor *interpreterScriptExecutor) scriptExecutionFunction() InterpretFu if err != nil { return nil, err } + return inter.Invoke("main", values...) } } diff --git a/runtime/sema/authaccount_type.go b/runtime/sema/authaccount_type.go index 4ac83c8ee1..53606d550b 100644 --- a/runtime/sema/authaccount_type.go +++ b/runtime/sema/authaccount_type.go @@ -54,6 +54,8 @@ const AuthAccountTypeInboxClaimFunctionName = "claim" var AuthAccountTypeLinkAccountFunctionType *FunctionType +var AuthAccountTypeLinkAccountFunctionTypePathParameterType = PrivatePathType + // AuthAccountType represents the authorized access to an account. // Access to an AuthAccount means having full access to its storage, public keys, and code. // Only signed transactions can get the AuthAccount for an account. @@ -76,9 +78,11 @@ var AuthAccountType = func() *CompositeType { AuthAccountTypeLinkAccountFunctionType = &FunctionType{ Parameters: []Parameter{ { - Label: ArgumentLabelNotRequired, - Identifier: "newCapabilityPath", - TypeAnnotation: CapabilityPathTypeAnnotation, + Label: ArgumentLabelNotRequired, + Identifier: "newCapabilityPath", + TypeAnnotation: NewTypeAnnotation( + AuthAccountTypeLinkAccountFunctionTypePathParameterType, + ), }, }, ReturnTypeAnnotation: NewTypeAnnotation( diff --git a/runtime/sema/checker.go b/runtime/sema/checker.go index ad879b312d..bba2fc9d0f 100644 --- a/runtime/sema/checker.go +++ b/runtime/sema/checker.go @@ -121,7 +121,6 @@ type Checker struct { inInvocation bool inCreate bool isChecked bool - allowAccountLinking bool } var _ ast.DeclarationVisitor[struct{}] = &Checker{} @@ -404,20 +403,18 @@ func (checker *Checker) CheckProgram(program *ast.Program) { for _, declaration := range declarations { // A pragma declaration #allowAccountLinking determines - // if the program is allowed to use the account linking. + // if the program is allowed to use account linking. // // It must appear as a top-level declaration (i.e. not nested in the program), // and must appear before all other declarations (i.e. at the top of the program). // - // This is a temporary feature, which is planned to get replaced - // by capability controllers, a new Account type, and account entitlements. + // This is a temporary feature, which is planned to get replaced by capability controllers, + // and a new Account type with entitlements. if pragmaDeclaration, isPragma := declaration.(*ast.PragmaDeclaration); isPragma { if IsAllowAccountLinkingPragma(pragmaDeclaration) { if rejectAllowAccountLinkingPragma { checker.reportInvalidNonHeaderPragma(pragmaDeclaration) - } else { - checker.allowAccountLinking = true } continue } @@ -2059,17 +2056,20 @@ func (checker *Checker) rewritePostConditions(postConditions []*ast.Condition) P } for _, extractedExpression := range extractedExpressions { + expression := extractedExpression.Expression + startPos := expression.StartPosition() // NOTE: no need to check the before statements or update elaboration here: // The before statements are visited/checked later variableDeclaration := ast.NewEmptyVariableDeclaration(checker.memoryGauge) + variableDeclaration.StartPos = startPos variableDeclaration.Identifier = extractedExpression.Identifier variableDeclaration.Transfer = ast.NewTransfer( checker.memoryGauge, ast.TransferOperationCopy, - ast.EmptyPosition, + startPos, ) - variableDeclaration.Value = extractedExpression.Expression + variableDeclaration.Value = expression beforeStatements = append(beforeStatements, variableDeclaration, @@ -2477,8 +2477,7 @@ func (checker *Checker) isAvailableMember(expressionType Type, identifier string if expressionType == AuthAccountType && identifier == AuthAccountTypeLinkAccountFunctionName { - return checker.Config.AccountLinkingEnabled && - checker.allowAccountLinking + return checker.Config.AccountLinkingEnabled } return true diff --git a/runtime/sema/gen/main.go b/runtime/sema/gen/main.go index baba218d47..fb6a932eca 100644 --- a/runtime/sema/gen/main.go +++ b/runtime/sema/gen/main.go @@ -34,6 +34,7 @@ import ( "github.com/onflow/cadence/runtime/common" "github.com/onflow/cadence/runtime/parser" "github.com/onflow/cadence/runtime/pretty" + "github.com/onflow/cadence/runtime/sema" "github.com/dave/dst" ) @@ -265,6 +266,7 @@ func (g *generator) addFunctionTypeDeclaration( ReturnTypeAnnotation: decl.ReturnTypeAnnotation, ParameterTypeAnnotations: parameterTypeAnnotations, }, + decl.ParameterList, decl.TypeParameterList, typeParams, ), @@ -501,7 +503,7 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { } case *ast.FunctionType: - return functionTypeExpr(t, nil, typeParams) + return functionTypeExpr(t, nil, nil, typeParams) case *ast.InstantiationType: typeArguments := t.TypeArguments @@ -533,6 +535,7 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { func functionTypeExpr( t *ast.FunctionType, + parameters *ast.ParameterList, typeParameterList *ast.TypeParameterList, typeParams map[string]string, ) dst.Expr { @@ -583,16 +586,48 @@ func functionTypeExpr( if parameterCount > 0 { parameterExprs := make([]dst.Expr, 0, parameterCount) - for _, parameterTypeAnnotation := range parameterTypeAnnotations { + for parameterIndex, parameterTypeAnnotation := range parameterTypeAnnotations { + + var parameterElements []dst.Expr + + if parameters != nil { + parameter := parameters.Parameters[parameterIndex] + + if parameter.Label != "" { + var lit dst.Expr + if parameter.Label == sema.ArgumentLabelNotRequired { + lit = &dst.Ident{ + Path: "github.com/onflow/cadence/runtime/sema", + Name: "ArgumentLabelNotRequired", + } + } else { + lit = goStringLit(parameter.Label) + } + + parameterElements = append( + parameterElements, + goKeyValue("Label", lit), + ) + } + + parameterElements = append( + parameterElements, + goKeyValue("Identifier", goStringLit(parameter.Identifier.Identifier)), + ) + } + + parameterElements = append( + parameterElements, + goKeyValue( + "TypeAnnotation", + typeAnnotationCallExpr(typeExpr(parameterTypeAnnotation.Type, typeParams)), + ), + ) parameterExpr := &dst.CompositeLit{ - Elts: []dst.Expr{ - goKeyValue( - "TypeAnnotation", - typeAnnotationCallExpr(typeExpr(parameterTypeAnnotation.Type, typeParams)), - ), - }, + Elts: parameterElements, } + parameterExpr.Decorations().Before = dst.NewLine parameterExpr.Decorations().After = dst.NewLine diff --git a/runtime/sema/gen/testdata/docstrings.golden.go b/runtime/sema/gen/testdata/docstrings.golden.go index f2ab0176c1..2459e56e5c 100644 --- a/runtime/sema/gen/testdata/docstrings.golden.go +++ b/runtime/sema/gen/testdata/docstrings.golden.go @@ -48,6 +48,7 @@ const DocstringsTypeNwnFunctionName = "nwn" var DocstringsTypeNwnFunctionType = &FunctionType{ Parameters: []Parameter{ { + Identifier: "x", TypeAnnotation: NewTypeAnnotation(IntType), }, }, diff --git a/runtime/sema/gen/testdata/functions.golden.go b/runtime/sema/gen/testdata/functions.golden.go index e20426da3f..ebe3835954 100644 --- a/runtime/sema/gen/testdata/functions.golden.go +++ b/runtime/sema/gen/testdata/functions.golden.go @@ -22,6 +22,7 @@ package sema import ( "github.com/onflow/cadence/runtime/ast" "github.com/onflow/cadence/runtime/common" + "github.com/onflow/cadence/runtime/sema" ) const TestTypeNothingFunctionName = "nothing" @@ -41,9 +42,12 @@ const TestTypeParamsFunctionName = "params" var TestTypeParamsFunctionType = &FunctionType{ Parameters: []Parameter{ { + Identifier: "a", TypeAnnotation: NewTypeAnnotation(IntType), }, { + Label: sema.ArgumentLabelNotRequired, + Identifier: "b", TypeAnnotation: NewTypeAnnotation(StringType), }, }, @@ -73,9 +77,12 @@ const TestTypeParamsAndReturnFunctionName = "paramsAndReturn" var TestTypeParamsAndReturnFunctionType = &FunctionType{ Parameters: []Parameter{ { + Identifier: "a", TypeAnnotation: NewTypeAnnotation(IntType), }, { + Label: sema.ArgumentLabelNotRequired, + Identifier: "b", TypeAnnotation: NewTypeAnnotation(StringType), }, }, @@ -141,6 +148,7 @@ var TestTypeTypeParamWithBoundAndParamFunctionType = &FunctionType{ }, Parameters: []Parameter{ { + Identifier: "t", TypeAnnotation: NewTypeAnnotation(&GenericType{ TypeParameter: TestTypeTypeParamWithBoundAndParamFunctionTypeParameterT, }), diff --git a/runtime/sharedstate_test.go b/runtime/sharedstate_test.go index e7ef26e9d6..e4df0d0c04 100644 --- a/runtime/sharedstate_test.go +++ b/runtime/sharedstate_test.go @@ -83,27 +83,15 @@ func TestRuntimeSharedState(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return []Address{signerAddress}, nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, - removeAccountContractCode: func(address Address, name string) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + removeAccountContractCode: func(location common.AddressLocation) error { delete(accountCodes, location) return nil }, diff --git a/runtime/stdlib/account.go b/runtime/stdlib/account.go index 0878099ca4..ae671ee774 100644 --- a/runtime/stdlib/account.go +++ b/runtime/stdlib/account.go @@ -1117,7 +1117,7 @@ func newAccountContractsGetNamesFunction( type AccountContractProvider interface { // GetAccountContractCode returns the code associated with an account contract. - GetAccountContractCode(address common.Address, name string) ([]byte, error) + GetAccountContractCode(location common.AddressLocation) ([]byte, error) } func newAccountContractsGetFunction( @@ -1138,11 +1138,12 @@ func newAccountContractsGetFunction( panic(errors.NewUnreachableError()) } name := nameValue.Str + location := common.NewAddressLocation(invocation.Interpreter, address, name) var code []byte var err error errors.WrapPanic(func() { - code, err = provider.GetAccountContractCode(address, name) + code, err = provider.GetAccountContractCode(location) }) if err != nil { panic(err) @@ -1189,6 +1190,7 @@ func newAccountContractsBorrowFunction( panic(errors.NewUnreachableError()) } name := nameValue.Str + location := common.NewAddressLocation(invocation.Interpreter, address, name) typeParameterPair := invocation.TypeParameterTypes.Oldest() if typeParameterPair == nil { @@ -1206,7 +1208,7 @@ func newAccountContractsBorrowFunction( var code []byte var err error errors.WrapPanic(func() { - code, err = handler.GetAccountContractCode(address, name) + code, err = handler.GetAccountContractCode(location) }) if err != nil { panic(err) @@ -1256,8 +1258,8 @@ type AccountContractAdditionHandler interface { getAndSetProgram bool, ) (*interpreter.Program, error) // UpdateAccountContractCode updates the code associated with an account contract. - UpdateAccountContractCode(address common.Address, name string, code []byte) error - RecordContractUpdate(address common.Address, name string, value *interpreter.CompositeValue) + UpdateAccountContractCode(location common.AddressLocation, code []byte) error + RecordContractUpdate(location common.AddressLocation, value *interpreter.CompositeValue) InterpretContract( location common.AddressLocation, program *interpreter.Program, @@ -1318,7 +1320,9 @@ func newAuthAccountContractsChangeFunction( } address := addressValue.ToAddress() - existingCode, err := handler.GetAccountContractCode(address, contractName) + location := common.NewAddressLocation(invocation.Interpreter, address, contractName) + + existingCode, err := handler.GetAccountContractCode(location) if err != nil { panic(err) } @@ -1349,9 +1353,6 @@ func newAuthAccountContractsChangeFunction( } // Check the code - - location := common.NewAddressLocation(invocation.Interpreter, address, contractName) - handleContractUpdateError := func(err error) { if err == nil { return @@ -1453,7 +1454,7 @@ func newAuthAccountContractsChangeFunction( // Validate the contract update if isUpdate { - oldCode, err := handler.GetAccountContractCode(address, contractName) + oldCode, err := handler.GetAccountContractCode(location) handleContractUpdateError(err) oldProgram, err := parser.ParseProgram( @@ -1484,9 +1485,7 @@ func newAuthAccountContractsChangeFunction( handler, location, program, - declaredName, code, - addressValue, contractType, constructorArguments, constructorArgumentTypes, @@ -1607,9 +1606,7 @@ func updateAccountContractCode( handler AccountContractAdditionHandler, location common.AddressLocation, program *interpreter.Program, - name string, code []byte, - addressValue interpreter.AddressValue, contractType *sema.CompositeType, constructorArguments []interpreter.Value, constructorArgumentTypes []sema.Type, @@ -1631,8 +1628,6 @@ func updateAccountContractCode( createContract := contractType != nil && options.createContract - address := addressValue.ToAddress() - var err error if createContract { @@ -1640,7 +1635,6 @@ func updateAccountContractCode( handler, location, program, - address, contractType, constructorArguments, constructorArgumentTypes, @@ -1653,7 +1647,7 @@ func updateAccountContractCode( // NOTE: only update account code if contract instantiation succeeded errors.WrapPanic(func() { - err = handler.UpdateAccountContractCode(address, name, code) + err = handler.UpdateAccountContractCode(location, code) }) if err != nil { return err @@ -1664,8 +1658,7 @@ func updateAccountContractCode( // until the end of the execution of the program handler.RecordContractUpdate( - address, - name, + location, contractValue, ) } @@ -1709,7 +1702,6 @@ func instantiateContract( handler AccountContractAdditionHandler, location common.AddressLocation, program *interpreter.Program, - address common.Address, contractType *sema.CompositeType, constructorArguments []interpreter.Value, argumentTypes []sema.Type, @@ -1769,7 +1761,7 @@ func instantiateContract( program, contractType.Identifier, DeployedContractConstructorInvocation{ - Address: address, + Address: location.Address, ContractType: contractType, ConstructorArguments: constructorArguments, ArgumentTypes: argumentTypes, @@ -1781,8 +1773,8 @@ func instantiateContract( type AccountContractRemovalHandler interface { EventEmitter AccountContractProvider - RemoveAccountContractCode(address common.Address, name string) error - RecordContractRemoval(address common.Address, name string) + RemoveAccountContractCode(location common.AddressLocation) error + RecordContractRemoval(location common.AddressLocation) } func newAuthAccountContractsRemoveFunction( @@ -1805,13 +1797,14 @@ func newAuthAccountContractsRemoveFunction( panic(errors.NewUnreachableError()) } name := nameValue.Str + location := common.NewAddressLocation(invocation.Interpreter, address, name) // Get the current code var code []byte var err error errors.WrapPanic(func() { - code, err = handler.GetAccountContractCode(address, name) + code, err = handler.GetAccountContractCode(location) }) if err != nil { panic(err) @@ -1839,7 +1832,7 @@ func newAuthAccountContractsRemoveFunction( } errors.WrapPanic(func() { - err = handler.RemoveAccountContractCode(address, name) + err = handler.RemoveAccountContractCode(location) }) if err != nil { panic(err) @@ -1848,7 +1841,7 @@ func newAuthAccountContractsRemoveFunction( // NOTE: the contract recording function delays the write // until the end of the execution of the program - handler.RecordContractRemoval(address, name) + handler.RecordContractRemoval(location) codeHashValue := CodeToHashValue(inter, code) diff --git a/runtime/stdlib/flow.go b/runtime/stdlib/flow.go index 237dc9aa65..ff8ea53df3 100644 --- a/runtime/stdlib/flow.go +++ b/runtime/stdlib/flow.go @@ -74,6 +74,10 @@ func (l FlowLocation) Description() string { return FlowLocationPrefix } +func (l FlowLocation) ID() string { + return FlowLocationPrefix +} + func (l FlowLocation) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Type string @@ -105,11 +109,6 @@ func decodeFlowLocationTypeID(typeID string) (FlowLocation, string, error) { parts := strings.SplitN(typeID, ".", 2) - pieceCount := len(parts) - if pieceCount == 1 { - return newError("missing qualified identifier") - } - prefix := parts[0] if prefix != FlowLocationPrefix { @@ -121,7 +120,11 @@ func decodeFlowLocationTypeID(typeID string) (FlowLocation, string, error) { ) } - qualifiedIdentifier := parts[1] + var qualifiedIdentifier string + pieceCount := len(parts) + if pieceCount > 1 { + qualifiedIdentifier = parts[1] + } return FlowLocation{}, qualifiedIdentifier, nil } @@ -271,3 +274,14 @@ var AccountInboxClaimedEventType = newFlowEventType( AccountEventRecipientParameter, AccountEventNameParameter, ) + +var AccountLinkedEventType = newFlowEventType( + "AccountLinked", + AccountEventAddressParameter, + sema.Parameter{ + Identifier: "path", + TypeAnnotation: sema.NewTypeAnnotation( + sema.AuthAccountTypeLinkAccountFunctionTypePathParameterType, + ), + }, +) diff --git a/runtime/stdlib/flow_test.go b/runtime/stdlib/flow_test.go index ef90e58512..da19c17a20 100644 --- a/runtime/stdlib/flow_test.go +++ b/runtime/stdlib/flow_test.go @@ -78,6 +78,19 @@ func TestFlowLocationTypeID(t *testing.T) { ) } +func TestFlowLocationID(t *testing.T) { + + t.Parallel() + + location, _, err := decodeFlowLocationTypeID("flow.Bar.Baz") + require.NoError(t, err) + + assert.Equal(t, + "flow", + location.ID(), + ) +} + func TestDecodeFlowLocationTypeID(t *testing.T) { t.Parallel() @@ -90,15 +103,35 @@ func TestDecodeFlowLocationTypeID(t *testing.T) { require.EqualError(t, err, "invalid Flow location type ID: missing prefix") }) - t.Run("missing qualified identifier", func(t *testing.T) { + t.Run("missing qualified identifier part", func(t *testing.T) { + + t.Parallel() + + location, qualifiedIdentifier, err := decodeFlowLocationTypeID("flow") + require.NoError(t, err) + + assert.Equal(t, + FlowLocation{}, + location, + ) + assert.Equal(t, "", qualifiedIdentifier) + }) + + t.Run("empty qualified identifier", func(t *testing.T) { t.Parallel() - _, _, err := decodeFlowLocationTypeID("flow") - require.EqualError(t, err, "invalid Flow location type ID: missing qualified identifier") + location, qualifiedIdentifier, err := decodeFlowLocationTypeID("flow.") + require.NoError(t, err) + + assert.Equal(t, + FlowLocation{}, + location, + ) + assert.Equal(t, "", qualifiedIdentifier) }) - t.Run("missing qualified identifier", func(t *testing.T) { + t.Run("invalid prefix", func(t *testing.T) { t.Parallel() diff --git a/runtime/storage.go b/runtime/storage.go index d0fa5ae48e..c0a41147c9 100644 --- a/runtime/storage.go +++ b/runtime/storage.go @@ -161,11 +161,10 @@ func (s *Storage) storeNewStorageMap(address atree.Address, domain string) *inte } func (s *Storage) recordContractUpdate( - address common.Address, - name string, + location common.AddressLocation, contractValue *interpreter.CompositeValue, ) { - key := interpreter.NewStorageKey(s.memoryGauge, address, name) + key := interpreter.NewStorageKey(s.memoryGauge, location.Address, location.Name) // NOTE: do NOT delete the map entry, // otherwise the removal write is lost @@ -229,6 +228,13 @@ func (s *Storage) Commit(inter *interpreter.Interpreter, commitContractUpdates b // Commit the underlying slab storage's writes + size := s.PersistentSlabStorage.DeltasSizeWithoutTempAddresses() + if size > 0 { + inter.ReportComputation(common.ComputationKindEncodeValue, uint(size)) + usage := common.NewBytesMemoryUsage(int(size)) + common.UseMemory(s.memoryGauge, usage) + } + deltas := s.PersistentSlabStorage.DeltasWithoutTempAddresses() common.UseMemory(s.memoryGauge, common.NewAtreeEncodedSlabMemoryUsage(deltas)) diff --git a/runtime/storage_test.go b/runtime/storage_test.go index 9d566fc615..0128426f2b 100644 --- a/runtime/storage_test.go +++ b/runtime/storage_test.go @@ -526,19 +526,11 @@ func TestRuntimePublicCapabilityBorrowTypeConfusion(t *testing.T) { return []Address{signingAddress}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, @@ -765,19 +757,11 @@ func TestRuntimeTopShotContractDeployment(t *testing.T) { return []Address{testAddress}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = string(code) return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = []byte(accountCodes[location]) return code, nil }, @@ -868,19 +852,11 @@ func TestRuntimeTopShotBatchTransfer(t *testing.T) { return []Address{signerAddress}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = string(code) return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = []byte(accountCodes[location]) return code, nil }, @@ -1156,19 +1132,11 @@ func TestRuntimeBatchMintAndTransfer(t *testing.T) { return []Address{signerAddress}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = string(code) return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = []byte(accountCodes[location]) return code, nil }, @@ -1522,19 +1490,11 @@ func TestRuntimeStorageReferenceCast(t *testing.T) { return []Address{signerAddress}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, @@ -1827,19 +1787,11 @@ func TestRuntimeResourceOwnerChange(t *testing.T) { return signers, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, @@ -2241,18 +2193,10 @@ transaction { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -2377,18 +2321,10 @@ func TestRuntimeReferenceOwnerAccess(t *testing.T) { return signers, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -2514,18 +2450,10 @@ func TestRuntimeReferenceOwnerAccess(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -2660,18 +2588,10 @@ func TestRuntimeReferenceOwnerAccess(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -2792,18 +2712,10 @@ func TestRuntimeReferenceOwnerAccess(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -2922,18 +2834,10 @@ func TestRuntimeReferenceOwnerAccess(t *testing.T) { return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { return accountCodes[location], nil }, - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, @@ -3061,19 +2965,11 @@ func TestRuntimeStorageEnumCase(t *testing.T) { return []Address{address}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, @@ -3287,19 +3183,11 @@ func TestRuntimeStorageInternalAccess(t *testing.T) { return []Address{address}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { code = accountCodes[location] return code, nil }, @@ -3432,20 +3320,11 @@ func TestRuntimeStorageIteration(t *testing.T) { return []Address{address}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } - + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { if contractIsBroken { // Contract no longer has the type return []byte(`pub contract Test {}`), nil @@ -3566,20 +3445,11 @@ func TestRuntimeStorageIteration(t *testing.T) { return []Address{address}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } - + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { if contractIsBroken { // Contract has a syntax problem return []byte(`BROKEN`), nil @@ -3702,20 +3572,11 @@ func TestRuntimeStorageIteration(t *testing.T) { return []Address{address}, nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, name string, code []byte) error { - location := common.AddressLocation{ - Address: address, - Name: name, - } + updateAccountContractCode: func(location common.AddressLocation, code []byte) error { accountCodes[location] = code return nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { - location := common.AddressLocation{ - Address: address, - Name: name, - } - + getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { if contractIsBroken { // Contract has a semantic error. i.e: cannot find `Bar` return []byte(`pub contract Test { diff --git a/runtime/tests/checker/account_test.go b/runtime/tests/checker/account_test.go index 8d78657d66..39c5bd2839 100644 --- a/runtime/tests/checker/account_test.go +++ b/runtime/tests/checker/account_test.go @@ -1120,37 +1120,27 @@ func TestCheckAccount_linkAccount(t *testing.T) { type testCase struct { domain common.PathDomain enabled bool - allowed bool } test := func(tc testCase) { testName := fmt.Sprintf( - "%s, enabled=%v, allowed=%v", + "%s, enabled=%v", tc.domain.Identifier(), tc.enabled, - tc.allowed, ) t.Run(testName, func(t *testing.T) { t.Parallel() - var pragma string - if tc.allowed { - pragma = "#allowAccountLinking" - } - code := fmt.Sprintf(` - %s - resource R {} fun test(authAccount: AuthAccount): Capability<&AuthAccount>? { return authAccount.linkAccount(/%s/r) } `, - pragma, tc.domain.Identifier(), ) @@ -1163,41 +1153,30 @@ func TestCheckAccount_linkAccount(t *testing.T) { }, ) - if tc.enabled { - if tc.allowed { - switch tc.domain { - case common.PathDomainPrivate, common.PathDomainPublic: - require.NoError(t, err) - - default: - errs := RequireCheckerErrors(t, err, 1) + if !tc.enabled { + errs := RequireCheckerErrors(t, err, 1) - require.IsType(t, &sema.TypeMismatchError{}, errs[0]) - } - } else { - errs := RequireCheckerErrors(t, err, 1) + require.IsType(t, &sema.NotDeclaredMemberError{}, errs[0]) + return + } - require.IsType(t, &sema.NotDeclaredMemberError{}, errs[0]) - } - } else { + if tc.domain != common.PathDomainPrivate { errs := RequireCheckerErrors(t, err, 1) - require.IsType(t, &sema.NotDeclaredMemberError{}, errs[0]) + require.IsType(t, &sema.TypeMismatchError{}, errs[0]) + return } + + require.NoError(t, err) }) } - options := []bool{true, false} - - for _, enabled := range options { - for _, allowed := range options { - for _, domain := range common.AllPathDomainsByIdentifier { - test(testCase{ - domain: domain, - enabled: enabled, - allowed: allowed, - }) - } + for _, enabled := range []bool{true, false} { + for _, domain := range common.AllPathDomainsByIdentifier { + test(testCase{ + domain: domain, + enabled: enabled, + }) } } } diff --git a/runtime/tests/checker/conditions_test.go b/runtime/tests/checker/conditions_test.go index 600ebbceb4..12ca315385 100644 --- a/runtime/tests/checker/conditions_test.go +++ b/runtime/tests/checker/conditions_test.go @@ -24,6 +24,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/onflow/cadence/runtime/ast" "github.com/onflow/cadence/runtime/sema" ) @@ -520,3 +521,39 @@ func TestCheckConditionCreateBefore(t *testing.T) { require.ErrorAs(t, errs[0], ¬CallableErr) require.Equal(t, sema.IntType, notCallableErr.Type) } + +func TestCheckRewrittenPostConditions(t *testing.T) { + + t.Parallel() + + checker, err := ParseAndCheck(t, ` + fun test(x: Int) { + post { + before(x) == 0 + } + } + `) + require.NoError(t, err) + + declarations := checker.Program.Declarations() + require.Len(t, declarations, 1) + firstDeclaration := declarations[0] + + require.IsType(t, &ast.FunctionDeclaration{}, firstDeclaration) + functionDeclaration := firstDeclaration.(*ast.FunctionDeclaration) + + postConditions := functionDeclaration.FunctionBlock.PostConditions + postConditionsRewrite := checker.Elaboration.PostConditionsRewrite(postConditions) + + require.Len(t, postConditionsRewrite.RewrittenPostConditions, 1) + require.Len(t, postConditionsRewrite.BeforeStatements, 1) + + beforeStatement := postConditionsRewrite.BeforeStatements[0] + + ast.Inspect(beforeStatement, func(element ast.Element) bool { + if element != nil { + assert.Positive(t, element.StartPosition().Line) + } + return true + }) +} diff --git a/runtime/tests/checker/pragma_test.go b/runtime/tests/checker/pragma_test.go index abfa2c0c20..07a9ca9f39 100644 --- a/runtime/tests/checker/pragma_test.go +++ b/runtime/tests/checker/pragma_test.go @@ -113,6 +113,19 @@ func TestCheckAllowAccountLinkingPragma(t *testing.T) { require.NoError(t, err) }) + t.Run("top-level, after other pragmas", func(t *testing.T) { + t.Parallel() + + _, err := ParseAndCheck(t, ` + #someOtherPragma + #allowAccountLinking + + let x = 1 + `) + errs := RequireCheckerErrors(t, err, 1) + assert.IsType(t, &sema.InvalidPragmaError{}, errs[0]) + }) + t.Run("top-level, after other declarations", func(t *testing.T) { t.Parallel() diff --git a/runtime/tests/fuzz/crashers_test.go b/runtime/tests/fuzz/crashers_test.go index bcfcc8aba9..c24a5cff48 100644 --- a/runtime/tests/fuzz/crashers_test.go +++ b/runtime/tests/fuzz/crashers_test.go @@ -34,14 +34,11 @@ func TestCrashers(t *testing.T) { t.Parallel() - f, err := os.Open(crashersDir) + files, err := os.ReadDir(crashersDir) if err != nil { return } - files, err := f.Readdir(-1) - _ = f.Close() - for _, file := range files { name := file.Name() diff --git a/runtime/tests/interpreter/capability_test.go b/runtime/tests/interpreter/capability_test.go index 2d6dd575cc..28517c2f1e 100644 --- a/runtime/tests/interpreter/capability_test.go +++ b/runtime/tests/interpreter/capability_test.go @@ -473,30 +473,26 @@ func TestInterpretCapability_borrow(t *testing.T) { ` #allowAccountLinking - fun link() { - account.linkAccount(/public/acct) + fun link(): Capability { + return account.linkAccount(/private/acct)! } - fun address(_ path: CapabilityPath): Address { - return account.getCapability(path).borrow<&AuthAccount>()!.address + fun address(_ cap: Capability): Address { + return cap.borrow<&AuthAccount>()!.address } - fun borrow(): Address { - return address(/public/acct) + fun borrow(_ cap: Capability): Address { + return address(cap) } - fun borrowAuth(): auth &AuthAccount? { - return account.getCapability(/public/acct).borrow() + fun borrowAuth(_ cap: Capability): auth &AuthAccount? { + return cap.borrow() } - fun nonExistent(): Address { - return address(/public/nonExistent) - } - - fun unlinkAfterBorrow(): Address { - let ref = account.getCapability(/public/acct).borrow<&AuthAccount>()! + fun unlinkAfterBorrow(_ cap: Capability): Address { + let ref = cap.borrow<&AuthAccount>()! - account.unlink(/public/acct) + account.unlink(/private/acct) return ref.address } @@ -508,12 +504,12 @@ func TestInterpretCapability_borrow(t *testing.T) { // link - _, err := inter.Invoke("link") + capability, err := inter.Invoke("link") require.NoError(t, err) t.Run("borrow", func(t *testing.T) { - value, err := inter.Invoke("borrow") + value, err := inter.Invoke("borrow", capability) require.NoError(t, err) RequireValuesEqual(t, @@ -525,23 +521,15 @@ func TestInterpretCapability_borrow(t *testing.T) { t.Run("borrowAuth", func(t *testing.T) { - value, err := inter.Invoke("borrowAuth") + value, err := inter.Invoke("borrowAuth", capability) require.NoError(t, err) require.Equal(t, interpreter.NilValue{}, value) }) - t.Run("nonExistent", func(t *testing.T) { - - _, err := inter.Invoke("nonExistent") - RequireError(t, err) - - require.ErrorAs(t, err, &interpreter.ForceNilError{}) - }) - t.Run("unlink after borrow", func(t *testing.T) { - _, err := inter.Invoke("unlinkAfterBorrow") + _, err := inter.Invoke("unlinkAfterBorrow", capability) RequireError(t, err) require.ErrorAs(t, err, &interpreter.DereferenceError{}) @@ -922,24 +910,16 @@ func TestInterpretCapability_check(t *testing.T) { ` #allowAccountLinking - fun link() { - account.linkAccount(/public/acct) - } - - fun checkPath(_ path: CapabilityPath): Bool { - return account.getCapability(path).check<&AuthAccount>() + fun link(): Capability { + return account.linkAccount(/private/acct)! } - fun check(): Bool { - return checkPath(/public/acct) + fun check(_ cap: Capability): Bool { + return cap.check<&AuthAccount>() } - fun checkAuth(): Bool { - return account.getCapability(/public/acct).check() - } - - fun nonExistent(): Bool { - return checkPath(/public/nonExistent) + fun checkAuth(_ cap: Capability): Bool { + return cap.check() } `, sema.Config{ @@ -949,12 +929,12 @@ func TestInterpretCapability_check(t *testing.T) { // link - _, err := inter.Invoke("link") + capability, err := inter.Invoke("link") require.NoError(t, err) t.Run("check", func(t *testing.T) { - value, err := inter.Invoke("check") + value, err := inter.Invoke("check", capability) require.NoError(t, err) require.Equal(t, interpreter.TrueValue, value) @@ -962,15 +942,7 @@ func TestInterpretCapability_check(t *testing.T) { t.Run("checkAuth", func(t *testing.T) { - value, err := inter.Invoke("checkAuth") - require.NoError(t, err) - - require.Equal(t, interpreter.FalseValue, value) - }) - - t.Run("nonExistent", func(t *testing.T) { - - value, err := inter.Invoke("nonExistent") + value, err := inter.Invoke("checkAuth", capability) require.NoError(t, err) require.Equal(t, interpreter.FalseValue, value) diff --git a/runtime/tests/interpreter/interpreter_test.go b/runtime/tests/interpreter/interpreter_test.go index b60cc3a7b7..7a3ab23df4 100644 --- a/runtime/tests/interpreter/interpreter_test.go +++ b/runtime/tests/interpreter/interpreter_test.go @@ -157,6 +157,8 @@ func parseCheckAndInterpretWithOptionsAndMemoryMetering( require.NoError(t, err) + inter.ConfigureAccountLinkingAllowed() + err = inter.Interpret() if err == nil { diff --git a/runtime/tests/interpreter/memory_metering_test.go b/runtime/tests/interpreter/memory_metering_test.go index 85f14cbb9e..fdd72fc533 100644 --- a/runtime/tests/interpreter/memory_metering_test.go +++ b/runtime/tests/interpreter/memory_metering_test.go @@ -6976,7 +6976,7 @@ func TestInterpretStorageCapabilityValueMetering(t *testing.T) { pub fun main(account: AuthAccount) { let r <- create R() account.save(<-r, to: /storage/r) - let x = account.link<&R>(/public/capo, target: /storage/r) + let x = account.link<&R>(/public/cap, target: /storage/r) } ` meter := newTestMemoryGauge() @@ -7000,7 +7000,7 @@ func TestInterpretStorageCapabilityValueMetering(t *testing.T) { pub fun main(account: AuthAccount) { let r <- create R() account.save(<-r, to: /storage/r) - let x = account.link<&R>(/public/capo, target: /storage/r) + let x = account.link<&R>(/public/cap, target: /storage/r) let y = [x] } @@ -7026,7 +7026,7 @@ func TestInterpretPathLinkValueMetering(t *testing.T) { resource R {} pub fun main(account: AuthAccount) { - account.link<&R>(/public/capo, target: /private/p) + account.link<&R>(/public/cap, target: /private/p) } ` meter := newTestMemoryGauge() @@ -7052,7 +7052,7 @@ func TestInterpretAccountLinkValueMetering(t *testing.T) { #allowAccountLinking pub fun main(account: AuthAccount) { - account.linkAccount(/public/capo) + account.linkAccount(/private/cap) } ` @@ -8705,7 +8705,7 @@ func TestInterpretStorageMapMetering(t *testing.T) { pub fun main(account: AuthAccount) { let r <- create R() account.save(<-r, to: /storage/r) - account.link<&R>(/public/capo, target: /storage/r) + account.link<&R>(/public/cap, target: /storage/r) account.borrow<&R>(from: /storage/r) } ` diff --git a/runtime/tests/interpreter/pragma_test.go b/runtime/tests/interpreter/pragma_test.go new file mode 100644 index 0000000000..e8121f4ff6 --- /dev/null +++ b/runtime/tests/interpreter/pragma_test.go @@ -0,0 +1,107 @@ +/* + * Cadence - The resource-oriented smart contract programming language + * + * Copyright Dapper Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package interpreter_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/onflow/cadence/runtime/sema" + "github.com/onflow/cadence/runtime/tests/checker" +) + +func TestInterpretAllowAccountLinkingPragma(t *testing.T) { + + t.Parallel() + + t.Run("top-level, before other declarations", func(t *testing.T) { + t.Parallel() + + inter := parseCheckAndInterpret(t, ` + #allowAccountLinking + + let x = 1 + `) + require.True(t, inter.SharedState.Config.AccountLinkingAllowed) + }) + + t.Run("top-level, after other pragmas", func(t *testing.T) { + t.Parallel() + + inter, err := parseCheckAndInterpretWithOptions(t, + ` + #someOtherPragma + #allowAccountLinking + + let x = 1 + `, + ParseCheckAndInterpretOptions{ + HandleCheckerError: func(err error) { + errs := checker.RequireCheckerErrors(t, err, 1) + assert.IsType(t, &sema.InvalidPragmaError{}, errs[0]) + }, + }, + ) + require.NoError(t, err) + require.False(t, inter.SharedState.Config.AccountLinkingAllowed) + }) + + t.Run("top-level, after other declarations", func(t *testing.T) { + t.Parallel() + + inter, err := parseCheckAndInterpretWithOptions(t, + ` + let x = 1 + + #allowAccountLinking + `, + ParseCheckAndInterpretOptions{ + HandleCheckerError: func(err error) { + errs := checker.RequireCheckerErrors(t, err, 1) + assert.IsType(t, &sema.InvalidPragmaError{}, errs[0]) + }, + }, + ) + require.NoError(t, err) + require.False(t, inter.SharedState.Config.AccountLinkingAllowed) + }) + + t.Run("nested", func(t *testing.T) { + + t.Parallel() + + inter, err := parseCheckAndInterpretWithOptions(t, + ` + fun test() { + #allowAccountLinking + } + `, + ParseCheckAndInterpretOptions{ + HandleCheckerError: func(err error) { + errs := checker.RequireCheckerErrors(t, err, 1) + require.IsType(t, &sema.InvalidDeclarationError{}, errs[0]) + }, + }, + ) + require.NoError(t, err) + require.False(t, inter.SharedState.Config.AccountLinkingAllowed) + }) +} diff --git a/runtime/tests/interpreter/values_test.go b/runtime/tests/interpreter/values_test.go index 8536450694..3ad28f0b0a 100644 --- a/runtime/tests/interpreter/values_test.go +++ b/runtime/tests/interpreter/values_test.go @@ -50,7 +50,7 @@ var validateAtree = flag.Bool("validateAtree", true, "Enable atree validation") func TestRandomMapOperations(t *testing.T) { if !*runSmokeTests { - t.SkipNow() + t.Skip("smoke tests are disabled") } t.Parallel() @@ -357,7 +357,25 @@ func TestRandomMapOperations(t *testing.T) { t.Run("random insert & remove", func(t *testing.T) { keyValues := make([][2]interpreter.Value, numberOfValues) for i := 0; i < numberOfValues; i++ { - keyValues[i][0] = randomHashableValue(inter) + // Generate unique key + var key interpreter.Value + for { + key = randomHashableValue(inter) + + var foundConflict bool + for j := 0; j < i; j++ { + existingKey := keyValues[j][0] + if key.(interpreter.EquatableValue).Equal(inter, interpreter.EmptyLocationRange, existingKey) { + foundConflict = true + break + } + } + if !foundConflict { + break + } + } + + keyValues[i][0] = key keyValues[i][1] = randomStorableValue(inter, 0) } @@ -497,7 +515,7 @@ func TestRandomMapOperations(t *testing.T) { func TestRandomArrayOperations(t *testing.T) { if !*runSmokeTests { - t.SkipNow() + t.Skip("smoke tests are disabled") } seed := time.Now().UnixNano() @@ -861,7 +879,7 @@ func TestRandomArrayOperations(t *testing.T) { func TestRandomCompositeValueOperations(t *testing.T) { if !*runSmokeTests { - t.SkipNow() + t.Skip("smoke tests are disabled") } seed := time.Now().UnixNano() diff --git a/runtime/transaction_executor.go b/runtime/transaction_executor.go index 1591a8d8b0..f7f6ccc192 100644 --- a/runtime/transaction_executor.go +++ b/runtime/transaction_executor.go @@ -251,6 +251,8 @@ func (executor *interpreterTransactionExecutor) transactionExecutionFunction( err = internalErr }) + inter.ConfigureAccountLinkingAllowed() + values, err := validateArgumentParams( inter, executor.environment, diff --git a/runtime/validation_test.go b/runtime/validation_test.go index 444f01be25..76e3b0b922 100644 --- a/runtime/validation_test.go +++ b/runtime/validation_test.go @@ -52,7 +52,7 @@ func TestRuntimeArgumentImportMissingType(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return nil, nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return nil, nil }, meterMemory: func(_ common.MemoryUsage) error { @@ -102,7 +102,7 @@ func TestRuntimeArgumentImportMissingType(t *testing.T) { getSigningAccounts: func() ([]Address, error) { return nil, nil }, - getAccountContractCode: func(address Address, name string) (code []byte, err error) { + getAccountContractCode: func(_ common.AddressLocation) (code []byte, err error) { return nil, nil }, meterMemory: func(_ common.MemoryUsage) error { diff --git a/runtime/value.go b/runtime/value.go index 0cbad8f48a..8f085a79c8 100644 --- a/runtime/value.go +++ b/runtime/value.go @@ -40,6 +40,16 @@ func newExportableValue(v interpreter.Value, inter *interpreter.Interpreter) exp } } +func newExportableValues(inter *interpreter.Interpreter, values []interpreter.Value) []exportableValue { + exportableValues := make([]exportableValue, 0, len(values)) + + for _, value := range values { + exportableValues = append(exportableValues, newExportableValue(value, inter)) + } + + return exportableValues +} + func (v exportableValue) Interpreter() *interpreter.Interpreter { return v.inter } diff --git a/tools/constructorcheck/Makefile b/tools/constructorcheck/Makefile index d81cf139a5..24c52ef2dc 100644 --- a/tools/constructorcheck/Makefile +++ b/tools/constructorcheck/Makefile @@ -1,3 +1,2 @@ -.PHONY: plugin -plugin: - go build -buildmode=plugin . \ No newline at end of file +constructorcheck.so: go.mod + go build -buildmode=plugin . diff --git a/tools/constructorcheck/go.mod b/tools/constructorcheck/go.mod index 16e6612fae..1a9332f039 100644 --- a/tools/constructorcheck/go.mod +++ b/tools/constructorcheck/go.mod @@ -1,10 +1,10 @@ module github.com/onflow/cadence/tools/constructorcheck -go 1.18 +go 1.19 -require golang.org/x/tools v0.1.12 +require golang.org/x/tools v0.6.0 require ( - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect + golang.org/x/mod v0.8.0 // indirect + golang.org/x/sys v0.5.0 // indirect ) diff --git a/tools/constructorcheck/go.sum b/tools/constructorcheck/go.sum index 1c6a6614e7..44d387ef3f 100644 --- a/tools/constructorcheck/go.sum +++ b/tools/constructorcheck/go.sum @@ -1,6 +1,7 @@ -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= diff --git a/tools/golangci-lint/Makefile b/tools/golangci-lint/Makefile index ac711c6cb5..ddafc4d7a0 100644 --- a/tools/golangci-lint/Makefile +++ b/tools/golangci-lint/Makefile @@ -1,2 +1,2 @@ -golangci-lint: +golangci-lint: go.mod go build -o golangci-lint github.com/golangci/golangci-lint/cmd/golangci-lint diff --git a/tools/golangci-lint/go.mod b/tools/golangci-lint/go.mod index e7939fd723..07fa12d3f7 100644 --- a/tools/golangci-lint/go.mod +++ b/tools/golangci-lint/go.mod @@ -1,66 +1,68 @@ module github.com/filecoin-project/tools/golangci-lint -go 1.18 +go 1.19 -require github.com/golangci/golangci-lint v1.49.0 +require github.com/golangci/golangci-lint v1.51.2 require ( - 4d63.com/gochecknoglobals v0.1.0 // indirect + 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect + 4d63.com/gochecknoglobals v0.2.1 // indirect + github.com/Abirdcfly/dupword v0.0.9 // indirect github.com/Antonboom/errname v0.1.7 // indirect github.com/Antonboom/nilnil v0.1.1 // indirect - github.com/BurntSushi/toml v1.2.0 // indirect + github.com/BurntSushi/toml v1.2.1 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 // indirect github.com/Masterminds/semver v1.5.0 // indirect - github.com/OpenPeeDeeP/depguard v1.1.0 // indirect + github.com/OpenPeeDeeP/depguard v1.1.1 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect - github.com/ashanbrown/forbidigo v1.3.0 // indirect + github.com/ashanbrown/forbidigo v1.4.0 // indirect github.com/ashanbrown/makezero v1.1.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bkielbasa/cyclop v1.2.0 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect - github.com/bombsimon/wsl/v3 v3.3.0 // indirect + github.com/bombsimon/wsl/v3 v3.4.0 // indirect github.com/breml/bidichk v0.2.3 // indirect github.com/breml/errchkjson v0.3.0 // indirect github.com/butuzov/ireturn v0.1.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/charithe/durationcheck v0.0.9 // indirect - github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 // indirect - github.com/curioswitch/go-reassign v0.1.2 // indirect - github.com/daixiang0/gci v0.6.3 // indirect + github.com/chavacava/garif v0.0.0-20221024190013-b3ef35877348 // indirect + github.com/curioswitch/go-reassign v0.2.0 // indirect + github.com/daixiang0/gci v0.9.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/denis-tingaikin/go-header v0.4.3 // indirect github.com/esimonov/ifshort v1.0.4 // indirect github.com/ettle/strcase v0.1.1 // indirect - github.com/fatih/color v1.13.0 // indirect + github.com/fatih/color v1.14.1 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/firefart/nonamedreturns v1.0.4 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/go-critic/go-critic v0.6.4 // indirect - github.com/go-toolsmith/astcast v1.0.0 // indirect - github.com/go-toolsmith/astcopy v1.0.1 // indirect - github.com/go-toolsmith/astequal v1.0.2 // indirect - github.com/go-toolsmith/astfmt v1.0.0 // indirect - github.com/go-toolsmith/astp v1.0.0 // indirect - github.com/go-toolsmith/strparse v1.0.0 // indirect - github.com/go-toolsmith/typep v1.0.2 // indirect - github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b // indirect + github.com/go-critic/go-critic v0.6.7 // indirect + github.com/go-toolsmith/astcast v1.1.0 // indirect + github.com/go-toolsmith/astcopy v1.0.3 // indirect + github.com/go-toolsmith/astequal v1.1.0 // indirect + github.com/go-toolsmith/astfmt v1.1.0 // indirect + github.com/go-toolsmith/astp v1.1.0 // indirect + github.com/go-toolsmith/strparse v1.1.0 // indirect + github.com/go-toolsmith/typep v1.1.0 // indirect + github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect - github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a // indirect + github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 // indirect github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect - github.com/golangci/misspell v0.3.5 // indirect + github.com/golangci/misspell v0.4.0 // indirect github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 // indirect github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect - github.com/google/go-cmp v0.5.8 // indirect - github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.4.2 // indirect github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect @@ -70,82 +72,85 @@ require ( github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/jgautheron/goconst v1.5.1 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect github.com/julz/importas v0.1.0 // indirect - github.com/kisielk/errcheck v1.6.2 // indirect + github.com/junk1tm/musttag v0.4.5 // indirect + github.com/kisielk/errcheck v1.6.3 // indirect github.com/kisielk/gotool v1.0.0 // indirect + github.com/kkHAIKE/contextcheck v1.1.3 // indirect github.com/kulti/thelper v0.6.3 // indirect github.com/kunwardeep/paralleltest v1.0.6 // indirect - github.com/kyoh86/exportloopref v0.1.8 // indirect + github.com/kyoh86/exportloopref v0.1.11 // indirect github.com/ldez/gomoddirectives v0.2.3 // indirect - github.com/ldez/tagliatelle v0.3.1 // indirect - github.com/leonklingele/grouper v1.1.0 // indirect + github.com/ldez/tagliatelle v0.4.0 // indirect + github.com/leonklingele/grouper v1.1.1 // indirect github.com/lufeee/execinquery v1.2.1 // indirect github.com/magiconair/properties v1.8.6 // indirect + github.com/maratori/testableexamples v1.0.0 // indirect github.com/maratori/testpackage v1.1.0 // indirect github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mbilski/exhaustivestruct v1.2.0 // indirect - github.com/mgechev/revive v1.2.3 // indirect + github.com/mgechev/revive v1.2.5 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moricho/tparallel v0.2.1 // indirect github.com/nakabonne/nestif v0.3.1 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect - github.com/nishanths/exhaustive v0.8.1 // indirect + github.com/nishanths/exhaustive v0.9.5 // indirect github.com/nishanths/predeclared v0.2.2 // indirect + github.com/nunnatsa/ginkgolinter v0.8.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.2 // indirect - github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d // indirect + github.com/pelletier/go-toml/v2 v2.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/polyfloyd/go-errorlint v1.0.2 // indirect + github.com/polyfloyd/go-errorlint v1.1.0 // indirect github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/quasilyte/go-ruleguard v0.3.17 // indirect - github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5 // indirect + github.com/quasilyte/go-ruleguard v0.3.19 // indirect + github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect - github.com/ryancurrah/gomodguard v1.2.4 // indirect - github.com/ryanrolds/sqlclosecheck v0.3.0 // indirect - github.com/sanposhiho/wastedassign/v2 v2.0.6 // indirect + github.com/ryancurrah/gomodguard v1.3.0 // indirect + github.com/ryanrolds/sqlclosecheck v0.4.0 // indirect + github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.13.0 // indirect - github.com/securego/gosec/v2 v2.13.1 // indirect + github.com/sashamelentyev/usestdlibvars v1.23.0 // indirect + github.com/securego/gosec/v2 v2.15.0 // indirect github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect github.com/sirupsen/logrus v1.9.0 // indirect github.com/sivchari/containedctx v1.0.2 // indirect github.com/sivchari/nosnakecase v1.7.0 // indirect - github.com/sivchari/tenv v1.7.0 // indirect + github.com/sivchari/tenv v1.7.1 // indirect github.com/sonatard/noctx v0.0.1 // indirect - github.com/sourcegraph/go-diff v0.6.1 // indirect + github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/spf13/afero v1.8.2 // indirect github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.5.0 // indirect + github.com/spf13/cobra v1.6.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.12.0 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect - github.com/stretchr/objx v0.4.0 // indirect - github.com/stretchr/testify v1.8.0 // indirect - github.com/subosito/gotenv v1.4.0 // indirect - github.com/sylvia7788/contextcheck v1.0.6 // indirect + github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/testify v1.8.1 // indirect + github.com/subosito/gotenv v1.4.1 // indirect + github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect github.com/tdakkota/asciicheck v0.1.1 // indirect github.com/tetafro/godot v1.4.11 // indirect - github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 // indirect - github.com/timonwong/logrlint v0.1.0 // indirect - github.com/tomarrell/wrapcheck/v2 v2.6.2 // indirect - github.com/tommy-muehle/go-mnd/v2 v2.5.0 // indirect + github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e // indirect + github.com/timonwong/loggercheck v0.9.3 // indirect + github.com/tomarrell/wrapcheck/v2 v2.8.0 // indirect + github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/ultraware/funlen v0.0.3 // indirect github.com/ultraware/whitespace v0.0.5 // indirect github.com/uudashr/gocognit v1.0.6 // indirect @@ -156,19 +161,19 @@ require ( go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.17.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/tools v0.1.12 // indirect + golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9 // indirect + golang.org/x/mod v0.8.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.6.0 // indirect + golang.org/x/tools v0.6.0 // indirect google.golang.org/protobuf v1.28.0 // indirect - gopkg.in/ini.v1 v1.66.6 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - honnef.co/go/tools v0.3.3 // indirect - mvdan.cc/gofumpt v0.3.1 // indirect + honnef.co/go/tools v0.4.2 // indirect + mvdan.cc/gofumpt v0.4.0 // indirect mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect - mvdan.cc/unparam v0.0.0-20220706161116-678bad134442 // indirect + mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d // indirect ) diff --git a/tools/golangci-lint/go.sum b/tools/golangci-lint/go.sum index 9ec670339b..d721114bbb 100644 --- a/tools/golangci-lint/go.sum +++ b/tools/golangci-lint/go.sum @@ -1,5 +1,7 @@ -4d63.com/gochecknoglobals v0.1.0 h1:zeZSRqj5yCg28tCkIV/z/lWbwvNm5qnKVS15PI8nhD0= -4d63.com/gochecknoglobals v0.1.0/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= +4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA= +4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= +4d63.com/gochecknoglobals v0.2.1 h1:1eiorGsgHOFOuoOiJDy2psSrQbRdIHrlge0IJIkUgDc= +4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU= 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= @@ -38,13 +40,15 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Abirdcfly/dupword v0.0.9 h1:MxprGjKq3yDBICXDgEEsyGirIXfMYXkLNT/agPsE1tk= +github.com/Abirdcfly/dupword v0.0.9/go.mod h1:PzmHVLLZ27MvHSzV7eFmMXSFArWXZPZmfuuziuUrf2g= github.com/Antonboom/errname v0.1.7 h1:mBBDKvEYwPl4WFFNwec1CZO096G6vzK9vvDQzAwkako= github.com/Antonboom/errname v0.1.7/go.mod h1:g0ONh16msHIPgJSGsecu1G/dcF2hlYR/0SddnIAGavU= github.com/Antonboom/nilnil v0.1.1 h1:PHhrh5ANKFWRBh7TdYmyyq2gyT2lotnvFvvFbylF81Q= github.com/Antonboom/nilnil v0.1.1/go.mod h1:L1jBqoWM7AOeTD+tSquifKSesRHs4ZdaxvZR+xdJEaI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= -github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= @@ -52,8 +56,8 @@ github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 h1:+r1rSv4gvYn0wmRjC8X7I github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/OpenPeeDeeP/depguard v1.1.0 h1:pjK9nLPS1FwQYGGpPxoMYpe7qACHOhAWQMQzV71i49o= -github.com/OpenPeeDeeP/depguard v1.1.0/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= +github.com/OpenPeeDeeP/depguard v1.1.1 h1:TSUznLjvp/4IUP+OQ0t/4jF4QUyxIcVX8YnghZdunyA= +github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= 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= @@ -63,8 +67,8 @@ github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pO github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= -github.com/ashanbrown/forbidigo v1.3.0 h1:VkYIwb/xxdireGAdJNZoo24O4lmnEWkactplBlWTShc= -github.com/ashanbrown/forbidigo v1.3.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= +github.com/ashanbrown/forbidigo v1.4.0 h1:spdPbupaSqtWORq1Q4eHBoPBmHtwVyLKwaedbSLc5Sw= +github.com/ashanbrown/forbidigo v1.4.0/go.mod h1:IvgwB5Y4fzqSAj/WVXKWigoTkB0dzI2FBbpKWuh7ph8= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -75,8 +79,8 @@ github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7 github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ089M= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= -github.com/bombsimon/wsl/v3 v3.3.0 h1:Mka/+kRLoQJq7g2rggtgQsjuI/K5Efd87WX96EWFxjM= -github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU= +github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= github.com/breml/bidichk v0.2.3 h1:qe6ggxpTfA8E75hdjWPZ581sY3a2lnl0IRxLQFelECI= github.com/breml/bidichk v0.2.3/go.mod h1:8u2C6DnAy0g2cEq+k/A2+tr9O1s+vHGxWn0LTc70T2A= github.com/breml/errchkjson v0.3.0 h1:YdDqhfqMT+I1vIxPSas44P+9Z9HzJwCeAzjB8PxP1xw= @@ -89,8 +93,8 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cb github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charithe/durationcheck v0.0.9 h1:mPP4ucLrf/rKZiIG/a9IPXHGlh8p4CzgpyTy6EEutYk= github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= -github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 h1:E7LT642ysztPWE0dfz43cWOvMiF42DyTRC+eZIaO4yI= -github.com/chavacava/garif v0.0.0-20220630083739-93517212f375/go.mod h1:4m1Rv7xfuwWPNKXlThldNuJvutYM6J95wNuuVmn55To= +github.com/chavacava/garif v0.0.0-20221024190013-b3ef35877348 h1:cy5GCEZLUCshCGCRRUjxHrDUqkB4l5cuUt3ShEckQEo= +github.com/chavacava/garif v0.0.0-20221024190013-b3ef35877348/go.mod h1:f/miWtG3SSuTxKsNK3o58H1xl+XV6ZIfbC6p7lPPB8U= 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= @@ -99,12 +103,10 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX 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/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/cristalhq/acmd v0.7.0/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= -github.com/curioswitch/go-reassign v0.1.2 h1:ekM07+z+VFT560Exz4mTv0/s1yU9gem6CJc/tlYpkmI= -github.com/curioswitch/go-reassign v0.1.2/go.mod h1:bFJIHgtTM3hRm2sKXSPkbwNjSFyGURQXyn4IXD2qwfQ= -github.com/daixiang0/gci v0.6.3 h1:wUAqXChk8HbwXn8AfxD9DYSCp9Bpz1L3e6Q4Roe+q9E= -github.com/daixiang0/gci v0.6.3/go.mod h1:EpVfrztufwVgQRXjnX4zuNinEpLj5OmMjtu/+MB0V0c= +github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= +github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= +github.com/daixiang0/gci v0.9.1 h1:jBrwBmBZTDsGsXiaCTLIe9diotp1X4X64zodFrh7l+c= +github.com/daixiang0/gci v0.9.1/go.mod h1:EpVfrztufwVgQRXjnX4zuNinEpLj5OmMjtu/+MB0V0c= 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= @@ -120,8 +122,8 @@ github.com/esimonov/ifshort v1.0.4 h1:6SID4yGWfRae/M7hkVDVVyppy8q/v9OuxNdmjLQStB github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= @@ -131,8 +133,8 @@ github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwV github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/go-critic/go-critic v0.6.4 h1:tucuG1pvOyYgpBIrVxw0R6gwO42lNa92Aq3VaDoIs+E= -github.com/go-critic/go-critic v0.6.4/go.mod h1:qL5SOlk7NtY6sJPoVCTKDIgzNOxHkkkOCVDyi9wJe1U= +github.com/go-critic/go-critic v0.6.7 h1:1evPrElnLQ2LZtJfmNDzlieDhjnq36SLgNzisx06oPM= +github.com/go-critic/go-critic v0.6.7/go.mod h1:fYZUijFdcnxgx6wPjQA2QEjIRaNCT0gO8bhexy6/QmE= 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= @@ -142,29 +144,28 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb 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-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= -github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= -github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= -github.com/go-toolsmith/astcopy v1.0.1 h1:l09oBhAPyV74kLJ3ZO31iBU8htZGTwr9LTjuMCyL8go= -github.com/go-toolsmith/astcopy v1.0.1/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= -github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astequal v1.0.1/go.mod h1:4oGA3EZXTVItV/ipGiOx7NWkY5veFfcsOJVS2YxltLw= -github.com/go-toolsmith/astequal v1.0.2 h1:+XvaV8zNxua+9+Oa4AHmgmpo4RYAbwr/qjNppLfX2yM= +github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= +github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= +github.com/go-toolsmith/astcopy v1.0.3 h1:r0bgSRlMOAgO+BdQnVAcpMSMkrQCnV6ZJmIkrJgcJj0= +github.com/go-toolsmith/astcopy v1.0.3/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= -github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= -github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= -github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= -github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= +github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= +github.com/go-toolsmith/astequal v1.1.0 h1:kHKm1AWqClYn15R0K1KKE4RG614D46n+nqUQ06E1dTw= +github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= +github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsOmcco= +github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= +github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= +github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5 h1:eD9POs68PHkwrx7hAB78z1cb6PfGq/jyWn3wJywsH1o= -github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5/go.mod h1:3NAwwmD4uY/yggRxoEjk/S00MIV3A+H7rrE3i87eYxM= -github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= -github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYwvlk= -github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= -github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo= -github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= +github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= +github.com/go-toolsmith/typep v1.1.0 h1:fIRYDyF+JywLfqzyhdiHzRop/GQDxxNhLGQ6gFUNHus= +github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= +github.com/go-xmlfmt/xmlfmt v1.1.2 h1:Nea7b4icn8s57fTx1M5AI4qQT5HEM3rVUO8MuE6g80U= +github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= @@ -204,16 +205,16 @@ github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9 github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6J5HIP8ZtyMdiDscjMLfRBSPuzVVeo= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= -github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks= -github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= -github.com/golangci/golangci-lint v1.49.0 h1:I8WHOavragDttlLHtSraHn/h39C+R60bEQ5NoGcHQr8= -github.com/golangci/golangci-lint v1.49.0/go.mod h1:+V/7lLv449R6w9mQ3WdV0EKh7Je/jTylMeSwBZcLeWE= +github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= +github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= +github.com/golangci/golangci-lint v1.51.2 h1:yIcsT1X9ZYHdSpeWXRT1ORC/FPGSqDHbHsu9uk4FK7M= +github.com/golangci/golangci-lint v1.51.2/go.mod h1:KH9Q7/3glwpYSknxUgUyLlAv46A8fsSKo1hH2wDvkr8= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= -github.com/golangci/misspell v0.3.5 h1:pLzmVdl3VxTOncgzHcvLOKirdvcx/TydsClUQXTehjo= -github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/misspell v0.4.0 h1:KtVB/hTK4bbL/S6bs64rYyk8adjmh1BygbBiaAiX+a0= +github.com/golangci/misspell v0.4.0/go.mod h1:W6O/bwV6lGDxUCChm2ykw9NQdd5bYd1Xkjo88UcWyJc= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 h1:DIPQnGy2Gv2FSA4B/hh8Q7xx3B7AIDk3DAMeHclH1vQ= github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= @@ -230,9 +231,9 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/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-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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= @@ -252,9 +253,8 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ 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/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 h1:PVRE9d4AQKmbelZ7emNig1+NT27DUmKZn5qXxfio54U= -github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= -github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 h1:9alfqbrhuD+9fLZ4iaAVwhlp5PEhmnBt7yvK2Oy5C1U= +github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= @@ -284,15 +284,14 @@ github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUq github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= 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 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= -github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -304,10 +303,14 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= -github.com/kisielk/errcheck v1.6.2 h1:uGQ9xI8/pgc9iOoCe7kWQgRE6SBTrCGmTSf0LrEtY7c= -github.com/kisielk/errcheck v1.6.2/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= +github.com/junk1tm/musttag v0.4.5 h1:d+mpJ1vn6WFEVKHwkgJiIedis1u/EawKOuUTygAUtCo= +github.com/junk1tm/musttag v0.4.5/go.mod h1:XkcL/9O6RmD88JBXb+I15nYRl9W4ExhgQeCBEhfMC8U= +github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM8= +github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkHAIKE/contextcheck v1.1.3 h1:l4pNvrb8JSwRd51ojtcOxOeHJzHek+MtOyXbaR0uvmw= +github.com/kkHAIKE/contextcheck v1.1.3/go.mod h1:PG/cwd6c0705/LM0KTr1acO2gORUxkSVWyLJOFW5qoo= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -317,46 +320,43 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= 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/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= github.com/kunwardeep/paralleltest v1.0.6 h1:FCKYMF1OF2+RveWlABsdnmsvJrei5aoyZoaGS+Ugg8g= github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= -github.com/kyoh86/exportloopref v0.1.8 h1:5Ry/at+eFdkX9Vsdw3qU4YkvGtzuVfzT4X7S77LoN/M= -github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= +github.com/kyoh86/exportloopref v0.1.11 h1:1Z0bcmTypkL3Q4k+IDHMWTcnCliEZcaPiIe0/ymEyhQ= +github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= github.com/ldez/gomoddirectives v0.2.3 h1:y7MBaisZVDYmKvt9/l1mjNCiSA1BVn34U0ObUcJwlhA= github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= -github.com/ldez/tagliatelle v0.3.1 h1:3BqVVlReVUZwafJUwQ+oxbx2BEX2vUG4Yu/NOfMiKiM= -github.com/ldez/tagliatelle v0.3.1/go.mod h1:8s6WJQwEYHbKZDsp/LjArytKOG8qaMrKQQ3mFukHs88= -github.com/leonklingele/grouper v1.1.0 h1:tC2y/ygPbMFSBOs3DcyaEMKnnwH7eYKzohOtRrf0SAg= -github.com/leonklingele/grouper v1.1.0/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/ldez/tagliatelle v0.4.0 h1:sylp7d9kh6AdXN2DpVGHBRb5guTVAgOxqNGhbqc4b1c= +github.com/ldez/tagliatelle v0.4.0/go.mod h1:mNtTfrHy2haaBAw+VT7IBV6VXBThS7TCreYWbBcJ87I= +github.com/leonklingele/grouper v1.1.1 h1:suWXRU57D4/Enn6pXR0QVqqWWrnJ9Osrz+5rjt8ivzU= +github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= github.com/lufeee/execinquery v1.2.1 h1:hf0Ems4SHcUGBxpGN7Jz78z1ppVkP/837ZlETPCEtOM= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= +github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= github.com/maratori/testpackage v1.1.0 h1:GJY4wlzQhuBusMF1oahQCBtUV/AQ/k69IZ68vxaac2Q= github.com/maratori/testpackage v1.1.0/go.mod h1:PeAhzU8qkCwdGEMTEupsHJNlQu2gZopMC6RjbhmHeDc= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= -github.com/mgechev/revive v1.2.3 h1:NzIEEa9+WimQ6q2Ov7OcNeySS/IOcwtkQ8RAh0R5UJ4= -github.com/mgechev/revive v1.2.3/go.mod h1:iAWlQishqCuj4yhV24FTnKSXGpbAA+0SckXB8GQMX/Q= +github.com/mgechev/revive v1.2.5 h1:UF9AR8pOAuwNmhXj2odp4mxv9Nx2qUIwVz8ZsU+Mbec= +github.com/mgechev/revive v1.2.5/go.mod h1:nFOXent79jMTISAfOAasKfy0Z2Ejq0WX7Qn/KAdYopI= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -375,15 +375,16 @@ github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4N github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nishanths/exhaustive v0.8.1 h1:0QKNascWv9qIHY7zRoZSxeRr6kuk5aAT3YXLTiDmjTo= -github.com/nishanths/exhaustive v0.8.1/go.mod h1:qj+zJJUgJ76tR92+25+03oYUhzF4R7/2Wk7fGTfCHmg= +github.com/nishanths/exhaustive v0.9.5 h1:TzssWan6orBiLYVqewCG8faud9qlFntJE30ACpzmGME= +github.com/nishanths/exhaustive v0.9.5/go.mod h1:IbwrGdVMizvDcIxPYGVdQn5BqWJaOwpCvg4RGb8r/TA= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= +github.com/nunnatsa/ginkgolinter v0.8.1 h1:/y4o/0hV+ruUHj4xXh89xlFjoaitnI4LnkpuYs02q1c= +github.com/nunnatsa/ginkgolinter v0.8.1/go.mod h1:FYYLtszIdmzCH8XMaMPyxPVXZ7VCaIm55bA+gugx+14= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= -github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= +github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI= +github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q= github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -392,10 +393,8 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9 github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.2 h1:+jQXlF3scKIcSEKkdHzXhCTDLPFi5r1wnK6yPS+49Gw= -github.com/pelletier/go-toml/v2 v2.0.2/go.mod h1:MovirKjgVRESsAvNZlAjtFwV867yGuwRkXbG66OzopI= -github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9ocOS/xlSptM1N3BbrA6/kmaep5ggwaIA= -github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= +github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= 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= @@ -403,8 +402,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= 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/polyfloyd/go-errorlint v1.0.2 h1:kp1yvHflYhTmw5m3MmBy8SCyQkKPjwDthVuMH0ug6Yk= -github.com/polyfloyd/go-errorlint v1.0.2/go.mod h1:APVvOesVSAnne5SClsPxPdfvZTVDojXh1/G3qb5wjGI= +github.com/polyfloyd/go-errorlint v1.1.0 h1:VKoEFg5yxSgJ2yFPVhxW7oGz+f8/OVcuMeNvcPIi6Eg= +github.com/polyfloyd/go-errorlint v1.1.0/go.mod h1:Uss7Bc/izYG0leCMRx3WVlrpqWedSZk7V/FUQW6VJ6U= 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.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -427,34 +426,29 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= -github.com/quasilyte/go-ruleguard v0.3.17 h1:cDdoaSbQg11LXPDQqiCK54QmQXsEQQCTIgdcpeULGSI= -github.com/quasilyte/go-ruleguard v0.3.17/go.mod h1:sST5PvaR7yb/Az5ksX8oc88usJ4EGjmJv7cK7y3jyig= -github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/dsl v0.3.21/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= -github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5 h1:PDWGei+Rf2bBiuZIbZmM20J2ftEy9IeUCHA8HbQqed8= -github.com/quasilyte/gogrep v0.0.0-20220120141003-628d8b3623b5/go.mod h1:wSEyW6O61xRV6zb6My3HxrQ5/8ke7NE2OayqCHa3xRM= +github.com/quasilyte/go-ruleguard v0.3.19 h1:tfMnabXle/HzOb5Xe9CUZYWXKfkS1KwRmZyPmD9nVcc= +github.com/quasilyte/go-ruleguard v0.3.19/go.mod h1:lHSn69Scl48I7Gt9cX3VrbsZYvYiBYszZOZW4A+oTEw= +github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= +github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY= github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryancurrah/gomodguard v1.2.4 h1:CpMSDKan0LtNGGhPrvupAoLeObRFjND8/tU1rEOtBp4= -github.com/ryancurrah/gomodguard v1.2.4/go.mod h1:+Kem4VjWwvFpUJRJSwa16s1tBJe+vbv02+naTow2f6M= -github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8OUZI9xFw= -github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= -github.com/sanposhiho/wastedassign/v2 v2.0.6 h1:+6/hQIHKNJAUixEj6EmOngGIisyeI+T3335lYTyxRoA= -github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= +github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= +github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= +github.com/ryanrolds/sqlclosecheck v0.4.0 h1:i8SX60Rppc1wRuyQjMciLqIzV3xnoHB7/tXbr6RGYNI= +github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ= +github.com/sanposhiho/wastedassign/v2 v2.0.7 h1:J+6nrY4VW+gC9xFzUc+XjPD3g3wF3je/NsJFwFK7Uxc= +github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.13.0 h1:uObNudVEEHf6JbOJy5bgKJloA1bWjxR9fwgNFpPzKnI= -github.com/sashamelentyev/usestdlibvars v1.13.0/go.mod h1:D2Wb7niIYmTB+gB8z7kh8tyP5ccof1dQ+SFk+WW5NtY= -github.com/securego/gosec/v2 v2.13.1 h1:7mU32qn2dyC81MH9L2kefnQyRMUarfDER3iQyMHcjYM= -github.com/securego/gosec/v2 v2.13.1/go.mod h1:EO1sImBMBWFjOTFzMWfTRrZW6M15gm60ljzrmy/wtHo= +github.com/sashamelentyev/usestdlibvars v1.23.0 h1:01h+/2Kd+NblNItNeux0veSL5cBF1jbEOPrEhDzGYq0= +github.com/sashamelentyev/usestdlibvars v1.23.0/go.mod h1:YPwr/Y1LATzHI93CqoPUN/2BzGQ/6N/cl/KwgR0B/aU= +github.com/securego/gosec/v2 v2.15.0 h1:v4Ym7FF58/jlykYmmhZ7mTm7FQvN/setNm++0fgIAtw= +github.com/securego/gosec/v2 v2.15.0/go.mod h1:VOjTrZOkUtSDt2QLSJmQBMWnvwiQPEjg0l+5juIqGk8= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -468,18 +462,18 @@ github.com/sivchari/containedctx v1.0.2 h1:0hLQKpgC53OVF1VT7CeoFHk9YKstur1XOgfYI github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt95do8= github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= -github.com/sivchari/tenv v1.7.0 h1:d4laZMBK6jpe5PWepxlV9S+LC0yXqvYHiq8E6ceoVVE= -github.com/sivchari/tenv v1.7.0/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= +github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak= +github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= github.com/sonatard/noctx v0.0.1 h1:VC1Qhl6Oxx9vvWo3UDgrGXYCeKCe3Wbw7qAWL6FrmTY= github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= -github.com/sourcegraph/go-diff v0.6.1 h1:hmA1LzxW0n1c3Q4YbrFgg4P99GSnebYa3x8gr0HZqLQ= -github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= +github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= +github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= -github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= 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= @@ -492,8 +486,9 @@ github.com/stbenjam/no-sprintf-host-port v0.1.1 h1:tYugd/yrm1O0dV+ThCbaKZh195Dfm github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= 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 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -501,13 +496,13 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs= -github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= -github.com/sylvia7788/contextcheck v1.0.6 h1:o2EZgVPyMKE/Mtoqym61DInKEjwEbsmyoxg3VrmjNO4= -github.com/sylvia7788/contextcheck v1.0.6/go.mod h1:9XDxwvxyuKD+8N+a7Gs7bfWLityh5t70g/GjdEt2N2M= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= +github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= github.com/tdakkota/asciicheck v0.1.1 h1:PKzG7JUTUmVspQTDqtkX9eSiLGossXTybutHwTXuO0A= github.com/tdakkota/asciicheck v0.1.1/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= @@ -516,14 +511,14 @@ github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpR github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= -github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 h1:kl4KhGNsJIbDHS9/4U9yQo1UcPQM0kOMJHn29EoH/Ro= -github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= -github.com/timonwong/logrlint v0.1.0 h1:phZCcypL/vtx6cGxObJgWZ5wexZF5SXFPLOM+ru0e/M= -github.com/timonwong/logrlint v0.1.0/go.mod h1:Zleg4Gw+kRxNej+Ra7o+tEaW5k1qthTaYKU7rSD39LU= -github.com/tomarrell/wrapcheck/v2 v2.6.2 h1:3dI6YNcrJTQ/CJQ6M/DUkc0gnqYSIk6o0rChn9E/D0M= -github.com/tomarrell/wrapcheck/v2 v2.6.2/go.mod h1:ao7l5p0aOlUNJKI0qVwB4Yjlqutd0IvAB9Rdwyilxvg= -github.com/tommy-muehle/go-mnd/v2 v2.5.0 h1:iAj0a8e6+dXSL7Liq0aXPox36FiN1dBbjA6lt9fl65s= -github.com/tommy-muehle/go-mnd/v2 v2.5.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= +github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e h1:MV6KaVu/hzByHP0UvJ4HcMGE/8a6A4Rggc/0wx2AvJo= +github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= +github.com/timonwong/loggercheck v0.9.3 h1:ecACo9fNiHxX4/Bc02rW2+kaJIAMAes7qJ7JKxt0EZI= +github.com/timonwong/loggercheck v0.9.3/go.mod h1:wUqnk9yAOIKtGA39l1KLE9Iz0QiTocu/YZoOf+OzFdw= +github.com/tomarrell/wrapcheck/v2 v2.8.0 h1:qDzbir0xmoE+aNxGCPrn+rUSxAX+nG6vREgbbXAR81I= +github.com/tomarrell/wrapcheck/v2 v2.8.0/go.mod h1:ao7l5p0aOlUNJKI0qVwB4Yjlqutd0IvAB9Rdwyilxvg= +github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= +github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iLA= github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= @@ -564,6 +559,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +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= @@ -577,8 +573,8 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d h1:+W8Qf4iJtMGKkyAygcKohjxTk4JPsL9DpzApJ22m5Ic= -golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9 h1:6WHiuFL9FNjg8RljAaT7FNUuKDbvMqS1i5cr2OE2sLQ= +golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= 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= @@ -605,8 +601,11 @@ 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.1/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 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= 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.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -643,8 +642,12 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= 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.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= 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= @@ -666,8 +669,9 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ 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 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= 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-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-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -685,7 +689,6 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/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-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -714,7 +717,6 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -723,10 +725,19 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= 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= @@ -734,8 +745,11 @@ 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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 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.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 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= @@ -749,7 +763,6 @@ golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3 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-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/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= @@ -759,7 +772,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/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-20190916130336-e45ffcd953cc/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-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -788,24 +800,19 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY 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-20200622203043-20e05c1c8ffa/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200625211823-6506e20df31f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 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-20200812195022-5ae4c3c160a0/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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-20201230224404-63754364767c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= @@ -813,12 +820,16 @@ golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0t golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.9-0.20211228192929-ee1ca4ffc4da/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= 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.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +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= @@ -920,10 +931,9 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 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-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.66.6 h1:LATuAqN/shcYAOkv3wl2L4rkaKqkcgTBQjOyYDvcPKI= -gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -943,16 +953,16 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh 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= -honnef.co/go/tools v0.3.3 h1:oDx7VAwstgpYpb3wv0oxiZlxY+foCpRAwY7Vk6XpAgA= -honnef.co/go/tools v0.3.3/go.mod h1:jzwdWgg7Jdq75wlfblQxO4neNaFFSvgc1tD5Wv8U0Yw= -mvdan.cc/gofumpt v0.3.1 h1:avhhrOmv0IuvQVK7fvwV91oFSGAk5/6Po8GXTzICeu8= -mvdan.cc/gofumpt v0.3.1/go.mod h1:w3ymliuxvzVx8DAutBnVyDqYb1Niy/yCJt/lk821YCE= +honnef.co/go/tools v0.4.2 h1:6qXr+R5w+ktL5UkwEbPp+fEvfyoMPche6GkOpGHZcLc= +honnef.co/go/tools v0.4.2/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= +mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM= +mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -mvdan.cc/unparam v0.0.0-20220706161116-678bad134442 h1:seuXWbRB1qPrS3NQnHmFKLJLtskWyueeIzmLXghMGgk= -mvdan.cc/unparam v0.0.0-20220706161116-678bad134442/go.mod h1:F/Cxw/6mVrNKqrR2YjFf5CaW0Bw4RL8RfbEf4GRggJk= +mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w= +mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= 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= diff --git a/tools/maprange/Makefile b/tools/maprange/Makefile index d81cf139a5..5485d4a205 100644 --- a/tools/maprange/Makefile +++ b/tools/maprange/Makefile @@ -1,3 +1,2 @@ -.PHONY: plugin -plugin: - go build -buildmode=plugin . \ No newline at end of file +maprange.so: go.mod + go build -buildmode=plugin . diff --git a/tools/maprange/go.mod b/tools/maprange/go.mod index fbf8b24b1b..f606575814 100644 --- a/tools/maprange/go.mod +++ b/tools/maprange/go.mod @@ -1,10 +1,10 @@ module github.com/onflow/cadence/tools/maprange -go 1.18 +go 1.19 -require golang.org/x/tools v0.1.12 +require golang.org/x/tools v0.6.0 require ( - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect + golang.org/x/mod v0.8.0 // indirect + golang.org/x/sys v0.5.0 // indirect ) diff --git a/tools/maprange/go.sum b/tools/maprange/go.sum index 1c6a6614e7..44d387ef3f 100644 --- a/tools/maprange/go.sum +++ b/tools/maprange/go.sum @@ -1,6 +1,7 @@ -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= diff --git a/tools/unkeyed/Makefile b/tools/unkeyed/Makefile index d81cf139a5..240422e9be 100644 --- a/tools/unkeyed/Makefile +++ b/tools/unkeyed/Makefile @@ -1,3 +1,2 @@ -.PHONY: plugin -plugin: - go build -buildmode=plugin . \ No newline at end of file +unkeyed.so: go.mod + go build -buildmode=plugin . diff --git a/tools/unkeyed/go.mod b/tools/unkeyed/go.mod index 499eff1e1b..b002306faf 100644 --- a/tools/unkeyed/go.mod +++ b/tools/unkeyed/go.mod @@ -1,13 +1,13 @@ module github.com/onflow/cadence/tools/unkeyed -go 1.18 +go 1.19 require ( - golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d - golang.org/x/tools v0.1.12 + golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9 + golang.org/x/tools v0.6.0 ) require ( - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect + golang.org/x/mod v0.8.0 // indirect + golang.org/x/sys v0.5.0 // indirect ) diff --git a/tools/unkeyed/go.sum b/tools/unkeyed/go.sum index a72f2cebde..381b6c01cf 100644 --- a/tools/unkeyed/go.sum +++ b/tools/unkeyed/go.sum @@ -1,8 +1,9 @@ -golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d h1:+W8Qf4iJtMGKkyAygcKohjxTk4JPsL9DpzApJ22m5Ic= -golang.org/x/exp/typeparams v0.0.0-20220613132600-b0d781184e0d/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9 h1:6WHiuFL9FNjg8RljAaT7FNUuKDbvMqS1i5cr2OE2sLQ= +golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= diff --git a/types.go b/types.go index 43f2d4c705..70b08781f3 100644 --- a/types.go +++ b/types.go @@ -1092,12 +1092,12 @@ func NewStructType( func NewMeteredStructType( gauge common.MemoryGauge, location common.Location, - qualifiedIdentifer string, + qualifiedIdentifier string, fields []Field, initializers [][]Parameter, ) *StructType { common.UseMemory(gauge, common.CadenceStructTypeMemoryUsage) - return NewStructType(location, qualifiedIdentifer, fields, initializers) + return NewStructType(location, qualifiedIdentifier, fields, initializers) } func (*StructType) isType() {} @@ -1153,13 +1153,13 @@ type ResourceType struct { func NewResourceType( location common.Location, - qualifiedIdentifer string, + qualifiedIdentifier string, fields []Field, initializers [][]Parameter, ) *ResourceType { return &ResourceType{ Location: location, - QualifiedIdentifier: qualifiedIdentifer, + QualifiedIdentifier: qualifiedIdentifier, Fields: fields, Initializers: initializers, } @@ -1168,12 +1168,12 @@ func NewResourceType( func NewMeteredResourceType( gauge common.MemoryGauge, location common.Location, - qualifiedIdentifer string, + qualifiedIdentifier string, fields []Field, initializers [][]Parameter, ) *ResourceType { common.UseMemory(gauge, common.CadenceResourceTypeMemoryUsage) - return NewResourceType(location, qualifiedIdentifer, fields, initializers) + return NewResourceType(location, qualifiedIdentifier, fields, initializers) } func (*ResourceType) isType() {} @@ -1312,13 +1312,13 @@ type EventType struct { func NewEventType( location common.Location, - qualifiedIdentifer string, + qualifiedIdentifier string, fields []Field, initializer []Parameter, ) *EventType { return &EventType{ Location: location, - QualifiedIdentifier: qualifiedIdentifer, + QualifiedIdentifier: qualifiedIdentifier, Fields: fields, Initializer: initializer, } @@ -1327,12 +1327,12 @@ func NewEventType( func NewMeteredEventType( gauge common.MemoryGauge, location common.Location, - qualifiedIdentifer string, + qualifiedIdentifier string, fields []Field, initializer []Parameter, ) *EventType { common.UseMemory(gauge, common.CadenceEventTypeMemoryUsage) - return NewEventType(location, qualifiedIdentifer, fields, initializer) + return NewEventType(location, qualifiedIdentifier, fields, initializer) } func (*EventType) isType() {} diff --git a/values.go b/values.go index f944024f0e..df7f603e35 100644 --- a/values.go +++ b/values.go @@ -1426,7 +1426,7 @@ func (v Array) String() string { // Dictionary type Dictionary struct { - DictionaryType Type + DictionaryType *DictionaryType Pairs []KeyValuePair } @@ -1453,6 +1453,11 @@ func NewMeteredDictionary( func (Dictionary) isValue() {} func (v Dictionary) Type() Type { + if v.DictionaryType == nil { + // Return nil Type instead of Type referencing nil *DictionaryType, + // so caller can check if v's type is nil and also prevent nil pointer dereference. + return nil + } return v.DictionaryType } @@ -1541,6 +1546,11 @@ func NewMeteredStruct( func (Struct) isValue() {} func (v Struct) Type() Type { + if v.StructType == nil { + // Return nil Type instead of Type referencing nil *StructType, + // so caller can check if v's type is nil and also prevent nil pointer dereference. + return nil + } return v.StructType } @@ -1619,6 +1629,11 @@ func NewMeteredResource( func (Resource) isValue() {} func (v Resource) Type() Type { + if v.ResourceType == nil { + // Return nil Type instead of Type referencing nil *ResourceType, + // so caller can check if v's type is nil and also prevent nil pointer dereference. + return nil + } return v.ResourceType } @@ -1676,6 +1691,11 @@ func NewMeteredAttachment( func (Attachment) isValue() {} func (v Attachment) Type() Type { + if v.AttachmentType == nil { + // Return nil Type instead of Type referencing nil *AttachmentType, + // so caller can check if v's type is nil and also prevent nil pointer dereference. + return nil + } return v.AttachmentType } @@ -1733,6 +1753,11 @@ func NewMeteredEvent( func (Event) isValue() {} func (v Event) Type() Type { + if v.EventType == nil { + // Return nil Type instead of Type referencing nil *EventType, + // so caller can check if v's type is nil and also prevent nil pointer dereference. + return nil + } return v.EventType } @@ -1789,6 +1814,11 @@ func NewMeteredContract( func (Contract) isValue() {} func (v Contract) Type() Type { + if v.ContractType == nil { + // Return nil Type instead of Type referencing nil *ContractType, + // so caller can check if v's type is nil and also prevent nil pointer dereference. + return nil + } return v.ContractType } @@ -1815,6 +1845,49 @@ func (v Contract) String() string { return formatComposite(v.ContractType.ID(), v.ContractType.Fields, v.Fields) } +// PathLink + +type PathLink struct { + TargetPath Path + // TODO: a future version might want to export the whole type + BorrowType string +} + +var _ Value = PathLink{} + +func NewPathLink(targetPath Path, borrowType string) PathLink { + return PathLink{ + TargetPath: targetPath, + BorrowType: borrowType, + } +} + +func NewMeteredLink(gauge common.MemoryGauge, targetPath Path, borrowType string) PathLink { + common.UseMemory(gauge, common.CadencePathLinkValueMemoryUsage) + return NewPathLink(targetPath, borrowType) +} + +func (PathLink) isValue() {} + +func (v PathLink) Type() Type { + return nil +} + +func (v PathLink) MeteredType(_ common.MemoryGauge) Type { + return v.Type() +} + +func (v PathLink) ToGoValue() any { + return nil +} + +func (v PathLink) String() string { + return format.PathLink( + v.BorrowType, + v.TargetPath.String(), + ) +} + // Path type Path struct { @@ -1969,6 +2042,11 @@ func NewMeteredEnum( func (Enum) isValue() {} func (v Enum) Type() Type { + if v.EnumType == nil { + // Return nil Type instead of Type referencing nil *EnumType, + // so caller can check if v's type is nil and also prevent nil pointer dereference. + return nil + } return v.EnumType } @@ -2016,6 +2094,11 @@ func NewMeteredFunction(gauge common.MemoryGauge, functionType *FunctionType) Fu func (Function) isValue() {} func (v Function) Type() Type { + if v.FunctionType == nil { + // Return nil Type instead of Type referencing nil *FunctionType, + // so caller can check if v's type is nil and also prevent nil pointer dereference. + return nil + } return v.FunctionType } diff --git a/values_test.go b/values_test.go index 695f3d42e7..85080e7eb7 100644 --- a/values_test.go +++ b/values_test.go @@ -21,10 +21,8 @@ package cadence import ( "fmt" "math/big" - "reflect" "testing" "unicode/utf8" - "unsafe" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -33,129 +31,171 @@ import ( "github.com/onflow/cadence/runtime/tests/utils" ) -func TestStringer(t *testing.T) { - - t.Parallel() - - type testCase struct { - value Value - expected string - } +type valueTestCase struct { + value Value + string string + exampleType Type + expectedType Type + withType func(value Value, ty Type) Value + noType bool +} +func newValueTestCases() map[string]valueTestCase { ufix64, _ := NewUFix64("64.01") fix64, _ := NewFix64("-32.11") - stringerTests := map[string]testCase{ + testFunctionType := NewFunctionType( + "((String):UInt8)", + FunctionPurityUnspecified, + []Parameter{ + { + Type: StringType{}, + }, + }, + UInt8Type{}, + ) + + return map[string]valueTestCase{ "UInt": { - value: NewUInt(10), - expected: "10", + value: NewUInt(10), + string: "10", + expectedType: UIntType{}, }, "UInt8": { - value: NewUInt8(8), - expected: "8", + value: NewUInt8(8), + string: "8", + expectedType: UInt8Type{}, }, "UInt16": { - value: NewUInt16(16), - expected: "16", + value: NewUInt16(16), + string: "16", + expectedType: UInt16Type{}, }, "UInt32": { - value: NewUInt32(32), - expected: "32", + value: NewUInt32(32), + string: "32", + expectedType: UInt32Type{}, }, "UInt64": { - value: NewUInt64(64), - expected: "64", + value: NewUInt64(64), + string: "64", + expectedType: UInt64Type{}, }, "UInt128": { - value: NewUInt128(128), - expected: "128", + value: NewUInt128(128), + string: "128", + expectedType: UInt128Type{}, }, "UInt256": { - value: NewUInt256(256), - expected: "256", + value: NewUInt256(256), + string: "256", + expectedType: UInt256Type{}, }, "Int": { - value: NewInt(1000000), - expected: "1000000", + value: NewInt(1000000), + string: "1000000", + expectedType: IntType{}, }, "Int8": { - value: NewInt8(-8), - expected: "-8", + value: NewInt8(-8), + string: "-8", + expectedType: Int8Type{}, }, "Int16": { - value: NewInt16(-16), - expected: "-16", + value: NewInt16(-16), + string: "-16", + expectedType: Int16Type{}, }, "Int32": { - value: NewInt32(-32), - expected: "-32", + value: NewInt32(-32), + string: "-32", + expectedType: Int32Type{}, }, "Int64": { - value: NewInt64(-64), - expected: "-64", + value: NewInt64(-64), + string: "-64", + expectedType: Int64Type{}, }, "Int128": { - value: NewInt128(-128), - expected: "-128", + value: NewInt128(-128), + string: "-128", + expectedType: Int128Type{}, }, "Int256": { - value: NewInt256(-256), - expected: "-256", + value: NewInt256(-256), + string: "-256", + expectedType: Int256Type{}, }, "Word8": { - value: NewWord8(8), - expected: "8", + value: NewWord8(8), + string: "8", + expectedType: Word8Type{}, }, "Word16": { - value: NewWord16(16), - expected: "16", + value: NewWord16(16), + string: "16", + expectedType: Word16Type{}, }, "Word32": { - value: NewWord32(32), - expected: "32", + value: NewWord32(32), + string: "32", + expectedType: Word32Type{}, }, "Word64": { - value: NewWord64(64), - expected: "64", + value: NewWord64(64), + string: "64", + expectedType: Word64Type{}, }, "UFix64": { - value: ufix64, - expected: "64.01000000", + value: ufix64, + string: "64.01000000", + expectedType: UFix64Type{}, }, "Fix64": { - value: fix64, - expected: "-32.11000000", + value: fix64, + string: "-32.11000000", + expectedType: Fix64Type{}, }, "Void": { - value: NewVoid(), - expected: "()", + value: NewVoid(), + string: "()", + expectedType: VoidType{}, }, - "true": { - value: NewBool(true), - expected: "true", - }, - "false": { - value: NewBool(false), - expected: "false", + "Bool": { + value: NewBool(true), + string: "true", + expectedType: BoolType{}, }, "some": { - value: NewOptional(ufix64), - expected: "64.01000000", + value: NewOptional(ufix64), + string: "64.01000000", + expectedType: NewOptionalType(UFix64Type{}), }, "nil": { - value: NewOptional(nil), - expected: "nil", + value: NewOptional(nil), + string: "nil", + expectedType: NewOptionalType(NeverType{}), }, "String": { - value: String("Flow ridah!"), - expected: "\"Flow ridah!\"", + value: String("Flow ridah!"), + string: "\"Flow ridah!\"", + expectedType: StringType{}, + }, + "Character": { + value: Character("✌️"), + string: "\"\\u{270c}\\u{fe0f}\"", + expectedType: CharacterType{}, }, "Array": { value: NewArray([]Value{ NewInt(10), String("TEST"), }), - expected: "[10, \"TEST\"]", + exampleType: NewConstantSizedArrayType(2, AnyType{}), + withType: func(value Value, ty Type) Value { + return value.(Array).WithType(ty.(ArrayType)) + }, + string: "[10, \"TEST\"]", }, "Dictionary": { value: NewDictionary([]KeyValuePair{ @@ -164,18 +204,25 @@ func TestStringer(t *testing.T) { Value: String("value"), }, }), - expected: "{\"key\": \"value\"}", + exampleType: NewDictionaryType(StringType{}, StringType{}), + withType: func(value Value, ty Type) Value { + return value.(Dictionary).WithType(ty.(*DictionaryType)) + }, + string: "{\"key\": \"value\"}", }, "Bytes": { - value: NewBytes([]byte{0x1, 0x2}), - expected: "[0x1, 0x2]", + value: NewBytes([]byte{0x1, 0x2}), + string: "[0x1, 0x2]", + expectedType: BytesType{}, }, "Address": { - value: NewAddress([8]byte{0, 0, 0, 0, 0, 0, 0, 1}), - expected: "0x0000000000000001", + value: NewAddress([8]byte{0, 0, 0, 0, 0, 0, 0, 1}), + string: "0x0000000000000001", + expectedType: AddressType{}, }, "struct": { - value: NewStruct([]Value{String("bar")}).WithType(&StructType{ + value: NewStruct([]Value{String("bar")}), + exampleType: &StructType{ Location: utils.TestLocation, QualifiedIdentifier: "FooStruct", Fields: []Field{ @@ -184,11 +231,15 @@ func TestStringer(t *testing.T) { Type: StringType{}, }, }, - }), - expected: "S.test.FooStruct(y: \"bar\")", + }, + withType: func(value Value, ty Type) Value { + return value.(Struct).WithType(ty.(*StructType)) + }, + string: "S.test.FooStruct(y: \"bar\")", }, "resource": { - value: NewResource([]Value{NewInt(1)}).WithType(&ResourceType{ + value: NewResource([]Value{NewInt(1)}), + exampleType: &ResourceType{ Location: utils.TestLocation, QualifiedIdentifier: "FooResource", Fields: []Field{ @@ -197,8 +248,11 @@ func TestStringer(t *testing.T) { Type: IntType{}, }, }, - }), - expected: "S.test.FooResource(bar: 1)", + }, + withType: func(value Value, ty Type) Value { + return value.(Resource).WithType(ty.(*ResourceType)) + }, + string: "S.test.FooResource(bar: 1)", }, "event": { value: NewEvent( @@ -206,7 +260,8 @@ func TestStringer(t *testing.T) { NewInt(1), String("foo"), }, - ).WithType(&EventType{ + ), + exampleType: &EventType{ Location: utils.TestLocation, QualifiedIdentifier: "FooEvent", Fields: []Field{ @@ -219,11 +274,15 @@ func TestStringer(t *testing.T) { Type: StringType{}, }, }, - }), - expected: "S.test.FooEvent(a: 1, b: \"foo\")", + }, + withType: func(value Value, ty Type) Value { + return value.(Event).WithType(ty.(*EventType)) + }, + string: "S.test.FooEvent(a: 1, b: \"foo\")", }, "contract": { - value: NewContract([]Value{String("bar")}).WithType(&ContractType{ + value: NewContract([]Value{String("bar")}), + exampleType: &ContractType{ Location: utils.TestLocation, QualifiedIdentifier: "FooContract", Fields: []Field{ @@ -232,19 +291,69 @@ func TestStringer(t *testing.T) { Type: StringType{}, }, }, - }), - expected: "S.test.FooContract(y: \"bar\")", + }, + withType: func(value Value, ty Type) Value { + return value.(Contract).WithType(ty.(*ContractType)) + }, + string: "S.test.FooContract(y: \"bar\")", + }, + "enum": { + value: NewEnum([]Value{UInt8(1)}), + exampleType: &EnumType{ + Location: utils.TestLocation, + QualifiedIdentifier: "FooEnum", + Fields: []Field{ + { + Identifier: sema.EnumRawValueFieldName, + Type: UInt8Type{}, + }, + }, + }, + withType: func(value Value, ty Type) Value { + return value.(Enum).WithType(ty.(*EnumType)) + }, + string: "S.test.FooEnum(rawValue: 1)", + }, + "attachment": { + value: NewAttachment([]Value{NewInt(1)}), + exampleType: &AttachmentType{ + Location: utils.TestLocation, + QualifiedIdentifier: "FooAttachment", + Fields: []Field{ + { + Identifier: "bar", + Type: IntType{}, + }, + }, + }, + withType: func(value Value, ty Type) Value { + return value.(Attachment).WithType(ty.(*AttachmentType)) + }, + string: "S.test.FooAttachment(bar: 1)", + }, + "Link": { + value: NewPathLink( + Path{ + Domain: "storage", + Identifier: "foo", + }, + "Int", + ), + string: "PathLink(/storage/foo)", + noType: true, }, "Path": { value: Path{ Domain: "storage", Identifier: "foo", }, - expected: "/storage/foo", + expectedType: PathType{}, + string: "/storage/foo", }, "Type": { - value: TypeValue{StaticType: IntType{}}, - expected: "Type()", + value: TypeValue{StaticType: IntType{}}, + expectedType: NewMetaType(), + string: "Type()", }, "Capability": { value: StorageCapability{ @@ -252,29 +361,47 @@ func TestStringer(t *testing.T) { Address: BytesToAddress([]byte{1, 2, 3, 4, 5}), BorrowType: IntType{}, }, - expected: "Capability(address: 0x0000000102030405, path: /storage/foo)", + expectedType: NewCapabilityType(IntType{}), + string: "Capability(address: 0x0000000102030405, path: /storage/foo)", + }, + "Function": { + value: NewFunction( + testFunctionType, + ), + expectedType: testFunctionType, + string: "Function(...)", }, } +} + +func TestValue_String(t *testing.T) { - test := func(name string, testCase testCase) { + t.Parallel() + + test := func(name string, testCase valueTestCase) { t.Run(name, func(t *testing.T) { t.Parallel() + withType := testCase.withType + if withType != nil { + testCase.value = withType(testCase.value, testCase.exampleType) + } + assert.Equal(t, - testCase.expected, + testCase.string, testCase.value.String(), ) }) } - for name, testCase := range stringerTests { + for name, testCase := range newValueTestCases() { test(name, testCase) } } -func TestToBigEndianBytes(t *testing.T) { +func TestNumberValue_ToBigEndianBytes(t *testing.T) { t.Parallel() @@ -622,112 +749,50 @@ func TestNewUInt256FromBig(t *testing.T) { require.Error(t, err) } -//go:linkname typelinks reflect.typelinks -func typelinks() (sections []unsafe.Pointer, offset [][]int32) - -//go:linkname add reflect.add -func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer - -func TestGetType(t *testing.T) { +func TestValue_Type(t *testing.T) { t.Parallel() - t.Run("simple values", func(t *testing.T) { - - // This method test all simple typed values (and any newly added values/types). - - t.Parallel() + checkedTypes := map[Type]struct{}{} - complexTypes := map[reflect.Type]struct{}{ - reflect.TypeOf(Array{}): {}, - reflect.TypeOf(Contract{}): {}, - reflect.TypeOf(Dictionary{}): {}, - reflect.TypeOf(Event{}): {}, - reflect.TypeOf(Resource{}): {}, - reflect.TypeOf(Struct{}): {}, - } - - var valueInterface Value - valueInterfaceType := reflect.TypeOf(&valueInterface).Elem() + test := func(name string, testCase valueTestCase) { - checkedTypes := map[Type]struct{}{} + t.Run(name, func(t *testing.T) { - sections, offsets := typelinks() - for i, base := range sections { - for _, offset := range offsets[i] { - typeAddr := add(base, uintptr(offset), "") - valueType := reflect.TypeOf(*(*interface{})(unsafe.Pointer(&typeAddr))) + value := testCase.value - if !valueType.Implements(valueInterfaceType) { - continue - } + returnedType := value.Type() - valueType = valueType.Elem() + expectedType := testCase.expectedType + if expectedType != nil { + require.NotNil(t, returnedType) + require.True(t, returnedType != nil) + require.Equal(t, expectedType, returnedType) + } else if !testCase.noType { + exampleType := testCase.exampleType + require.NotNil(t, exampleType) - if _, ok := complexTypes[valueType]; ok { - continue - } + // Ensure the nil type is an *untyped nil* + require.Nil(t, returnedType) + require.True(t, returnedType == nil) - valueInstance := reflect.New(valueType) - value := valueInstance.Elem().Interface().(Value) + // Once a type is set, it should be returned + value = testCase.withType(value, exampleType) - // Check whether the type is always returned - cadenceType := value.Type() - assert.NotNil(t, cadenceType) + returnedType = value.Type() - // Check if the type is not a duplicate of some other type - // i.e: two values can't return the same type. - assert.NotContains(t, checkedTypes, cadenceType) - checkedTypes[cadenceType] = struct{}{} + require.NotNil(t, returnedType) + require.Equal(t, exampleType, returnedType) } - } - }) - t.Run("array value", func(t *testing.T) { - t.Parallel() - - typ := NewConstantSizedArrayType(4, TheInt8Type) - arrayValue := NewArray([]Value{}).WithType(typ) - assert.Equal(t, arrayValue.Type(), typ) - }) - - t.Run("contract value", func(t *testing.T) { - t.Parallel() - - typ := NewContractType(nil, "Foo", nil, nil) - value := NewContract([]Value{}).WithType(typ) - assert.Equal(t, typ, value.Type()) - }) - - t.Run("dictionary value", func(t *testing.T) { - t.Parallel() - - typ := NewDictionaryType(TheInt8Type, TheStringType) - value := NewDictionary([]KeyValuePair{}).WithType(typ) - assert.Equal(t, typ, value.Type()) - }) - - t.Run("event value", func(t *testing.T) { - t.Parallel() - - typ := NewEventType(nil, "Foo", nil, nil) - value := NewEvent([]Value{}).WithType(typ) - assert.Equal(t, typ, value.Type()) - }) - - t.Run("resource value", func(t *testing.T) { - t.Parallel() - - typ := NewResourceType(nil, "Foo", nil, nil) - value := NewResource([]Value{}).WithType(typ) - assert.Equal(t, typ, value.Type()) - }) - - t.Run("struct value", func(t *testing.T) { - t.Parallel() + // Check if the type is not a duplicate of some other type + // i.e: two values can't return the same type. + require.NotContains(t, checkedTypes, returnedType) + checkedTypes[returnedType] = struct{}{} + }) + } - typ := NewStructType(nil, "Foo", nil, nil) - value := NewStruct([]Value{}).WithType(typ) - assert.Equal(t, typ, value.Type()) - }) + for name, testCase := range newValueTestCases() { + test(name, testCase) + } } diff --git a/version.go b/version.go index 20aa2c8860..dfa632ff30 100644 --- a/version.go +++ b/version.go @@ -21,4 +21,4 @@ package cadence -const Version = "v0.35.0" +const Version = "v0.37.0"