Skip to content

Commit

Permalink
Merge pull request #902 from o1-labs/refactor/field
Browse files Browse the repository at this point in the history
Move Field to JS
  • Loading branch information
mitschabaude authored May 31, 2023
2 parents 11a1fba + d6b7f5b commit c331808
Show file tree
Hide file tree
Showing 32 changed files with 2,123 additions and 442 deletions.
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,38 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Breaking changes

- Rewrite of `Provable.if()` causes breaking changes to all deployed contracts https://github.com/o1-labs/snarkyjs/pull/889
- Remove all deprecated methods and properties on `Field` https://github.com/o1-labs/snarkyjs/pull/902
- The `Field(x)` constructor and other Field methods no longer accept a `boolean` as input. Instead, you can now pass in a `bigint` to all Field methods. https://github.com/o1-labs/snarkyjs/pull/902

### Added

- Add `field.assertNotEquals()` to assert that a field element does not equal some value https://github.com/o1-labs/snarkyjs/pull/902
- More efficient than `field.equals(x).assertFalse()`

### Changed

- **Make stack traces more readable** https://github.com/o1-labs/snarkyjs/pull/890
- Stack traces thrown from SnarkyJS are cleaned up by filtering out unnecessary lines and other noisy details
- Remove optional `zkappKey` argument in `smartContract.init()`, and instead assert that `provedState` is false when `init()` is called https://github.com/o1-labs/snarkyjs/pull/908
- Improve assertion error messages on `Field` methods https://github.com/o1-labs/snarkyjs/issues/743 https://github.com/o1-labs/snarkyjs/pull/902
- Publicly expose the internal details of the `Field` type https://github.com/o1-labs/snarkyjs/pull/902

### Deprecated

- Utility methods on `Circuit` are deprecated in favor of the same methods on `Provable` https://github.com/o1-labs/snarkyjs/pull/889
- `Circuit.if()`, `Circuit.witness()`, `Circuit.log()` and others replaced by `Provable.if()`, `Provable.witness()`, `Provable.log()`
- Under the hood, some of these methods were rewritten in TypeScript
- Deprecate `field.isZero()` https://github.com/o1-labs/snarkyjs/pull/902

### Fixed

- Fix running SnarkyJS in Node.js on Windows https://github.com/o1-labs/snarkyjs-bindings/pull/19 (@wizicer)[https://github.com/wizicer]
- Fix running SnarkyJS in Node.js on Windows https://github.com/o1-labs/snarkyjs-bindings/pull/19 [@wizicer](https://github.com/wizicer)
- Fix error reporting from GraphQL requests https://github.com/o1-labs/snarkyjs/pull/919
- Resolved an `Out of Memory error` experienced on iOS devices (iPhones and iPads) during the initialization of the WASM memory https://github.com/o1-labs/snarkyjs-bindings/pull/26
- Fix `field.greaterThan()` and other comparison methods outside provable code https://github.com/o1-labs/snarkyjs/issues/858 https://github.com/o1-labs/snarkyjs/pull/902
- Fix `field.assertBool()` https://github.com/o1-labs/snarkyjs/issues/469 https://github.com/o1-labs/snarkyjs/pull/902
- Fix `Field(bigint)` where `bigint` is larger than the field modulus https://github.com/o1-labs/snarkyjs/issues/432 https://github.com/o1-labs/snarkyjs/pull/902
- The new behaviour is to use the modular residual of the input

## [0.10.1](https://github.com/o1-labs/snarkyjs/compare/bcc666f2...a632313a)

Expand Down
2 changes: 1 addition & 1 deletion src/bindings
6 changes: 3 additions & 3 deletions src/examples/zkapps/hello_world/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ try {
await txn.prove();
await txn.sign([feePayer1.privateKey]).send();
} catch (err: any) {
handleError(err, 'assert_equal');
handleError(err, 'assertEquals');
}

if (!correctlyFails) {
Expand All @@ -120,7 +120,7 @@ try {
await txn.prove();
await txn.sign([feePayer1.privateKey]).send();
} catch (err: any) {
handleError(err, 'assert_equal');
handleError(err, 'assertEquals');
}

if (!correctlyFails) {
Expand Down Expand Up @@ -176,7 +176,7 @@ try {
await txn4.prove();
await txn4.sign([feePayer4.privateKey]).send();
} catch (err: any) {
handleError(err, 'assert_equal');
handleError(err, 'assertEquals');
}

if (!correctlyFails) {
Expand Down
41 changes: 19 additions & 22 deletions src/examples/zkapps/voting/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,10 +300,10 @@ export async function testSet(
}
}

if (sequenceOverflowSet.voterContract.reducer.getActions({}).length < 3) {
if (sequenceOverflowSet.voterContract.reducer.getActions().length < 3) {
throw Error(
`Did not emit expected actions! Only emitted ${
sequenceOverflowSet.voterContract.reducer.getActions({}).length
sequenceOverflowSet.voterContract.reducer.getActions().length
}`
);
}
Expand Down Expand Up @@ -387,7 +387,7 @@ export async function testSet(
feePayer
);

if (voterContract.reducer.getActions({}).length !== 1) {
if (voterContract.reducer.getActions().length !== 1) {
throw Error(
'Should have emitted 1 event after registering only one valid voter'
);
Expand Down Expand Up @@ -468,10 +468,10 @@ export async function testSet(
voting.voterRegistration(newVoter1);
},
feePayer,
'assert_equal'
'Member already exists!'
);

if (voterContract.reducer.getActions({}).length !== 1) {
if (voterContract.reducer.getActions().length !== 1) {
throw Error(
'Should have emitted 1 event after registering only one valid voter'
);
Expand Down Expand Up @@ -540,8 +540,8 @@ export async function testSet(
feePayer
);

let numberOfEvents = candidateContract.reducer.getActions({}).length;
if (candidateContract.reducer.getActions({}).length !== 2) {
let numberOfEvents = candidateContract.reducer.getActions().length;
if (candidateContract.reducer.getActions().length !== 2) {
throw Error(
`Should have emitted 2 event after registering 2 candidates. ${numberOfEvents} emitted`
);
Expand Down Expand Up @@ -636,10 +636,8 @@ export async function testSet(
);
Local.setGlobalSlot(params.electionPreconditions.startElection.add(1));

let previousEventsVoter = voterContract.reducer.getActions({}).length;
let previousEventsCandidate = candidateContract.reducer.getActions(
{}
).length;
let previousEventsVoter = voterContract.reducer.getActions().length;
let previousEventsCandidate = candidateContract.reducer.getActions().length;

let lateCandidate = Member.from(
PrivateKey.random().toPublicKey(),
Expand All @@ -654,7 +652,7 @@ export async function testSet(
voting.candidateRegistration(lateCandidate);
},
feePayer,
'assert_equal'
'Outside of election period!'
);

console.log(
Expand All @@ -674,15 +672,14 @@ export async function testSet(
voting.voterRegistration(lateVoter);
},
feePayer,
'assert_equal'
'Outside of election period!'
);

if (previousEventsVoter !== voterContract.reducer.getActions({}).length) {
if (previousEventsVoter !== voterContract.reducer.getActions().length) {
throw Error('events emitted but should not have been');
}
if (
previousEventsCandidate !==
candidateContract.reducer.getActions({}).length
previousEventsCandidate !== candidateContract.reducer.getActions().length
) {
throw Error('events emitted but should not have been');
}
Expand Down Expand Up @@ -784,7 +781,7 @@ export async function testSet(

vote(0n, votesStore, candidatesStore);

numberOfEvents = voting.reducer.getActions({}).length;
numberOfEvents = voting.reducer.getActions().length;
if (numberOfEvents !== 1) {
throw Error('Should have emitted 1 event after voting for a candidate');
}
Expand Down Expand Up @@ -825,7 +822,7 @@ export async function testSet(
voting.vote(fakeCandidate, votersStore.get(0n)!);
},
feePayer,
'assert_equal'
'Member is not a candidate!'
);

console.log('unregistered voter attempting to vote');
Expand All @@ -842,7 +839,7 @@ export async function testSet(
voting.vote(fakeVoter, votersStore.get(0n)!);
},
feePayer,
'assert_equal'
'Member is not a candidate!'
);

console.log('attempting to vote for voter...');
Expand All @@ -854,7 +851,7 @@ export async function testSet(
voting.vote(voter, votersStore.get(0n)!);
},
feePayer,
'assert_equal'
'Member is not a candidate!'
);

/*
Expand Down Expand Up @@ -934,7 +931,7 @@ export async function testSet(
voting.voterRegistration(voter);
},
feePayer,
'assert_equal'
'Outside of election period!'
);

console.log('attempting to register candidate after election has ended');
Expand All @@ -951,7 +948,7 @@ export async function testSet(
voting.candidateRegistration(candidate);
},
feePayer,
'assert_equal'
'Outside of election period!'
);
}

Expand Down
4 changes: 2 additions & 2 deletions src/examples/zkapps/voting/voting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export class Voting_ extends SmartContract {
// the check happens here because we want to see if the other contract returns a value
// if exists is true, that means the member already exists within the accumulated state
// if its false, its a new entry
exists.assertEquals(false);
exists.assertFalse('Member already exists!');
}

/**
Expand All @@ -175,7 +175,7 @@ export class Voting_ extends SmartContract {
electionPreconditions.enforce,
currentSlot.lessThanOrEqual(electionPreconditions.startElection),
Bool(true)
).assertTrue();
).assertTrue('Outside of election period!');

// can only register candidates if their balance is gte the minimum amount required
// and lte the maximum amount
Expand Down
8 changes: 0 additions & 8 deletions src/lib/account_update.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
isReady,
Ledger,
Circuit,
AccountUpdate,
PrivateKey,
shutdown,
Expand Down Expand Up @@ -56,7 +55,6 @@ describe('AccountUpdate', () => {
// TODO remove restriction "This function can't be run outside of a checked computation."
Provable.runAndCheck(() => {
let hash = accountUpdate.hash();
expect(isField(hash)).toBeTruthy();

// if we clone the accountUpdate, hash should be the same
let accountUpdate2 = AccountUpdate.clone(accountUpdate);
Expand Down Expand Up @@ -101,9 +99,3 @@ describe('AccountUpdate', () => {
expect(TokenId.fromBase58(defaultTokenId).toString()).toEqual('1');
});
});

// to check that we got something that looks like a Field
// note: `instanceof Field` doesn't work
function isField(x: any) {
return x?.constructor === Field(1).constructor;
}
12 changes: 3 additions & 9 deletions src/lib/account_update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,7 @@ import { UInt64, UInt32, Int64, Sign } from './int.js';
import * as Mina from './mina.js';
import { SmartContract } from './zkapp.js';
import * as Precondition from './precondition.js';
import {
dummyBase64Proof,
Empty,
inCheckedComputation,
Proof,
Prover,
} from './proof_system.js';
import { dummyBase64Proof, Empty, Proof, Prover } from './proof_system.js';
import { Memo } from '../mina-signer/src/memo.js';
import {
Events,
Expand Down Expand Up @@ -1084,7 +1078,7 @@ class AccountUpdate implements Types.AccountUpdate {
// consistency between JS & OCaml hashing on *every single account update
// proof* we create. It will give us 100% confidence that the two
// implementations are equivalent, and catch regressions quickly
if (inCheckedComputation()) {
if (Provable.inCheckedComputation()) {
let input = Types.AccountUpdate.toInput(this);
return hashWithPrefix(prefixes.body, packToFields(input));
} else {
Expand Down Expand Up @@ -1578,7 +1572,7 @@ const CallForest = {
return Provable.witness(Field, () => CallForest.hashChildrenBase(update));
}
let calls = CallForest.hashChildrenBase(update);
if (callsType.type === 'Equals' && inCheckedComputation()) {
if (callsType.type === 'Equals' && Provable.inCheckedComputation()) {
calls.assertEquals(callsType.value);
}
return calls;
Expand Down
4 changes: 2 additions & 2 deletions src/lib/circuit.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { snarkContext } from './proof_system.js';
import { ProvablePure, Snarky } from '../snarky.js';
import { Field } from './core.js';
import { withThreadPool } from '../bindings/js/wrapper.js';
import { Provable, gatesFromJson } from './provable.js';
import { Provable } from './provable.js';
import { snarkContext, gatesFromJson } from './provable-context.js';

// external API
export { public_, circuitMain, Circuit, Keypair, Proof, VerificationKey };
Expand Down
3 changes: 2 additions & 1 deletion src/lib/circuit_value.unit-test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Field, isReady, shutdown } from '../snarky.js';
import { isReady, shutdown } from '../snarky.js';
import { provable, Struct } from './circuit_value.js';
import { UInt32 } from './int.js';
import { PrivateKey, PublicKey } from './signature.js';
Expand All @@ -8,6 +8,7 @@ import { LocalBlockchain, setActiveInstance, transaction } from './mina.js';
import { State, state } from './state.js';
import { AccountUpdate } from './account_update.js';
import { Provable } from './provable.js';
import { Field } from './core.js';

await isReady;

Expand Down
Loading

0 comments on commit c331808

Please sign in to comment.