Skip to content

Commit

Permalink
Merge branch 'master' into bastian/improve-state-decoding-tool
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent authored Dec 2, 2021
2 parents 4a5ee02 + 141b10c commit 80d66a9
Show file tree
Hide file tree
Showing 143 changed files with 10,641 additions and 2,632 deletions.
88 changes: 88 additions & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: Benchmark
on:
pull_request:
branches:
- master
- 'feature/**'
- 'v**'

jobs:
benchmark:
name: Performance regression check
runs-on: ubuntu-latest
steps:
- name: Set benchmark repetitions
# reducing repetition will speed up execution,
# but will be more inaccurate at detecting change
run: echo "::set-output name=benchmark_repetitions::7"
id: settings

- name: Install dependencies
run: sudo apt-get update && sudo apt-get install wabt

- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0

- uses: actions/setup-go@v2
with:
go-version: '1.17.x'

- uses: actions/setup-node@v2
with:
node-version: '15'

- uses: actions/cache@v1
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Build
run: make build

- name: Run benchmark on current branch
run: |
( for i in {1..${{ steps.settings.outputs.benchmark_repetitions }}}; do go test ./... -run=XXX -bench=. -shuffle=on; done | sed 's/pkg:.*/pkg: github.com\/onflow\/cadence\/runtime/' ) | tee new.txt
# the package replace line above is to make the results table more readable, since it is not fragmented by package


- name: Checkout base branch
run: git checkout ${{ github.event.pull_request.base.sha }}

- name: Run benchmark on base branch
run: |
( for i in {1..${{ steps.settings.outputs.benchmark_repetitions }}}; do go test ./... -run=XXX -bench=. -shuffle=on; done | sed 's/pkg:.*/pkg: github.com\/onflow\/cadence\/runtime/' ) | tee old.txt
# see https://trstringer.com/github-actions-multiline-strings/ to see why this part is complex
- name: Use benchstat for comparison
run: |
export PATH=$PATH:$(go env GOPATH)/bin
GO111MODULE=off go get golang.org/x/perf/cmd/benchstat
echo "BENCHSTAT<<EOF" >> $GITHUB_ENV
echo "$(benchstat -html -sort delta old.txt new.txt | sed '/<title/,/<\/style>/d' | sed 's/<!doctype html>//g')" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Find existing comment on PR
uses: peter-evans/find-comment@v1
id: fc
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: "github-actions[bot]"
body-includes: "## Cadence [Benchstat](https://pkg.go.dev/golang.org/x/perf/cmd/benchstat) comparison"

- name: Create or update comment
uses: peter-evans/create-or-update-comment@v1
with:
comment-id: ${{ steps.fc.outputs.comment-id }}
issue-number: ${{ github.event.pull_request.number }}
body: |
## Cadence [Benchstat](https://pkg.go.dev/golang.org/x/perf/cmd/benchstat) comparison
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=. -shuffle=on; done` was used.
Bench tests were run a total of ${{ steps.settings.outputs.benchmark_repetitions }} times on each branch.
## Results
${{ env.BENCHSTAT }}
edit-mode: replace
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,9 @@ suppressions

languageserver/test/languageserver
coverage.txt
runtime/cmd/check/check
runtime/cmd/main/main
runtime/cmd/parse/parse
runtime/cmd/parse/parse.wasm
languageserver/cmd/languageserver/languageserver
languageserver/cmd/languageserver/languageserver.wasm
22 changes: 22 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Use your best judgment, and feel free to propose changes to this document in a p
- [Reporting Bugs](#reporting-bugs)
- [Suggesting Enhancements](#suggesting-enhancements)
- [Your First Code Contribution](#your-first-code-contribution)
- [Dependencies](#dependencies)
- [Pull Requests](#pull-requests)

[Styleguides](#styleguides)
Expand Down Expand Up @@ -89,6 +90,13 @@ You can start by looking through these "Good first issue" and "Help wanted" issu
Both issue lists are sorted by total number of comments.
While not perfect, number of comments is a reasonable proxy for impact a given change will have.

#### Dependencies

You need some software installed to build and test Cadence:

- [Go](https://golang.org/doc/install)
- [wasm2wat](https://github.com/WebAssembly/wabt)

### Pull Requests

The process described here has several goals:
Expand All @@ -102,6 +110,20 @@ Please follow the [styleguides](#styleguides) to have your contribution consider
Reviewer(s) may ask you to complete additional design work, tests,
or other changes before your pull request can be ultimately accepted.

When opening a PR as a maintainer:

- Use a branch name in the format `<github-username>/<issue-number>-<short-title>`
- Assign yourself to the PR. You are responsible to merge the PR once it has been approved.
- Request reviews from engineers who can review the components you modified
- Link to the GitHub issue, e.g. as `Closes #123`, or `Work towards #123`.
If there is no issue yet, create one.
- Fill out the check list in the PR description (prefilled by the template)
- Add (an) appropriate label(s)
- Review the PR yourself
- Make sure TODOs have been addressed
- Make sure debug print statements are removed
- Make sure the relevant documentation was updated or added

## Styleguides

Before contributing, make sure to examine the project to get familiar with the patterns and style already being used.
Expand Down
19 changes: 19 additions & 0 deletions docs/language/accounts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,17 @@ to the `prepare` phase of the transaction.
}
```

A script can get the `AuthAccount` for an account address using the built-in `getAuthAccount` function:

```cadence
fun getAuthAccount(_ address: Address): AuthAccount
```

This `AuthAccount` object can perform all operations associated with authorized accounts,
and as such this function is only available in scripts,
which discard their changes upon completion.
Attempting to use this function outside of a script will cause a type error.

## Account Creation

Accounts can be created by calling the `AuthAccount` constructor
Expand Down Expand Up @@ -359,6 +370,14 @@ to all its stored objects.

The path must be a storage path, i.e., only the domain `storage` is allowed.

- `cadence•fun type(at path: StoragePath): Type?`

Reads the type of an object from the account's storage which is stored under the given path, or nil if no object is stored under the given path.

If there is an object stored, the type of the object is returned without modifying the stored object.

The path must be a storage path, i.e., only the domain `storage` is allowed

- `cadence•fun load<T>(from: StoragePath): T?`

Loads an object from account storage.
Expand Down
25 changes: 25 additions & 0 deletions docs/language/crypto.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ struct PublicKey {
domainSeparationTag: String,
hashAlgorithm: HashAlgorithm
): Bool
/// Verifies the proof of possession of the private key.
/// This function is only implemented if the signature algorithm of the public key is BLS, it errors if called with any other signature algorithm.
pub fun verifyPoP(_ proof: [UInt8]): Bool
}
```

Expand Down Expand Up @@ -185,6 +189,27 @@ The inputs to `verify()` depend on the signature scheme used:

BLS verification performs the necessary membership check of the signature while the membership check of the public key is performed at the creation of the `PublicKey` object.

The BLS signature scheme also supports two additional operations on keys and signatures:

```cadence
/// This is a specific function for the BLS signature scheme. It aggregate multiple BLS signatures into one,
/// considering the proof of possession as a defence against the rogue attacks.
///
/// Signatures could be generated from the same or distinct messages, they
/// could also be the aggregation of other signatures.
/// The order of the signatures in the slice does not matter since the aggregation is commutative.
/// No subgroup membership check is performed on the input signatures.
/// The function errors if the array is empty or if decoding one of the signature fails.
AggregateBLSSignatures(_ signatures: [[UInt8]]): [UInt8]
/// This is a specific function for the BLS signature scheme. It aggregates multiple BLS public keys into one.
///
/// The order of the public keys in the slice does not matter since the aggregation is commutative.
/// No subgroup membership check is performed on the input keys.
/// The function errors if the array is empty or any of the input keys is not a BLS key.
AggregateBLSPublicKeys(_ signatures: [PublicKey]): PublicKey
```

## Crypto Contract

The built-in contract `Crypto` can be used to perform cryptographic operations.
Expand Down
145 changes: 145 additions & 0 deletions docs/language/type-inference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
---
title: Type Inference
---

If a variable or constant declaration is not annotated explicitly with a type,
the declaration's type is inferred from the initial value.

### Basic Literals
Decimal integer literals and hex literals are inferred to type `Int`.

```cadence
let a = 1
// `a` has type `Int`
let b = -45
// `b` has type `Int`
let c = 0x02
// `c` has type `Int`
```

Unsigned fixed-point literals are inferred to type `UFix64`.
Signed fixed-point literals are inferred to type `Fix64`.

```cadence
let a = 1.2
// `a` has type `UFix64`
let b = -1.2
// `b` has type `Fix64`
```

Similarly, for other basic literals, the types are inferred in the following manner:

| Literal Kind | Example | Inferred Type (x) |
|:-----------------:|:-----------------:|:-----------------:|
| String literal | `let x = "hello"` | String |
| Boolean literal | `let x = true` | Bool |
| Nil literal | `let x = nil` | Never? |


### Array Literals
Array literals are inferred based on the elements of the literal, and to be variable-size.
The inferred element type is the _least common super-type_ of all elements.

```cadence
let integers = [1, 2]
// `integers` has type `[Int]`
let int8Array = [Int8(1), Int8(2)]
// `int8Array` has type `[Int8]`
let mixedIntegers = [UInt(65), 6, 275, Int128(13423)]
// `mixedIntegers` has type `[Integer]`
let nilableIntegers = [1, nil, 2, 3, nil]
// `nilableIntegers` has type `[Int?]`
let mixed = [1, true, 2, false]
// `mixed` has type `[AnyStruct]`
```

### Dictionary Literals
Dictionary literals are inferred based on the keys and values of the literal.
The inferred type of keys and values is the _least common super-type_ of all keys and values, respectively.

```cadence
let booleans = {
1: true,
2: false
}
// `booleans` has type `{Int: Bool}`
let mixed = {
Int8(1): true,
Int64(2): "hello"
}
// `mixed` has type `{Integer: AnyStruct}`
// Invalid: mixed keys
//
let invalidMixed = {
1: true,
false: 2
}
// The least common super-type of the keys is `AnyStruct`.
// But it is not a valid type for dictionary keys.
```

### Ternary Expression
Ternary expression type is inferred to be the least common super-type of the second and third operands.
```cadence
let a = true ? 1 : 2
// `a` has type `Int`
let b = true ? 1 : nil
// `b` has type `Int?`
let c = true ? 5 : (false ? "hello" : nil)
// `c` has type `AnyStruct`
```

### Functions
Functions are inferred based on the parameter types and the return type.

```cadence
let add = (a: Int8, b: Int8): Int {
return a + b
}
// `add` has type `((Int8, Int8): Int)`
```

Type inference is performed for each expression / statement, and not across statements.

## Ambiguities
There are cases where types cannot be inferred.
In these cases explicit type annotations are required.

```cadence
// Invalid: not possible to infer type based on array literal's elements.
//
let array = []
// Instead, specify the array type and the concrete element type, e.g. `Int`.
//
let array: [Int] = []
// Or, use a simple-cast to annotate the expression with a type.
let array = [] as [Int]
```

```cadence
// Invalid: not possible to infer type based on dictionary literal's keys and values.
//
let dictionary = {}
// Instead, specify the dictionary type and the concrete key
// and value types, e.g. `String` and `Int`.
//
let dictionary: {String: Int} = {}
// Or, use a simple-cast to annotate the expression with a type.
let dictionary = {} as {String: Int}
```
Loading

0 comments on commit 80d66a9

Please sign in to comment.