Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds Preconditions feature w/ example #2

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Adds Preconditions feature w/ example #2

wants to merge 1 commit into from

Conversation

bkase
Copy link
Member

@bkase bkase commented Sep 7, 2022

For the purposes of this exercise please do not comment directly on this PR (as we want to use this for several candidates)!

You may use the PR to view the diff nicely, but please instead prepare your feedback in a markdown file feedback.md where you can comment on a line of code like:

src/examples/simple_zkapp.ts:84

I thought this line of code was particularly hard to understand. Could you instead do X or Y?

src/mina.ts:100

This is line 100 of mina.ts

You may also include comments that are not attached to particular file:lines at the top or bottom of your feedback.md file.

Thank you!


  • Adds precondition feature to SnarkyJS
  • Includes an example @ src/examples/simple_zkapp.ts
  • Adds a method for checking deep equality of circuit values

Explanation of the precondition feature below:

We consolidate account / network preconditions under a single field, this.account and this.network. Using account / network fields looks like this:

let myBalance = this.account.balance.get();
// should be equal to my actual balance
this.account.balance.assertEquals(myBalance);
// ... doing arbitrary computations with the balance

let chainLength = this.network.blockchainLength.get();
// should be not more than the current length + 5
this.network.blockchainLength.assertBetween(chainLength, chainLength.add(5));

this.account.balance.get() does the following: It fetches the balance from chain and creates a variable with that value in it. It does NOT link it to the current balance in the snark circuit. Instead, explicit assertEquals or assertBetween is necessary to create that link.

To make this not a footgun, we throw an error if the user doesn't add any explicit precondition on the field. The error is thrown when compiling, proving, or running the smart contract method in any other way. Example:

@method payout(caller: PublicKey) {
  let balance = this.account.balance.get();
  this.transfer(balance.div(10), caller); // tentative API to send money from the zkapp account
}
// ...

MyContract.compile(zkappAddress); // throws an error!

Running this would throw:

Error: You used `this.account.balance.get()` without adding a precondition that links it to the actual balance.
Consider adding this line to your code:
this.account.balance.assertEquals(this.account.balance.get());
You can also add more flexible preconditions with `this.account.balance.assertBetween`.
    at /home/gregor/my-zkapp/node_modules/snarkyjs/dist/server/index.js:5039:145
    ...

The developer would hopefully read the error message and modify their code like this .. which would fix the error, and teach them about preconditions at the same time.

@method payout(caller: PublicKey) {
  let balance = this.account.balance.get();
  this.account.balance.assertEquals(balance);
  this.transfer(balance.div(10), caller); // tentative API to send money from the zkapp account
}

* Adds precondition feature to SnarkyJS
* Includes an example @ src/examples/simple_zkapp.ts
* Adds a method for checking deep equality of circuit values

Explanation of the precondition feature below:

We consolidate account / network preconditions under a single field, `this.account` and `this.network`. Using account / network fields looks like this:

```ts
let myBalance = this.account.balance.get();
// should be equal to my actual balance
this.account.balance.assertEquals(myBalance);
// ... doing arbitrary computations with the balance

let chainLength = this.network.blockchainLength.get();
// should be not more than the current length + 5
this.network.blockchainLength.assertBetween(chainLength, chainLength.add(5));
```

`this.account.balance.get()` does the following: It fetches the balance from chain and creates a variable with that value in it. It does NOT link it to the current balance in the snark circuit. Instead, explicit `assertEquals` or `assertBetween` is necessary to create that link.

To make this not a footgun, we throw an error if the user doesn't add any explicit precondition on the field. The error is thrown when compiling, proving, or running the smart contract method in any other way. Example:

```ts
@method payout(caller: PublicKey) {
  let balance = this.account.balance.get();
  this.transfer(balance.div(10), caller); // tentative API to send money from the zkapp account
}
// ...

MyContract.compile(zkappAddress); // throws an error!
```

Running this would throw:

```
Error: You used `this.account.balance.get()` without adding a precondition that links it to the actual balance.
Consider adding this line to your code:
this.account.balance.assertEquals(this.account.balance.get());
You can also add more flexible preconditions with `this.account.balance.assertBetween`.
    at /home/gregor/my-zkapp/node_modules/snarkyjs/dist/server/index.js:5039:145
    ...
```

The developer would hopefully read the error message and modify their code like this .. which would fix the error, and teach them about preconditions at the same time.

```ts
@method payout(caller: PublicKey) {
  let balance = this.account.balance.get();
  this.account.balance.assertEquals(balance);
  this.transfer(balance.div(10), caller); // tentative API to send money from the zkapp account
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant