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

Async circuits, pt. 1 - async circuit runners #1450

Merged
merged 34 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
6f2cece
get verification key is a promise
mitschabaude Feb 20, 2024
eda6942
async constraint system
mitschabaude Feb 21, 2024
e30a618
async cricuits poc
mitschabaude Feb 23, 2024
f666db4
Merge branch 'main' into feature/async-circuits
mitschabaude Feb 27, 2024
acceaac
assert promise helper
mitschabaude Feb 27, 2024
6add8c2
allow async inputs to compile
mitschabaude Feb 27, 2024
86169e7
simplify constraint system async
mitschabaude Feb 27, 2024
b26ae27
async constraint system
mitschabaude Feb 27, 2024
87d2a34
expose async run and check
mitschabaude Feb 27, 2024
2dcc126
support not checking constraints
mitschabaude Feb 27, 2024
9b4d2c4
async witness generation
mitschabaude Feb 27, 2024
0f65c98
digest is async
mitschabaude Feb 27, 2024
d6f8cd6
fix: sync analyze methods for reducer
mitschabaude Feb 27, 2024
e83b3ae
remove hack around running analyzeMethods from a contract (t wasn't w…
mitschabaude Feb 27, 2024
ed57417
fix examples build
mitschabaude Feb 27, 2024
933b133
comment for later
mitschabaude Feb 27, 2024
6f65555
fixup unit tests
mitschabaude Feb 27, 2024
298c4bd
this wasn't working - just accept actions per method as a parameter f…
mitschabaude Feb 27, 2024
140f7cb
bindings
mitschabaude Feb 27, 2024
8df5fc6
tweak
mitschabaude Feb 27, 2024
74f0e15
this doesn't make sense..
mitschabaude Feb 27, 2024
0788d77
ok no it needs to be this
mitschabaude Feb 27, 2024
b708ec1
vks
mitschabaude Feb 27, 2024
ed310ed
minor
mitschabaude Feb 27, 2024
ee8cb90
remove unused snarky apis
mitschabaude Feb 27, 2024
9c63fca
remove tmp test
mitschabaude Feb 27, 2024
ac3bb5a
remove deprecated experimental.zkprogram
mitschabaude Feb 27, 2024
d31f488
fix proof systems unit test
mitschabaude Feb 27, 2024
183bff4
changelog
mitschabaude Feb 27, 2024
b47224f
finalize, then count rows
mitschabaude Feb 28, 2024
464adba
Merge branch 'release/v0.16.3' into feature/async-circuits
mitschabaude Mar 6, 2024
2198f59
Merge branch 'main' into feature/async-circuits
mitschabaude Mar 7, 2024
147b607
submodules and revert vk regression
mitschabaude Mar 7, 2024
3cbc4b5
fixup benchmarks and type check them in ci
mitschabaude Mar 7, 2024
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
4 changes: 2 additions & 2 deletions src/examples/benchmarks/foreign-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ main();
console.timeEnd('running constant version');

console.time('running witness generation & checks');
Provable.runAndCheck(main);
await Provable.runAndCheck(main);
console.timeEnd('running witness generation & checks');

console.time('creating constraint system');
let cs = Provable.constraintSystem(main);
let cs = await Provable.constraintSystem(main);
console.timeEnd('creating constraint system');

console.log(cs.summary());
2 changes: 1 addition & 1 deletion src/examples/benchmarks/hash-witness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ function main(nMuls: number) {
}

tic('run and check');
Provable.runAndCheck(() => main(nPermutations));
await Provable.runAndCheck(() => main(nPermutations));
toc();
2 changes: 1 addition & 1 deletion src/examples/benchmarks/keccak-witness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Hash, Bytes, Provable } from 'o1js';
let Bytes32 = Bytes(32);

console.time('keccak witness');
Provable.runAndCheck(() => {
await Provable.runAndCheck(() => {
let bytes = Provable.witness(Bytes32.provable, () => Bytes32.random());
Hash.Keccak256.hash(bytes);
});
Expand Down
6 changes: 3 additions & 3 deletions src/examples/benchmarks/mul-web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ function main(nMuls: number) {
}
}

function getRows(nMuls: number) {
let { rows } = Provable.constraintSystem(() => main(nMuls));
async function getRows(nMuls: number) {
let { rows } = await Provable.constraintSystem(() => main(nMuls));
return rows;
}

Expand Down Expand Up @@ -52,7 +52,7 @@ function picklesCircuit(nMuls: number) {

// the script

console.log('circuit size (without pickles overhead)', getRows(nMuls));
console.log('circuit size (without pickles overhead)', await getRows(nMuls));

if (withPickles) {
let circuit = picklesCircuit(nMuls);
Expand Down
2 changes: 1 addition & 1 deletion src/examples/benchmarks/mul-witness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ function main(nMuls: number) {
}

tic('run and check');
Provable.runAndCheck(() => main(nMuls));
await Provable.runAndCheck(() => main(nMuls));
toc();
6 changes: 3 additions & 3 deletions src/examples/benchmarks/mul.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ function main(nMuls: number) {
}
}

function getRows(nMuls: number) {
let { rows } = Provable.constraintSystem(() => main(nMuls));
async function getRows(nMuls: number) {
let { rows } = await Provable.constraintSystem(() => main(nMuls));
return rows;
}

Expand Down Expand Up @@ -48,7 +48,7 @@ function picklesCircuit(nMuls: number) {
});
}

console.log('circuit size (without pickles overhead)', getRows(nMuls));
console.log('circuit size (without pickles overhead)', await getRows(nMuls));

if (withPickles) {
let circuit = picklesCircuit(nMuls);
Expand Down
16 changes: 9 additions & 7 deletions src/examples/constraint-system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { Field, Poseidon, Provable } from 'o1js';

let hash = Poseidon.hash([Field(1), Field(-1)]);

let { rows, digest, publicInputSize, print } = Provable.constraintSystem(() => {
let x = Provable.witness(Field, () => Field(1));
let y = Provable.witness(Field, () => Field(-1));
x.add(y).assertEquals(Field(0));
let z = Poseidon.hash([x, y]);
z.assertEquals(hash);
});
let { rows, digest, publicInputSize, print } = await Provable.constraintSystem(
() => {
let x = Provable.witness(Field, () => Field(1));
let y = Provable.witness(Field, () => Field(-1));
x.add(y).assertEquals(Field(0));
let z = Poseidon.hash([x, y]);
z.assertEquals(hash);
}
);

print();
console.log({ rows, digest, publicInputSize });
4 changes: 2 additions & 2 deletions src/examples/crypto/ecdsa/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ let signature = Ecdsa.sign(message.toBytes(), privateKey.toBigInt());
// investigate the constraint system generated by ECDSA verify

console.time('ecdsa verify only (build constraint system)');
let csEcdsa = ecdsa.analyzeMethods();
let csEcdsa = await ecdsa.analyzeMethods();
console.timeEnd('ecdsa verify only (build constraint system)');
console.log(csEcdsa.verifySignedHash.summary());

console.time('keccak + ecdsa verify (build constraint system)');
let cs = keccakAndEcdsa.analyzeMethods();
let cs = await keccakAndEcdsa.analyzeMethods();
console.timeEnd('keccak + ecdsa verify (build constraint system)');
console.log(cs.verifyEcdsa.summary());

Expand Down
2 changes: 1 addition & 1 deletion src/examples/crypto/foreign-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class MyContract extends SmartContract {
this.x.set(x.assertAlmostReduced());
}
}
MyContract.analyzeMethods(); // works
await MyContract.analyzeMethods(); // works

// btw - we support any finite field up to 259 bits. for example, the seqp256k1 base field:
let Fseqp256k1 = createForeignField((1n << 256n) - (1n << 32n) - 0b1111010001n);
Expand Down
2 changes: 1 addition & 1 deletion src/examples/crypto/sha256/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ console.timeEnd('compile');

let preimage = Bytes12.fromString('hello world!');

console.log('sha256 rows:', SHA256Program.analyzeMethods().sha256.rows);
console.log('sha256 rows:', (await SHA256Program.analyzeMethods()).sha256.rows);

console.time('prove');
let proof = await SHA256Program.sha256(preimage);
Expand Down
4 changes: 2 additions & 2 deletions src/examples/encryption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ console.log(`Recovered message: "${decryptedMessage}"`);

// the same but in a checked computation

Provable.runAndCheck(() => {
await Provable.runAndCheck(() => {
// encrypt
let cipherText = Encryption.encrypt(messageFields, publicKey);

Expand Down Expand Up @@ -76,7 +76,7 @@ console.log(`Recovered message: "${decryptedMessage}"`);

// the same but in a checked computation

Provable.runAndCheck(() => {
await Provable.runAndCheck(() => {
// encrypt
let cipherText = Encryption.encrypt(messageFields, publicKey);

Expand Down
8 changes: 4 additions & 4 deletions src/examples/internals/advanced-provable-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ expect(accountUpdateRecovered.lazyAuthorization).not.toEqual(
* -) witness() and asProver() blocks are executed
* -) constraints are checked; failing assertions throw an error
*/
Provable.runAndCheck(() => {
await Provable.runAndCheck(() => {
/**
* Provable.witness() is used to introduce all values to the circuit which are not hard-coded constants.
*
Expand Down Expand Up @@ -99,7 +99,7 @@ Provable.runAndCheck(() => {
* -) fields don't have actual values attached to them; they're purely abstract variables
* -) constraints are not checked
*/
let result = Provable.constraintSystem(() => {
let result = await Provable.constraintSystem(() => {
/**
* In compile mode, witness() returns
* - abstract variables without values for fields
Expand Down Expand Up @@ -140,7 +140,7 @@ console.log(
*
* This is why we have this custom way of witnessing account updates, with the `skipCheck` option.
*/
result = Provable.constraintSystem(() => {
result = await Provable.constraintSystem(() => {
let { accountUpdate: accountUpdateWitness } = AccountUpdate.witness(
Empty,
() => ({ accountUpdate, result: undefined }),
Expand All @@ -156,7 +156,7 @@ console.log(
* To relate an account update to the hash which is the public input, we need to perform the hash in-circuit.
* This is takes several 100 constraints, and is basically the minimal size of a zkApp method.
*/
result = Provable.constraintSystem(() => {
result = await Provable.constraintSystem(() => {
let { accountUpdate: accountUpdateWitness } = AccountUpdate.witness(
Empty,
() => ({ accountUpdate, result: undefined }),
Expand Down
4 changes: 2 additions & 2 deletions src/examples/matrix-mul.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ function circuit(): Field[][] {
return matrixMul(x, y);
}

let { rows } = Provable.constraintSystem(circuit);
let { rows } = await Provable.constraintSystem(circuit);
let result: Field[][];
Provable.runAndCheck(() => {
await Provable.runAndCheck(() => {
let result_ = circuit();
Provable.asProver(() => {
result = result_.map((x) => x.map((y) => y.toConstant()));
Expand Down
2 changes: 1 addition & 1 deletion src/examples/simple-zkapp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ if (doProofs) {
await SimpleZkapp.compile();
console.timeEnd('compile');
} else {
SimpleZkapp.analyzeMethods();
await SimpleZkapp.analyzeMethods();
}

console.log('deploy');
Expand Down
6 changes: 3 additions & 3 deletions src/examples/zkapps/dex/happy-path-with-proofs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ let tx, balances, oldBalances;

let { Dex, DexTokenHolder, getTokenBalances } = createDex();

TokenContract.analyzeMethods();
DexTokenHolder.analyzeMethods();
Dex.analyzeMethods();
await TokenContract.analyzeMethods();
await DexTokenHolder.analyzeMethods();
await Dex.analyzeMethods();

if (proofsEnabled) {
tic('compile (token)');
Expand Down
6 changes: 3 additions & 3 deletions src/examples/zkapps/dex/run-live.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ if (!useCustomLocalNetwork) {
await ensureFundedAccount(senderKey.toBase58());
}

TokenContract.analyzeMethods();
DexTokenHolder.analyzeMethods();
Dex.analyzeMethods();
await TokenContract.analyzeMethods();
await DexTokenHolder.analyzeMethods();
await Dex.analyzeMethods();

tic('compile (token)');
await TokenContract.compile();
Expand Down
6 changes: 3 additions & 3 deletions src/examples/zkapps/dex/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ console.log('TOKEN X ID\t', TokenId.toBase58(tokenIds.X));
console.log('TOKEN Y ID\t', TokenId.toBase58(tokenIds.Y));
console.log('-------------------------------------------------');

TokenContract.analyzeMethods();
await TokenContract.analyzeMethods();
if (proofsEnabled) {
console.log('compile (token)...');
await TokenContract.compile();
Expand Down Expand Up @@ -57,8 +57,8 @@ async function main({ withVesting }: { withVesting: boolean }) {
let { Dex, DexTokenHolder, getTokenBalances } = createDex(options);

// analyze methods for quick error feedback
DexTokenHolder.analyzeMethods();
Dex.analyzeMethods();
await DexTokenHolder.analyzeMethods();
await Dex.analyzeMethods();

if (proofsEnabled) {
// compile & deploy all zkApps
Expand Down
8 changes: 4 additions & 4 deletions src/examples/zkapps/dex/upgradability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ async function atomicActionsTest({ withVesting }: { withVesting: boolean }) {
let { Dex, DexTokenHolder, getTokenBalances } = createDex(options);

// analyze methods for quick error feedback
DexTokenHolder.analyzeMethods();
Dex.analyzeMethods();
await DexTokenHolder.analyzeMethods();
await Dex.analyzeMethods();

if (proofsEnabled) {
// compile & deploy all zkApps
Expand Down Expand Up @@ -249,8 +249,8 @@ async function upgradeabilityTests({ withVesting }: { withVesting: boolean }) {
} = createDex(options);

// analyze methods for quick error feedback
DexTokenHolder.analyzeMethods();
Dex.analyzeMethods();
await DexTokenHolder.analyzeMethods();
await Dex.analyzeMethods();

// compile & deploy all zkApps
console.log('compile (token contract)...');
Expand Down
2 changes: 1 addition & 1 deletion src/examples/zkapps/reducer/actions-as-merkle-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ let zkapp = new ActionsContract(zkappAddress);
await ActionsContract.compile();
console.log(
`rows for ${MAX_UPDATES_WITH_ACTIONS} updates with actions`,
ActionsContract.analyzeMethods().assertContainsAddress.rows
(await ActionsContract.analyzeMethods()).assertContainsAddress.rows
);
let deployTx = await Mina.transaction(sender, () => zkapp.deploy());
await deployTx.sign([senderKey, zkappKey]).send();
Expand Down
2 changes: 1 addition & 1 deletion src/examples/zkapps/reducer/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ let k = 1 << 4;

let Local = Mina.LocalBlockchain();
Mina.setActiveInstance(Local);
let cs = StorageContract.analyzeMethods();
let cs = await StorageContract.analyzeMethods();

console.log(`method size for a "mapping" contract with ${k} entries`);
console.log('get rows:', cs['get'].rows);
Expand Down
3 changes: 0 additions & 3 deletions src/examples/zkapps/reducer/reducer-composite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
SmartContract,
Mina,
AccountUpdate,
isReady,
Bool,
Struct,
Reducer,
Expand All @@ -16,8 +15,6 @@ import {
import assert from 'node:assert/strict';
import { getProfiler } from '../../utils/profiler.js';

await isReady;

class MaybeIncrement extends Struct({
isIncrement: Bool,
otherData: Field,
Expand Down
2 changes: 1 addition & 1 deletion src/examples/zkapps/reducer/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ if (doProofs) {
// TODO: if we don't do this, then `analyzeMethods()` will be called during `runUnchecked()` in the tx callback below,
// which currently fails due to `finalize_is_running` in snarky not resetting internal state, and instead setting is_running unconditionally to false,
// so we can't nest different snarky circuit runners
CounterZkapp.analyzeMethods();
await CounterZkapp.analyzeMethods();
}

console.log('deploy');
Expand Down
2 changes: 1 addition & 1 deletion src/examples/zkapps/sudoku/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const zkAppAddress = zkAppPrivateKey.toPublicKey();
// create an instance of the smart contract
const zkApp = new SudokuZkApp(zkAppAddress);

let methods = SudokuZkApp.analyzeMethods();
let methods = await SudokuZkApp.analyzeMethods();
console.log(
'first 5 gates of submitSolution method:',
...methods.submitSolution.gates.slice(0, 5)
Expand Down
2 changes: 1 addition & 1 deletion src/examples/zkprogram/gadgets.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Field, Provable, Gadgets, ZkProgram } from 'o1js';

let cs = Provable.constraintSystem(() => {
let cs = await Provable.constraintSystem(() => {
let f = Provable.witness(Field, () => Field(12));

let res1 = Gadgets.rotate64(f, 2, 'left');
Expand Down
16 changes: 7 additions & 9 deletions src/lib/account-update.unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,15 @@ function createAccountUpdate() {
let accountUpdate = createAccountUpdate();

// TODO remove restriction "This function can't be run outside of a checked computation."
Provable.runAndCheck(() => {
let hash = accountUpdate.hash();
let hash = accountUpdate.hash();

// if we clone the accountUpdate, hash should be the same
let accountUpdate2 = AccountUpdate.clone(accountUpdate);
expect(accountUpdate2.hash()).toEqual(hash);
// if we clone the accountUpdate, hash should be the same
let accountUpdate2 = AccountUpdate.clone(accountUpdate);
expect(accountUpdate2.hash()).toEqual(hash);

// if we change something on the cloned accountUpdate, the hash should become different
AccountUpdate.setValue(accountUpdate2.update.appState[0], Field(1));
expect(accountUpdate2.hash()).not.toEqual(hash);
});
// if we change something on the cloned accountUpdate, the hash should become different
AccountUpdate.setValue(accountUpdate2.update.appState[0], Field(1));
expect(accountUpdate2.hash()).not.toEqual(hash);
}

// converts account update to a public input that's consistent with the ocaml implementation
Expand Down
6 changes: 3 additions & 3 deletions src/lib/circuit-value.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('circuit', () => {
});

it('Provable.if in snark', () => {
Provable.runAndCheck(() => {
Provable.runAndCheckSync(() => {
let x = Provable.witness(Int64, () => Int64.from(-1));
let y = Provable.witness(Int64, () => Int64.from(-2));
let b = Provable.witness(Bool, () => Bool(true));
Expand Down Expand Up @@ -81,7 +81,7 @@ describe('circuit', () => {
it('Provable.assertEqual', () => {
const FieldAndBool = Struct({ x: Field, b: Bool });

Provable.runAndCheck(() => {
Provable.runAndCheckSync(() => {
let x = Provable.witness(Field, () => Field(1));
let b = Provable.witness(Bool, () => Bool(true));

Expand Down Expand Up @@ -123,7 +123,7 @@ describe('circuit', () => {
});
}

Provable.runAndCheck(() => {
Provable.runAndCheckSync(() => {
let x = Provable.witness(Field, () => Field(1));
let b = Provable.witness(Bool, () => Bool(true));
let pk = Provable.witness(PublicKey, () => pk1);
Expand Down
Loading
Loading