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

Flexible circuit values #416

Merged
merged 30 commits into from
Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
467927e
refactor to/from auxiliary
mitschabaude Sep 14, 2022
054f8cc
make fromFields not pull apart input
mitschabaude Sep 14, 2022
7449160
ofFields -> fromFields, ofBits -> fromBits
mitschabaude Sep 14, 2022
67257f8
replace AsFieldElements with AsFieldsAndAux, implement Circuit.witnes…
mitschabaude Sep 14, 2022
2b238ec
update bindings for CI
mitschabaude Sep 14, 2022
6eb5912
use more general type almost everywhere
mitschabaude Sep 15, 2022
ad8c388
unify some types
mitschabaude Sep 15, 2022
22db1d3
wip: overhaul circuit value, unit tests failing still
mitschabaude Sep 15, 2022
a1d3a2d
fixup unit tests
mitschabaude Sep 15, 2022
39b8e28
make circuitValue usable as class
mitschabaude Sep 19, 2022
2d5513d
start using new circuit value
mitschabaude Sep 19, 2022
d1263c8
fix type
mitschabaude Sep 19, 2022
008e265
fix circuit value class type, export a different VerificationKey from…
mitschabaude Sep 20, 2022
997b93d
pass in verification key in dex contract
mitschabaude Sep 20, 2022
20d11fc
Merge branch 'main' into feature/flexible-circuit-values
mitschabaude Sep 20, 2022
18f7167
minor
mitschabaude Sep 20, 2022
72a5ef1
add missing check to Circuit.witness & test it
mitschabaude Sep 20, 2022
87fe555
add Boolean
mitschabaude Sep 20, 2022
07172b4
update token example to update vk
mitschabaude Sep 20, 2022
50e4fe8
renaming to Struct / provable
mitschabaude Sep 27, 2022
d32f345
remove accidentally added file
mitschabaude Sep 27, 2022
0348150
infer whether Struct is pure at the type level
mitschabaude Sep 27, 2022
6165d71
naming tweaks and use struct in example
mitschabaude Sep 27, 2022
af53d5a
add massive amounts of doccomments
mitschabaude Sep 27, 2022
819d0b9
doccomment provable
mitschabaude Sep 27, 2022
e7a06fb
Merge branch 'main' into feature/flexible-circuit-values
mitschabaude Sep 27, 2022
64ffaf0
Merge branch 'main' into feature/flexible-circuit-values
mitschabaude Sep 28, 2022
9ac2c27
update changelog
mitschabaude Sep 28, 2022
18b0536
update bindings
mitschabaude Sep 28, 2022
467a39a
changelog
mitschabaude Sep 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion MINA_COMMIT
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
The mina commit used to generate the backends for node and chrome is
778f499316fe439a7a843f91cd3c6e05484b3f7d
98a2af2e4f0a1317a3401ba22a71e1b90ceb083f
2 changes: 1 addition & 1 deletion run-unit-tests.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
npm run build:test
for f in ./dist/test/**/*.unit-test.js; do
echo "Running $f"
node $f || (echo 'tests failed' && exit 1)
node $f || exit 1;
done
6 changes: 3 additions & 3 deletions src/build/jsLayoutToTypes.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ function writeTsContent(types, isJson) {
mergeObject(converters, inner.converters);
output += `type ${Type} = ${inner.output};\n\n`;
if (!isJson) {
output += `let ${Type} = asFieldsAndAux<${Type}, Json.${Type}>(jsLayout.${Type} as any, customTypes);\n\n`;
output += `let ${Type} = provableFromLayout<${Type}, Json.${Type}>(jsLayout.${Type} as any, customTypes);\n\n`;
}
}

Expand All @@ -136,7 +136,7 @@ function writeTsContent(types, isJson) {
import { ${[...imports].join(', ')} } from '${importPath}';
${
!isJson
? "import { asFieldsAndAux, AsFieldsAndAux } from '../transaction-helpers.js';\n" +
? "import { provableFromLayout, ProvableExtended } from '../transaction-helpers.js';\n" +
"import * as Json from './transaction-json.js';\n" +
"import { jsLayout } from './js-layout.js';\n"
: ''
Expand All @@ -153,7 +153,7 @@ ${
(!isJson || '') &&
`
type CustomTypes = { ${customTypes
.map((c) => `${c.typeName}: AsFieldsAndAux<${c.type}, ${c.jsonType}>;`)
.map((c) => `${c.typeName}: ProvableExtended<${c.type}, ${c.jsonType}>;`)
.join(' ')} }
let customTypes: CustomTypes = { ${customTypeNames.join(', ')} };
`
Expand Down
238 changes: 119 additions & 119 deletions src/chrome_bindings/snarky_js_chrome.bc.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/examples/ex01_small_preimage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Main extends Circuit {

const kp = Main.generateKeypair();

const preimage = Field.ofBits(Field.random().toBits().slice(0, 32));
const preimage = Field.fromBits(Field.random().toBits().slice(0, 32));
const hash = Poseidon.hash([preimage]);
const pi = Main.prove([preimage], [hash], kp);
console.log('proof', pi);
6 changes: 3 additions & 3 deletions src/examples/matrix_mul.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Field, circuitValue, Circuit } from 'snarkyjs';
import { Field, provable, Circuit } from 'snarkyjs';

// there are two ways of specifying an n*m matrix

// circuitValue
let Matrix3x3 = circuitValue<Field[][]>([
// provable
let Matrix3x3 = provable([
[Field, Field, Field],
[Field, Field, Field],
[Field, Field, Field],
Expand Down
16 changes: 6 additions & 10 deletions src/examples/party-witness.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {
Types,
AccountUpdate,
PrivateKey,
Circuit,
circuitValue,
} from 'snarkyjs';
import { Types, AccountUpdate, PrivateKey, Circuit, provable } from 'snarkyjs';

let address = PrivateKey.random().toPublicKey();

Expand All @@ -23,7 +17,7 @@ let json = Types.AccountUpdate.toJSON(accountUpdateRaw);

if (address.toBase58() !== json.body.publicKey) throw Error('fail');

let Null = circuitValue<null>(null);
let Null = provable(null);

Circuit.runAndCheck(() => {
let accountUpdateWitness = AccountUpdate.witness(Null, () => ({
Expand All @@ -48,7 +42,9 @@ let result = Circuit.constraintSystem(() => {
Circuit.assertEqual(Types.AccountUpdate, accountUpdateWitness, accountUpdate);
});

console.log(`a accountUpdate has ${Types.AccountUpdate.sizeInFields()} fields`);
console.log(
`witnessing a accountUpdate and comparing it to another one creates ${result.rows} rows`
`an account update has ${Types.AccountUpdate.sizeInFields()} fields`
);
console.log(
`witnessing an account update and comparing it to another one creates ${result.rows} rows`
);
14 changes: 7 additions & 7 deletions src/examples/rollup/data_store.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
Circuit,
Bool,
AsFieldElements,
ProvablePure,
Field,
Poseidon,
asFieldElementsToConstant,
Expand Down Expand Up @@ -45,8 +45,8 @@ export interface KeyedDataStore<K, V, P> {

export class Keyed {
static InMemory<K, V>(
eltTyp: AsFieldElements<V>,
keyTyp: AsFieldElements<K>,
eltTyp: ProvablePure<V>,
keyTyp: ProvablePure<K>,
key: (v: V) => K,
depth: number
): KeyedDataStore<K, V, MerkleProof> {
Expand All @@ -66,7 +66,7 @@ export class Keyed {
for (var i = 0; i < n; ++i) {
xs.push(Field.zero);
}
return eltTyp.ofFields(xs);
return eltTyp.fromFields(xs);
})();

const getValue = (k: K): { value: V; empty: boolean } => {
Expand Down Expand Up @@ -132,14 +132,14 @@ export class Keyed {
}

export function IPFS<A>(
eltTyp: AsFieldElements<A>,
eltTyp: ProvablePure<A>,
ipfsRoot: string
): DataStore<A, MerkleProof> {
throw 'ipfs';
}

export function InMemory<A>(
eltTyp: AsFieldElements<A>,
eltTyp: ProvablePure<A>,
depth: number
): DataStore<A, MerkleProof> {
const P = MerkleProofFactory(depth);
Expand Down Expand Up @@ -195,7 +195,7 @@ export function InMemory<A>(
}

export function OnDisk<A>(
eltTyp: AsFieldElements<A>,
eltTyp: ProvablePure<A>,
path: string
): DataStore<A, MerkleProof> {
throw 'ondisk';
Expand Down
16 changes: 8 additions & 8 deletions src/examples/rollup/merkle_proof.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
Field,
Circuit,
Poseidon,
AsFieldElements,
ProvablePure,
Optional,
} from 'snarkyjs';
import { DataStore, KeyedDataStore } from './data_store';
Expand Down Expand Up @@ -56,7 +56,7 @@ export function MerkleAccumulatorFactory<A extends CircuitValue>(
return [x.root];
}

static ofFields(xs: Field[]): MerkleAccumulator {
static fromFields(xs: Field[]): MerkleAccumulator {
return new MerkleAccumulator(xs[0]);
}

Expand Down Expand Up @@ -168,7 +168,7 @@ export function KeyedAccumulatorFactory<
return [x.root];
}

static ofFields(xs: Field[]): KeyedAccumulator {
static fromFields(xs: Field[]): KeyedAccumulator {
return new KeyedAccumulator(xs[0]);
}

Expand Down Expand Up @@ -258,10 +258,10 @@ export function MerkleProofFactory(depth: number) {
return x.path;
}

static ofFields(xs: Array<Field>): MerkleProof {
static fromFields(xs: Array<Field>): MerkleProof {
if (xs.length !== depth) {
throw new Error(
`MerkleTree: ofFields expected array of length ${depth}, got ${xs.length}`
`MerkleTree: fromFields expected array of length ${depth}, got ${xs.length}`
);
}
return new MerkleProof(xs);
Expand Down Expand Up @@ -290,7 +290,7 @@ export function IndexFactory(depth: number) {
return new Index(res);
}

static ofFields(xs: Field[]): Index {
static fromFields(xs: Field[]): Index {
return new Index(xs.map((x) => Bool.Unsafe.ofField(x)));
}

Expand Down Expand Up @@ -554,7 +554,7 @@ function constantIndex(xs: Array<Bool>): Array<boolean> {
}

export class Collection<A> {
eltTyp: AsFieldElements<A>;
eltTyp: ProvablePure<A>;
values:
| { computed: true; value: MerkleTree<A> }
| { computed: false; f: () => MerkleTree<A> };
Expand All @@ -572,7 +572,7 @@ export class Collection<A> {
return this.root;
}

constructor(eltTyp: AsFieldElements<A>, f: () => Tree<A>, root?: Field) {
constructor(eltTyp: ProvablePure<A>, f: () => Tree<A>, root?: Field) {
this.eltTyp = eltTyp;
this.cachedPaths = new Map();
this.cachedValues = new Map();
Expand Down
14 changes: 4 additions & 10 deletions src/examples/rollup/merkle_stack.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import {
AsFieldElements,
Circuit,
Field,
Poseidon,
CircuitValue,
} from 'snarkyjs';
import { ProvablePure, Circuit, Field, Poseidon, CircuitValue } from 'snarkyjs';

// TODO: Implement AsFieldElements
// TODO: Implement ProvablePure
export class MerkleStack<A extends CircuitValue> {
commitment: Field;
eltTyp: AsFieldElements<A>;
eltTyp: ProvablePure<A>;
values:
| { computed: true; value: Array<[A, Field]> }
| { computed: false; f: () => Array<[A, Field]> };
Expand All @@ -18,7 +12,7 @@ export class MerkleStack<A extends CircuitValue> {
return Poseidon.hash([comm].concat(x.toFields()));
}

constructor(eltTyp: AsFieldElements<A>, f: () => Array<[A, Field]>) {
constructor(eltTyp: ProvablePure<A>, f: () => Array<[A, Field]>) {
this.values = { computed: false, f };
this.eltTyp = eltTyp;
// TODO
Expand Down
14 changes: 7 additions & 7 deletions src/examples/zkapps/dex/dex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
Account,
Bool,
Circuit,
circuitValue,
provable,
CircuitValue,
DeployArgs,
Experimental,
Expand All @@ -19,6 +19,7 @@ import {
SmartContract,
Token,
UInt64,
VerificationKey,
} from 'snarkyjs';

export { Dex, DexTokenHolder, TokenContract, keys, addresses, tokenIds };
Expand Down Expand Up @@ -165,8 +166,8 @@ class Dex extends SmartContract {
}

// TODO: this is a pain -- let's define circuit values in one line, with a factory pattern
// we just have to make circuitValue return a class, that's it!
// class UInt64x2 extends circuitValue([UInt64, UInt64]) {}
// we just have to make provable return a class, that's it!
// class UInt64x2 extends provable([UInt64, UInt64]) {}
class UInt64x2 extends CircuitValue {
@prop 0: UInt64;
@prop 1: UInt64;
Expand Down Expand Up @@ -225,7 +226,7 @@ class DexTokenHolder extends SmartContract {

// TODO: getting the account update here w/o messing up the account updates structure is error-prone and non-obvious
let tokenYUpdate = AccountUpdate.witnessTree(
circuitValue<null>(null),
provable(null),
// need to walk two layers deeper, and need to respect the actual max number of child account updates
[[undefined, undefined, undefined], undefined, undefined],
() => {
Expand Down Expand Up @@ -321,7 +322,7 @@ class TokenContract extends SmartContract {

// this is a very standardized deploy method. instead, we could also take the account update from a callback
// => need callbacks for signatures
@method deployZkapp(address: PublicKey) {
@method deployZkapp(address: PublicKey, verificationKey: VerificationKey) {
let tokenId = this.experimental.token.id;
let zkapp = Experimental.createChildAccountUpdate(
this.self,
Expand All @@ -332,8 +333,7 @@ class TokenContract extends SmartContract {
...Permissions.default(),
send: Permissions.proof(),
});
// TODO pass in verification key --> make it a circuit value --> make circuit values able to hold auxiliary data
// AccountUpdate.setValue(zkapp.update.verificationKey, verificationKey);
AccountUpdate.setValue(zkapp.update.verificationKey, verificationKey);
zkapp.sign();
}

Expand Down
22 changes: 11 additions & 11 deletions src/examples/zkapps/dex/erc20.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
AsFieldElements,
ProvablePure,
Bool,
CircuitString,
circuitValue,
provablePure,
DeployArgs,
Field,
method,
Expand Down Expand Up @@ -38,12 +38,12 @@ type Erc20 = {

// events
events: {
Transfer: AsFieldElements<{
Transfer: ProvablePure<{
from: PublicKey;
to: PublicKey;
value: UInt64;
}>;
Approval: AsFieldElements<{
Approval: ProvablePure<{
owner: PublicKey;
spender: PublicKey;
value: UInt64;
Expand Down Expand Up @@ -151,16 +151,16 @@ class TrivialCoin extends SmartContract implements Erc20 {
}

events = {
Transfer: circuitValue<{ from: PublicKey; to: PublicKey; value: UInt64 }>({
Transfer: provablePure({
from: PublicKey,
to: PublicKey,
value: UInt64,
}),
Approval: circuitValue<{
owner: PublicKey;
spender: PublicKey;
value: UInt64;
}>({ owner: PublicKey, spender: PublicKey, value: UInt64 }),
Approval: provablePure({
owner: PublicKey,
spender: PublicKey,
value: UInt64,
}),
};

// additional API needed for zkApp token accounts
Expand Down Expand Up @@ -204,7 +204,7 @@ class TrivialCoin extends SmartContract implements Erc20 {
...Permissions.default(),
send: Permissions.proof(),
});
// TODO pass in verification key --> make it a circuit value --> make circuit values able to hold auxiliary data
// TODO pass in verification key
// AccountUpdate.setValue(zkapp.update.verificationKey, verificationKey);
zkapp.sign(zkappKey);
}
Expand Down
4 changes: 2 additions & 2 deletions src/examples/zkapps/dex/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ tx = await Mina.transaction(feePayerKey, () => {
// pay fees for creating 3 dex accounts
AccountUpdate.createSigned(feePayerKey).balance.subInPlace(accountFee.mul(3));
dex.deploy();
tokenX.deployZkapp(addresses.dex);
tokenY.deployZkapp(addresses.dex);
tokenX.deployZkapp(addresses.dex, DexTokenHolder._verificationKey!);
tokenY.deployZkapp(addresses.dex, DexTokenHolder._verificationKey!);
});
await tx.prove();
tx.sign([keys.dex]);
Expand Down
7 changes: 3 additions & 4 deletions src/examples/zkapps/reducer/reducer_composite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,18 @@ import {
AccountUpdate,
isReady,
Permissions,
circuitValue,
Bool,
Circuit,
Struct,
} from 'snarkyjs';
import assert from 'node:assert/strict';

await isReady;

type MaybeIncrement = { isIncrement: Bool; otherData: Field };
const MaybeIncrement = circuitValue<MaybeIncrement>({
class MaybeIncrement extends Struct({
isIncrement: Bool,
otherData: Field,
});
}) {}
const INCREMENT = { isIncrement: Bool(true), otherData: Field.zero };

class CounterZkapp extends SmartContract {
Expand Down
Loading