Skip to content

Commit

Permalink
Merge pull request #2402 from onflow/bastian/sync-stable-cadence-11
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent authored Mar 30, 2023
2 parents 929f849 + 96ab3db commit be303b7
Show file tree
Hide file tree
Showing 104 changed files with 3,492 additions and 1,572 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
cache: true

- name: Build
run: make build
run: make -j8 build

- name: Run benchmark on current branch
run: |
Expand Down Expand Up @@ -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.
<details>
<summary>Collapsed results for better readability</summary>
<p>
${{ env.BENCHSTAT }}
</p>
</details>
</details>
edit-mode: replace
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:

- name: Run Tests
run: |
make test
make ci
make lint-github-actions
- name: Config git
Expand Down
60 changes: 36 additions & 24 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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) ./...
Expand All @@ -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))
Expand Down
Binary file added docs/images/create_release.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/release_action.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/release_tag.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/language/accounts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ to the `prepare` phase of the transaction.
fun borrow<T: &Any>(from: StoragePath): T?
fun link<T: &Any>(_ newCapabilityPath: CapabilityPath, target: Path): Capability<T>?
fun linkAccount(_ newCapabilityPath: PrivatePath): Capability<&AuthAccount>?
fun getCapability<T>(_ path: CapabilityPath): Capability<T>
fun getLinkTarget(_ path: CapabilityPath): Path?
fun unlink(_ path: CapabilityPath)
Expand Down
2 changes: 1 addition & 1 deletion docs/language/attachments.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: Attachments

<Callout type="warning">
⚠️ 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.
</Callout>

Attachments are a feature of Cadence designed to allow developers to extend a struct or resource type
Expand Down
26 changes: 23 additions & 3 deletions docs/language/built-in-functions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion docs/language/run-time-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 24 additions & 3 deletions docs/releasing.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -20,10 +20,10 @@ Check for breaking changes can be done using the [BackwardCompatibilityCheck](ht
github action.

<img src="images/compatibility_check_action_trigger.png" width="800"/>

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.

<img src="images/compatibility_check_action_params.png" width="300"/>
Expand Down Expand Up @@ -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":

<img src="images/release_tag.png" width="800"/>

On the release page, click the "Generate release notes" button:

<img src="images/create_release.png" width="800"/>

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! 🎉
25 changes: 25 additions & 0 deletions encoding/json/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)

Expand Down
18 changes: 18 additions & 0 deletions encoding/json/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down Expand Up @@ -239,6 +244,7 @@ const (
resourceTypeStr = "Resource"
eventTypeStr = "Event"
contractTypeStr = "Contract"
linkTypeStr = "Link"
pathTypeStr = "Path"
typeTypeStr = "Type"
capabilityTypeStr = "Capability"
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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,
Expand Down
35 changes: 32 additions & 3 deletions encoding/json/encoding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -2999,22 +3028,22 @@ 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
encodedValue := `
{
"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) {
Expand Down
Loading

0 comments on commit be303b7

Please sign in to comment.