From 240292f2e6523fe214fbb401321235c5d1a05774 Mon Sep 17 00:00:00 2001 From: Gregor Date: Wed, 28 Feb 2024 16:19:17 +0100 Subject: [PATCH 01/10] expose snarky's internal state --- src/bindings | 2 +- src/snarky.d.ts | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index 2df95c622d..f9a994b1f3 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit 2df95c622df71f0696491179aa7db8b7c07e9883 +Subproject commit f9a994b1f36ef42dbefaf189f6708bc54e6669d8 diff --git a/src/snarky.d.ts b/src/snarky.d.ts index 2c10d27f8d..c1f091965b 100644 --- a/src/snarky.d.ts +++ b/src/snarky.d.ts @@ -217,6 +217,21 @@ declare const Snarky: { public_inputs: FieldVector, auxiliary_inputs: FieldVector ]; + + /** + * Snarky's internal state + */ + state: { + state: MlRef; + + allocVar(state: SnarkyState): FieldVar; + storeFieldElt(state: SnarkyState, x: FieldConst): FieldVar; + getVariableValue(state: SnarkyState, x: FieldVar): FieldConst; + + asProver(state: SnarkyState): MlBool; + setAsProver(state: SnarkyState, value: MlBool): void; + hasWitness(state: SnarkyState): MlBool; + }; }; /** @@ -562,6 +577,27 @@ declare const Snarky: { }; }; +type MlRef = [_: 0, contents: T]; + +type SnarkyVector = [0, [unknown, number, FieldVector]]; +type ConstraintSystem = unknown; + +type SnarkyState = [ + _: 0, + system: MlOption, + input: SnarkyVector, + aux: SnarkyVector, + eval_constraints: MlBool, + num_inputs: number, + next_auxiliary: MlRef, + has_witness: MlBool, + stack: MlList, + handler: unknown, + is_running: MlBool, + as_prover: MlRef, + log_constraint: unknown +]; + type GateType = | 'Zero' | 'Generic' From 6a8de03aebc774c1f9a1ac553961414abfe3ab30 Mon Sep 17 00:00:00 2001 From: Gregor Date: Wed, 28 Feb 2024 16:27:43 +0100 Subject: [PATCH 02/10] start writing async exists --- src/lib/provable-witness.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/lib/provable-witness.ts diff --git a/src/lib/provable-witness.ts b/src/lib/provable-witness.ts new file mode 100644 index 0000000000..5aa25803ea --- /dev/null +++ b/src/lib/provable-witness.ts @@ -0,0 +1,17 @@ +import { Snarky } from '../snarky.js'; +import type { FieldVar } from './field.js'; + +const SnarkyState = Snarky.run.state; + +async function existsAsync( + size: number, + compute: () => Promise +): Promise { + let state = SnarkyState.state[1]; + + if (SnarkyState.hasWitness(state)) { + // TODO + } else { + return Array.from({ length: size }, () => SnarkyState.allocVar(state)); + } +} From b98d4648c753949fcf94ed18ca03960629eaf1b6 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 29 Feb 2024 08:34:57 +0100 Subject: [PATCH 03/10] finish async exists --- src/lib/provable-core/exists.ts | 39 +++++++++++++++++++++++++++++++++ src/lib/provable-witness.ts | 17 -------------- 2 files changed, 39 insertions(+), 17 deletions(-) create mode 100644 src/lib/provable-core/exists.ts delete mode 100644 src/lib/provable-witness.ts diff --git a/src/lib/provable-core/exists.ts b/src/lib/provable-core/exists.ts new file mode 100644 index 0000000000..e5540b5a1d --- /dev/null +++ b/src/lib/provable-core/exists.ts @@ -0,0 +1,39 @@ +import { Snarky } from '../../snarky.js'; +import { FieldConst, FieldVar } from '../field.js'; +import { MlBool } from '../ml/base.js'; + +const SnarkyState = Snarky.run.state; + +async function existsAsync( + size: number, + compute: (() => Promise) | (() => bigint[]) +): Promise { + let state = SnarkyState.state[1]; + + if (SnarkyState.hasWitness(state)) { + let oldAsProver = SnarkyState.asProver(state); + SnarkyState.setAsProver(state, MlBool(true)); + + try { + // run the async callback to get values to witness + let values = await compute(); + if (values.length !== size) + throw Error( + `Expected witnessed values of length ${size}, got ${values.length}.` + ); + + // if we're nested in a prover block, return constants instead of storing + if (oldAsProver) return values.map(FieldVar.constant); + + // store the values as witnesses and return them + return values.map((x) => + SnarkyState.storeFieldElt(state, FieldConst.fromBigint(x)) + ); + } finally { + SnarkyState.setAsProver(state, oldAsProver); + } + } else { + // if we're in compile mode (no witness), just allocate "empty" variables + return Array.from({ length: size }, () => SnarkyState.allocVar(state)); + } +} diff --git a/src/lib/provable-witness.ts b/src/lib/provable-witness.ts deleted file mode 100644 index 5aa25803ea..0000000000 --- a/src/lib/provable-witness.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Snarky } from '../snarky.js'; -import type { FieldVar } from './field.js'; - -const SnarkyState = Snarky.run.state; - -async function existsAsync( - size: number, - compute: () => Promise -): Promise { - let state = SnarkyState.state[1]; - - if (SnarkyState.hasWitness(state)) { - // TODO - } else { - return Array.from({ length: size }, () => SnarkyState.allocVar(state)); - } -} From af54ce9914c5953aceda7a257ee4bacb1603b3e2 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 29 Feb 2024 09:19:48 +0100 Subject: [PATCH 04/10] async witness --- src/lib/provable-core/exists.ts | 2 ++ src/lib/provable.ts | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/lib/provable-core/exists.ts b/src/lib/provable-core/exists.ts index e5540b5a1d..082fa59684 100644 --- a/src/lib/provable-core/exists.ts +++ b/src/lib/provable-core/exists.ts @@ -2,6 +2,8 @@ import { Snarky } from '../../snarky.js'; import { FieldConst, FieldVar } from '../field.js'; import { MlBool } from '../ml/base.js'; +export { existsAsync }; + const SnarkyState = Snarky.run.state; async function existsAsync( diff --git a/src/lib/provable.ts b/src/lib/provable.ts index aafc841875..f2b918ff7f 100644 --- a/src/lib/provable.ts +++ b/src/lib/provable.ts @@ -22,6 +22,7 @@ import { generateWitness, runAndCheckSync, } from './provable-context.js'; +import { existsAsync } from './provable-core/exists.js'; // external API export { Provable }; @@ -61,6 +62,12 @@ const Provable = { * ``` */ witness, + /** + * Create a new witness from an async callback. + * + * See {@link Provable.witness} for more information. + */ + witnessAsync, /** * Proof-compatible if-statement. * This behaves like a ternary conditional statement in JS. @@ -262,6 +269,43 @@ function witness = FlexibleProvable>( return value; } +async function witnessAsync< + T, + S extends FlexibleProvable = FlexibleProvable +>(type: S, compute: () => Promise): Promise { + let ctx = snarkContext.get(); + + // outside provable code, we just call the callback and return its cloned result + if (!inCheckedComputation() || ctx.inWitnessBlock) { + let value: T = await compute(); + return clone(type, value); + } + let proverValue: T | undefined = undefined; + let fields: Field[]; + + // call into `existsAsync` to witness the raw field elements + let id = snarkContext.enter({ ...ctx, inWitnessBlock: true }); + try { + let fieldVars = await existsAsync(type.sizeInFields(), async () => { + proverValue = await compute(); + let fields = type.toFields(proverValue); + return fields.map((x) => x.toBigInt()); + }); + fields = fieldVars.map(Field); + } finally { + snarkContext.leave(id); + } + + // rebuild the value from its fields (which are now variables) and aux data + let aux = type.toAuxiliary(proverValue); + let value = (type as Provable).fromFields(fields, aux); + + // add type-specific constraints + type.check(value); + + return value; +} + type ToFieldable = { toFields(): Field[] }; // general provable methods From 7f24562a62a6b028eee8a1e3b4a789e15287e71f Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 29 Feb 2024 09:40:38 +0100 Subject: [PATCH 05/10] async transaction callback --- src/lib/account-update.unit-test.ts | 4 +- src/lib/caller.unit-test.ts | 2 +- src/lib/circuit-value.unit-test.ts | 4 +- src/lib/mina.ts | 6 +-- .../mina/account-update-layout.unit-test.ts | 8 ++-- src/lib/mina/local-blockchain.ts | 2 +- src/lib/mina/mina-instance.ts | 2 +- .../mina/token/token-contract.unit-test.ts | 10 ++-- src/lib/mina/transaction.ts | 32 +++++++------ src/lib/precondition.test.ts | 48 +++++++++---------- src/lib/token.test.ts | 46 +++++++++--------- 11 files changed, 85 insertions(+), 79 deletions(-) diff --git a/src/lib/account-update.unit-test.ts b/src/lib/account-update.unit-test.ts index 6c32d16382..9ab981d241 100644 --- a/src/lib/account-update.unit-test.ts +++ b/src/lib/account-update.unit-test.ts @@ -75,7 +75,7 @@ function createAccountUpdate() { }); // create transaction JSON with the same accountUpdate structure, for ocaml version - let tx = await Mina.transaction(() => { + let tx = await Mina.transaction(async () => { let accountUpdate = AccountUpdate.create(address); accountUpdate.approve(AccountUpdate.create(otherAddress)); }); @@ -112,7 +112,7 @@ function createAccountUpdate() { const feePayer = Local.testAccounts[0].publicKey; - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); }); tx.sign(); diff --git a/src/lib/caller.unit-test.ts b/src/lib/caller.unit-test.ts index 01eef352d3..173ebffc07 100644 --- a/src/lib/caller.unit-test.ts +++ b/src/lib/caller.unit-test.ts @@ -14,7 +14,7 @@ let parentId = TokenId.derive(publicKey); * * InheritFromParent -> ParentsOwnToken */ -let tx = await Mina.transaction(privateKey, () => { +let tx = await Mina.transaction(privateKey, async () => { let parent = AccountUpdate.defaultAccountUpdate(publicKey); parent.body.mayUseToken = AccountUpdate.MayUseToken.InheritFromParent; parent.balance.subInPlace(Mina.getNetworkConstants().accountCreationFee); diff --git a/src/lib/circuit-value.unit-test.ts b/src/lib/circuit-value.unit-test.ts index f084c9ffee..206762fd91 100644 --- a/src/lib/circuit-value.unit-test.ts +++ b/src/lib/circuit-value.unit-test.ts @@ -145,10 +145,10 @@ let key = PrivateKey.random(); let address = key.toPublicKey(); let contract = new MyContract(address); -let tx = await transaction(() => { +let tx = await transaction(async () => { let accountUpdate = AccountUpdate.createSigned(key); - contract.myMethod( + await contract.myMethod( { nested: { a: 1, b: false }, other: targetString, diff --git a/src/lib/mina.ts b/src/lib/mina.ts index 68866198e7..bd270a7e19 100644 --- a/src/lib/mina.ts +++ b/src/lib/mina.ts @@ -1,6 +1,6 @@ import { Test } from '../snarky.js'; import { Field } from './core.js'; -import { UInt32, UInt64 } from './int.js'; +import { UInt64 } from './int.js'; import { PublicKey } from './signature.js'; import { ZkappCommand, TokenId, Authorization } from './account-update.js'; import * as Fetch from './fetch.js'; @@ -87,7 +87,7 @@ export { // patch active instance so that we can still create basic transactions without giving Mina network details setActiveInstance({ ...activeInstance, - async transaction(sender: DeprecatedFeePayerSpec, f: () => void) { + async transaction(sender: DeprecatedFeePayerSpec, f: () => Promise) { return await createTransaction(sender, f, 0); }, }); @@ -374,7 +374,7 @@ function Network( waitOrThrowIfError, }; }, - async transaction(sender: DeprecatedFeePayerSpec, f: () => void) { + async transaction(sender: DeprecatedFeePayerSpec, f: () => Promise) { // TODO we run the transcation twice to be able to fetch data in between let tx = await createTransaction(sender, f, 0, { fetchMode: 'test', diff --git a/src/lib/mina/account-update-layout.unit-test.ts b/src/lib/mina/account-update-layout.unit-test.ts index 4adaeca841..ee82774383 100644 --- a/src/lib/mina/account-update-layout.unit-test.ts +++ b/src/lib/mina/account-update-layout.unit-test.ts @@ -37,7 +37,7 @@ let zkapp = new NestedCall(zkappAddress); // deploy zkapp -await (await Mina.transaction(sender, () => zkapp.deploy())) +await (await Mina.transaction(sender, async () => zkapp.deploy())) .sign([zkappKey, senderKey]) .send(); @@ -45,7 +45,7 @@ await (await Mina.transaction(sender, () => zkapp.deploy())) let balanceBefore = Mina.getBalance(zkappAddress); -let depositTx = await Mina.transaction(sender, () => zkapp.deposit()); +let depositTx = await Mina.transaction(sender, async () => zkapp.deposit()); console.log(depositTx.toPretty()); await depositTx.prove(); await depositTx.sign([senderKey]).send(); @@ -56,7 +56,9 @@ Mina.getBalance(zkappAddress).assertEquals(balanceBefore.add(1)); balanceBefore = balanceBefore.add(1); -depositTx = await Mina.transaction(sender, () => zkapp.depositUsingTree()); +depositTx = await Mina.transaction(sender, async () => + zkapp.depositUsingTree() +); console.log(depositTx.toPretty()); await depositTx.prove(); await depositTx.sign([senderKey]).send(); diff --git a/src/lib/mina/local-blockchain.ts b/src/lib/mina/local-blockchain.ts index c12f96b831..0204b679c5 100644 --- a/src/lib/mina/local-blockchain.ts +++ b/src/lib/mina/local-blockchain.ts @@ -300,7 +300,7 @@ function LocalBlockchain({ waitOrThrowIfError, }; }, - async transaction(sender: DeprecatedFeePayerSpec, f: () => void) { + async transaction(sender: DeprecatedFeePayerSpec, f: () => Promise) { // TODO we run the transaction twice to match the behaviour of `Network.transaction` let tx = await createTransaction(sender, f, 0, { isFinalRunOutsideCircuit: false, diff --git a/src/lib/mina/mina-instance.ts b/src/lib/mina/mina-instance.ts index 324dfefaeb..db7e4eb46d 100644 --- a/src/lib/mina/mina-instance.ts +++ b/src/lib/mina/mina-instance.ts @@ -93,7 +93,7 @@ type NetworkConstants = { interface Mina { transaction( sender: DeprecatedFeePayerSpec, - f: () => void + f: () => Promise ): Promise; currentSlot(): UInt32; hasAccount(publicKey: PublicKey, tokenId?: Field): boolean; diff --git a/src/lib/mina/token/token-contract.unit-test.ts b/src/lib/mina/token/token-contract.unit-test.ts index 3301f9380a..88cd92e10d 100644 --- a/src/lib/mina/token/token-contract.unit-test.ts +++ b/src/lib/mina/token/token-contract.unit-test.ts @@ -46,7 +46,7 @@ let token = new ExampleTokenContract(tokenAddress); let tokenId = token.deriveTokenId(); // deploy token contract -let deployTx = await Mina.transaction(sender, () => { +let deployTx = await Mina.transaction(sender, async () => { AccountUpdate.fundNewAccount(sender, 2); token.deploy(); }); @@ -59,7 +59,7 @@ assert( ); // can transfer tokens between two accounts -let transferTx = await Mina.transaction(sender, () => { +let transferTx = await Mina.transaction(sender, async () => { AccountUpdate.fundNewAccount(sender); token.transfer(tokenAddress, otherAddress, UInt64.one); }); @@ -84,7 +84,7 @@ update3.body.callDepth = 2; let forest = AccountUpdateForest.fromFlatArray([update1, update2, update3]); await assert.rejects( - () => Mina.transaction(sender, () => token.approveBase(forest)), + () => Mina.transaction(sender, async () => token.approveBase(forest)), /Field\.assertEquals\(\): 1 != 0/ ); @@ -101,6 +101,8 @@ forest = AccountUpdateForest.fromFlatArray([ update4, ]); -let approveTx = await Mina.transaction(sender, () => token.approveBase(forest)); +let approveTx = await Mina.transaction(sender, async () => + token.approveBase(forest) +); await approveTx.prove(); await approveTx.sign([senderKey, otherKey]).send(); diff --git a/src/lib/mina/transaction.ts b/src/lib/mina/transaction.ts index 8d62efb624..ef0646db3b 100644 --- a/src/lib/mina/transaction.ts +++ b/src/lib/mina/transaction.ts @@ -265,7 +265,7 @@ type RejectedTransaction = Pick< async function createTransaction( feePayer: DeprecatedFeePayerSpec, - f: () => unknown, + f: () => Promise, numberOfRuns: 0 | 1 | undefined, { fetchMode = 'cached' as FetchMode, @@ -307,16 +307,15 @@ async function createTransaction( // run circuit try { if (fetchMode === 'test') { - await Provable.runUnchecked(() => { - f(); + await Provable.runUnchecked(async () => { + await f(); Provable.asProver(() => { let tx = currentTransaction.get(); tx.layout.toConstantInPlace(); }); }); } else { - // TODO support async - f(); + await f(); } } catch (err) { currentTransaction.leave(transactionId); @@ -419,16 +418,19 @@ function newTransaction(transaction: ZkappCommand, proofsEnabled?: boolean) { * you can call into the methods of smart contracts. * * ``` - * let tx = await Mina.transaction(sender, () => { - * myZkapp.update(); - * someOtherZkapp.someOtherMethod(); + * let tx = await Mina.transaction(sender, async () => { + * await myZkapp.update(); + * await someOtherZkapp.someOtherMethod(); * }); * ``` * * @return A transaction that can subsequently be submitted to the chain. */ -function transaction(sender: FeePayerSpec, f: () => void): Promise; -function transaction(f: () => void): Promise; +function transaction( + sender: FeePayerSpec, + f: () => Promise +): Promise; +function transaction(f: () => Promise): Promise; /** * @deprecated It's deprecated to pass in the fee payer's private key. Pass in the public key instead. * ``` @@ -443,21 +445,21 @@ function transaction(f: () => void): Promise; */ function transaction( sender: DeprecatedFeePayerSpec, - f: () => void + f: () => Promise ): Promise; function transaction( - senderOrF: DeprecatedFeePayerSpec | (() => void), - fOrUndefined?: () => void + senderOrF: DeprecatedFeePayerSpec | (() => Promise), + fOrUndefined?: () => Promise ): Promise { let sender: DeprecatedFeePayerSpec; - let f: () => void; + let f: () => Promise; try { if (fOrUndefined !== undefined) { sender = senderOrF as DeprecatedFeePayerSpec; f = fOrUndefined; } else { sender = undefined; - f = senderOrF as () => void; + f = senderOrF as () => Promise; } return activeInstance.transaction(sender, f); } catch (error) { diff --git a/src/lib/precondition.test.ts b/src/lib/precondition.test.ts index 1228a2ec1f..365d9c0816 100644 --- a/src/lib/precondition.test.ts +++ b/src/lib/precondition.test.ts @@ -37,7 +37,7 @@ beforeAll(async () => { zkappAddress = zkappKey.toPublicKey(); zkapp = new MyContract(zkappAddress); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); zkapp.deploy(); }); @@ -49,7 +49,7 @@ describe('preconditions', () => { it('get without constraint should throw', async () => { for (let precondition of implemented) { await expect( - Mina.transaction(feePayer, () => { + Mina.transaction(feePayer, async () => { precondition().get(); AccountUpdate.attachToTransaction(zkapp.self); }) @@ -63,7 +63,7 @@ describe('preconditions', () => { it('get + assertEquals should not throw', async () => { let nonce = zkapp.account.nonce.get(); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { zkapp.requireSignature(); for (let precondition of implemented) { let p = precondition().get(); @@ -78,7 +78,7 @@ describe('preconditions', () => { it('get + requireEquals should not throw', async () => { let nonce = zkapp.account.nonce.get(); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { zkapp.requireSignature(); for (let precondition of implemented) { let p = precondition().get(); @@ -94,7 +94,7 @@ describe('preconditions', () => { it('get + assertEquals should throw for unimplemented fields', async () => { for (let precondition of unimplemented) { await expect( - Mina.transaction(feePayer, () => { + Mina.transaction(feePayer, async () => { let p = precondition(); p.assertEquals(p.get() as any); AccountUpdate.attachToTransaction(zkapp.self); @@ -106,7 +106,7 @@ describe('preconditions', () => { it('get + requireEquals should throw for unimplemented fields', async () => { for (let precondition of unimplemented) { await expect( - Mina.transaction(feePayer, () => { + Mina.transaction(feePayer, async () => { let p = precondition(); p.requireEquals(p.get() as any); AccountUpdate.attachToTransaction(zkapp.self); @@ -117,7 +117,7 @@ describe('preconditions', () => { it('get + assertBetween should not throw', async () => { let nonce = zkapp.account.nonce.get(); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { for (let precondition of implementedWithRange) { let p: any = precondition().get(); precondition().assertBetween(p.constructor.zero, p); @@ -132,7 +132,7 @@ describe('preconditions', () => { it('get + requireBetween should not throw', async () => { let nonce = zkapp.account.nonce.get(); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { for (let precondition of implementedWithRange) { let p: any = precondition().get(); precondition().requireBetween(p.constructor.zero, p); @@ -147,7 +147,7 @@ describe('preconditions', () => { it('satisfied currentSlot.assertBetween should not throw', async () => { let nonce = zkapp.account.nonce.get(); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { zkapp.currentSlot.assertBetween( UInt32.from(0), UInt32.from(UInt32.MAXINT()) @@ -161,7 +161,7 @@ describe('preconditions', () => { it('satisfied currentSlot.requireBetween should not throw', async () => { let nonce = zkapp.account.nonce.get(); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { zkapp.currentSlot.requireBetween( UInt32.from(0), UInt32.from(UInt32.MAXINT()) @@ -175,7 +175,7 @@ describe('preconditions', () => { it('get + assertNothing should not throw', async () => { let nonce = zkapp.account.nonce.get(); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { for (let precondition of implemented) { precondition().get(); precondition().assertNothing(); @@ -190,7 +190,7 @@ describe('preconditions', () => { it('get + requireNothing should not throw', async () => { let nonce = zkapp.account.nonce.get(); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { for (let precondition of implemented) { precondition().get(); precondition().requireNothing(); @@ -206,7 +206,7 @@ describe('preconditions', () => { it('get + manual precondition should not throw', async () => { // we only test this for a couple of preconditions let nonce = zkapp.account.nonce.get(); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { zkapp.account.balance.get(); zkapp.self.body.preconditions.account.balance.isSome = Bool(true); zkapp.self.body.preconditions.account.balance.value.upper = @@ -233,7 +233,7 @@ describe('preconditions', () => { it('unsatisfied assertEquals should be rejected (numbers)', async () => { for (let precondition of implementedNumber) { await expect(async () => { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { let p = precondition().get(); precondition().assertEquals(p.add(1) as any); AccountUpdate.attachToTransaction(zkapp.self); @@ -246,7 +246,7 @@ describe('preconditions', () => { it('unsatisfied requireEquals should be rejected (numbers)', async () => { for (let precondition of implementedNumber) { await expect(async () => { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { let p = precondition().get(); precondition().requireEquals(p.add(1) as any); AccountUpdate.attachToTransaction(zkapp.self); @@ -258,7 +258,7 @@ describe('preconditions', () => { it('unsatisfied assertEquals should be rejected (booleans)', async () => { for (let precondition of implementedBool) { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { let p = precondition().get(); precondition().assertEquals(p.not()); AccountUpdate.attachToTransaction(zkapp.self); @@ -271,7 +271,7 @@ describe('preconditions', () => { it('unsatisfied requireEquals should be rejected (booleans)', async () => { for (let precondition of implementedBool) { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { let p = precondition().get(); precondition().requireEquals(p.not()); AccountUpdate.attachToTransaction(zkapp.self); @@ -284,7 +284,7 @@ describe('preconditions', () => { it('unsatisfied assertEquals should be rejected (public key)', async () => { let publicKey = PublicKey.from({ x: Field(-1), isOdd: Bool(false) }); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { zkapp.account.delegate.assertEquals(publicKey); AccountUpdate.attachToTransaction(zkapp.self); }); @@ -295,7 +295,7 @@ describe('preconditions', () => { it('unsatisfied requireEquals should be rejected (public key)', async () => { let publicKey = PublicKey.from({ x: Field(-1), isOdd: Bool(false) }); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { zkapp.account.delegate.requireEquals(publicKey); AccountUpdate.attachToTransaction(zkapp.self); }); @@ -306,7 +306,7 @@ describe('preconditions', () => { it('unsatisfied assertBetween should be rejected', async () => { for (let precondition of implementedWithRange) { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { let p: any = precondition().get(); precondition().assertBetween(p.add(20), p.add(30)); AccountUpdate.attachToTransaction(zkapp.self); @@ -319,7 +319,7 @@ describe('preconditions', () => { it('unsatisfied requireBetween should be rejected', async () => { for (let precondition of implementedWithRange) { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { let p: any = precondition().get(); precondition().requireBetween(p.add(20), p.add(30)); AccountUpdate.attachToTransaction(zkapp.self); @@ -331,7 +331,7 @@ describe('preconditions', () => { }); it('unsatisfied currentSlot.assertBetween should be rejected', async () => { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { zkapp.currentSlot.assertBetween(UInt32.from(20), UInt32.from(30)); AccountUpdate.attachToTransaction(zkapp.self); }); @@ -341,7 +341,7 @@ describe('preconditions', () => { }); it('unsatisfied currentSlot.requireBetween should be rejected', async () => { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { zkapp.currentSlot.requireBetween(UInt32.from(20), UInt32.from(30)); AccountUpdate.attachToTransaction(zkapp.self); }); @@ -354,7 +354,7 @@ describe('preconditions', () => { // the test below fails, so it seems that nonce is applied successfully with a WRONG precondition.. // however, this is just because `zkapp.sign()` overwrites the nonce precondition with one that is satisfied it.skip('unsatisfied nonce precondition should be rejected', async () => { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { zkapp.account.nonce.assertEquals(UInt32.from(1e8)); zkapp.requireSignature(); AccountUpdate.attachToTransaction(zkapp.self); diff --git a/src/lib/token.test.ts b/src/lib/token.test.ts index aa5140b3ef..1b4122a235 100644 --- a/src/lib/token.test.ts +++ b/src/lib/token.test.ts @@ -162,7 +162,7 @@ function setupAccounts() { async function setupLocal() { setupAccounts(); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { let feePayerUpdate = AccountUpdate.fundNewAccount(feePayer); feePayerUpdate.send({ to: tokenZkappAddress, @@ -179,7 +179,7 @@ async function setupLocalProofs() { zkAppC = new ZkAppC(zkAppCAddress, tokenId); // don't use proofs for the setup, takes too long to do this every time Local.setProofsEnabled(false); - let tx = await Mina.transaction({ sender: feePayer }, () => { + let tx = await Mina.transaction({ sender: feePayer }, async () => { let feePayerUpdate = AccountUpdate.fundNewAccount(feePayer, 3); feePayerUpdate.send({ to: tokenZkappAddress, @@ -227,7 +227,7 @@ describe('Token', () => { test('setting a valid token symbol on a token contract', async () => { await ( - await Mina.transaction({ sender: feePayer }, () => { + await Mina.transaction({ sender: feePayer }, async () => { let tokenZkapp = AccountUpdate.createSigned(tokenZkappAddress); tokenZkapp.account.tokenSymbol.set(tokenSymbol); }) @@ -254,7 +254,7 @@ describe('Token', () => { test('token contract can successfully mint and updates the balances in the ledger (signature)', async () => { await ( - await Mina.transaction({ sender: feePayer }, () => { + await Mina.transaction({ sender: feePayer }, async () => { AccountUpdate.fundNewAccount(feePayer); tokenZkapp.mint(zkAppBAddress, UInt64.from(100_000)); tokenZkapp.requireSignature(); @@ -268,7 +268,7 @@ describe('Token', () => { }); test('minting should fail if overflow occurs ', async () => { - await Mina.transaction(feePayer, () => { + await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); tokenZkapp.mint(zkAppBAddress, UInt64.from(100_000_000_000)); tokenZkapp.requireSignature(); @@ -291,7 +291,7 @@ describe('Token', () => { }); test('token contract can successfully burn and updates the balances in the ledger (signature)', async () => { await ( - await Mina.transaction(feePayer, () => { + await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); tokenZkapp.mint(zkAppBAddress, UInt64.from(100_000)); tokenZkapp.requireSignature(); @@ -300,7 +300,7 @@ describe('Token', () => { .sign([feePayerKey, tokenZkappKey]) .send(); await ( - await Mina.transaction(feePayer, () => { + await Mina.transaction(feePayer, async () => { tokenZkapp.burn(zkAppBAddress, UInt64.from(10_000)); tokenZkapp.requireSignature(); }) @@ -314,7 +314,7 @@ describe('Token', () => { test('throw error if token owner burns more tokens than token account has', async () => { await ( - await Mina.transaction(feePayer, () => { + await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); tokenZkapp.mint(zkAppBAddress, UInt64.from(1_000)); tokenZkapp.requireSignature(); @@ -323,7 +323,7 @@ describe('Token', () => { .sign([feePayerKey, tokenZkappKey]) .send(); let tx = ( - await Mina.transaction(feePayer, () => { + await Mina.transaction(feePayer, async () => { tokenZkapp.burn(zkAppBAddress, UInt64.from(10_000)); tokenZkapp.requireSignature(); }) @@ -346,14 +346,14 @@ describe('Token', () => { }); test('change the balance of a token account after sending', async () => { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); tokenZkapp.mint(zkAppBAddress, UInt64.from(100_000)); tokenZkapp.requireSignature(); }); await tx.sign([feePayerKey, tokenZkappKey]).send(); - tx = await Mina.transaction(feePayer, () => { + tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); tokenZkapp.token.send({ from: zkAppBAddress, @@ -376,7 +376,7 @@ describe('Token', () => { test('should error creating a token account if no account creation fee is specified', async () => { await ( - await Mina.transaction(feePayer, () => { + await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); tokenZkapp.mint(zkAppBAddress, UInt64.from(100_000)); tokenZkapp.requireSignature(); @@ -385,7 +385,7 @@ describe('Token', () => { .sign([feePayerKey, tokenZkappKey]) .send(); let tx = ( - await Mina.transaction(feePayer, () => { + await Mina.transaction(feePayer, async () => { tokenZkapp.token.send({ from: zkAppBAddress, to: zkAppCAddress, @@ -401,7 +401,7 @@ describe('Token', () => { test('should error if sender sends more tokens than they have', async () => { await ( - await Mina.transaction(feePayer, () => { + await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); tokenZkapp.mint(zkAppBAddress, UInt64.from(100_000)); tokenZkapp.requireSignature(); @@ -410,7 +410,7 @@ describe('Token', () => { .sign([feePayerKey, tokenZkappKey]) .send(); let tx = ( - await Mina.transaction(feePayer, () => { + await Mina.transaction(feePayer, async () => { tokenZkapp.token.send({ from: zkAppBAddress, to: zkAppCAddress, @@ -464,7 +464,7 @@ describe('Token', () => { }); test('token contract can successfully mint and updates the balances in the ledger (proof)', async () => { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); tokenZkapp.mint(zkAppBAddress, UInt64.from(100_000)); }); @@ -489,13 +489,13 @@ describe('Token', () => { - burns and updates the token balance of the receiver */ test('token contract can successfully burn and updates the balances in the ledger (proof)', async () => { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); tokenZkapp.mint(zkAppBAddress, UInt64.from(100_000)); tokenZkapp.requireSignature(); }); await tx.sign([feePayerKey, tokenZkappKey]).send(); - tx = await Mina.transaction(feePayer, () => { + tx = await Mina.transaction(feePayer, async () => { tokenZkapp.burn(zkAppBAddress, UInt64.from(10_000)); }); await tx.prove(); @@ -521,14 +521,14 @@ describe('Token', () => { }); test('should approve and the balance of a token account after sending', async () => { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { tokenZkapp.mint(zkAppBAddress, UInt64.from(100_000)); tokenZkapp.requireSignature(); }); await tx.prove(); await tx.sign([feePayerKey, tokenZkappKey]).send(); - tx = await Mina.transaction(feePayer, () => { + tx = await Mina.transaction(feePayer, async () => { zkAppB.approveSend(UInt64.from(10_000)); tokenZkapp.approveTransfer( @@ -551,7 +551,7 @@ describe('Token', () => { test('should fail to approve with an incorrect layout', async () => { await ( - await Mina.transaction(feePayer, () => { + await Mina.transaction(feePayer, async () => { tokenZkapp.mint(zkAppCAddress, UInt64.from(100_000)); tokenZkapp.requireSignature(); }) @@ -560,7 +560,7 @@ describe('Token', () => { .send(); await expect(() => - Mina.transaction(feePayer, () => { + Mina.transaction(feePayer, async () => { zkAppC.approveIncorrectLayout(UInt64.from(10_000)); tokenZkapp.approveTransfer( zkAppBAddress, @@ -573,7 +573,7 @@ describe('Token', () => { }); test('should reject tx if user bypasses the token contract by using an empty account update', async () => { - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); tokenZkapp.token.mint({ address: zkAppBAddress, From 2776acebe8de1f15ccaf270e41dab2f3d3732ba8 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 29 Feb 2024 09:56:27 +0100 Subject: [PATCH 06/10] async tx callback - examples --- src/examples/circuit-string.ts | 6 +- src/examples/commonjs.cjs | 4 +- src/examples/fetch-live.ts | 2 +- src/examples/nullifier.ts | 6 +- src/examples/simple-zkapp-berkeley.ts | 4 +- src/examples/simple-zkapp.js | 4 +- src/examples/simple-zkapp.ts | 12 ++-- src/examples/simple-zkapp.web.ts | 8 +-- src/examples/zkapps/composability.ts | 4 +- .../zkapps/dex/happy-path-with-actions.ts | 18 +++--- .../zkapps/dex/happy-path-with-proofs.ts | 12 ++-- src/examples/zkapps/dex/run-live.ts | 18 +++--- src/examples/zkapps/dex/run.ts | 40 ++++++------- src/examples/zkapps/dex/upgradability.ts | 32 +++++----- src/examples/zkapps/hashing/run.ts | 10 ++-- src/examples/zkapps/hello-world/run-live.ts | 11 ++-- src/examples/zkapps/hello-world/run.ts | 30 ++++++---- src/examples/zkapps/local-events-zkapp.ts | 6 +- .../zkapps/merkle-tree/merkle-zkapp.ts | 4 +- .../zkapps/reducer/actions-as-merkle-list.ts | 6 +- src/examples/zkapps/reducer/map.ts | 14 ++--- .../zkapps/reducer/reducer-composite.ts | 16 ++--- src/examples/zkapps/reducer/reducer.ts | 16 ++--- .../zkapps/set-local-preconditions-zkapp.ts | 8 +-- src/examples/zkapps/simple-zkapp-payment.ts | 8 +-- .../zkapps/simple-zkapp-with-proof.ts | 10 ++-- src/examples/zkapps/sudoku/index.ts | 6 +- src/examples/zkapps/token-with-proofs.ts | 10 ++-- src/examples/zkapps/voting/demo.ts | 18 +++--- .../zkapps/voting/deploy-contracts.ts | 4 +- src/examples/zkapps/voting/run-berkeley.ts | 12 ++-- src/examples/zkapps/voting/test.ts | 59 ++++++++++--------- src/examples/zkapps/voting/voting-lib.ts | 2 +- src/examples/zkapps/zkapp-self-update.ts | 4 +- src/lib/zkapp.ts | 2 +- src/tests/fake-proof.ts | 4 +- src/tests/transaction-flow.ts | 20 +++---- .../on-chain-state-mgmt-zkapp-ui.js | 4 +- tests/integration/simple-zkapp-mock-apply.js | 6 +- tests/integration/simple-zkapp.js | 12 ++-- 40 files changed, 242 insertions(+), 230 deletions(-) diff --git a/src/examples/circuit-string.ts b/src/examples/circuit-string.ts index 71bbe20490..a69b515b53 100644 --- a/src/examples/circuit-string.ts +++ b/src/examples/circuit-string.ts @@ -26,19 +26,19 @@ console.log('compile...'); await MyContract.compile(); // should work console.log('prove...'); -let tx = await Mina.transaction(() => { +let tx = await Mina.transaction(async () => { new MyContract(address).checkString(CircuitString.fromString('a string')); }); await tx.prove(); console.log('test 1 - ok'); // should work -tx = await Mina.transaction(() => { +tx = await Mina.transaction(async () => { new MyContract(address).checkString(CircuitString.fromString('some string')); }); await tx.prove(); console.log('test 2 - ok'); // should fail -let fails = await Mina.transaction(() => { +let fails = await Mina.transaction(async () => { new MyContract(address).checkString(CircuitString.fromString('different')); }) .then(() => false) diff --git a/src/examples/commonjs.cjs b/src/examples/commonjs.cjs index 2f3c766009..ddf5fa4e21 100644 --- a/src/examples/commonjs.cjs +++ b/src/examples/commonjs.cjs @@ -56,7 +56,7 @@ async function main() { await SimpleZkapp.compile(); console.log('deploy'); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); zkapp.deploy(); }); @@ -65,7 +65,7 @@ async function main() { console.log('initial state: ' + zkapp.x.get()); console.log('update'); - tx = await Mina.transaction(feePayer, () => zkapp.update(Field(3))); + tx = await Mina.transaction(feePayer, async () => zkapp.update(Field(3))); await tx.prove(); await tx.sign([feePayerKey]).send(); console.log('final state: ' + zkapp.x.get()); diff --git a/src/examples/fetch-live.ts b/src/examples/fetch-live.ts index 85ce4b8d4d..b432580352 100644 --- a/src/examples/fetch-live.ts +++ b/src/examples/fetch-live.ts @@ -30,7 +30,7 @@ async function checkActualNetworkConstantsFetching() { '\nCase #2: check that actual network constants can be fetched within the transaction scope.' ); let networkConstants: Mina.NetworkConstants | undefined; - await Mina.transaction({ sender, fee: transactionFee }, () => { + await Mina.transaction({ sender, fee: transactionFee }, async () => { networkConstants = Mina.getNetworkConstants(); }); expect(networkConstants?.slotTime).not.toBeUndefined(); diff --git a/src/examples/nullifier.ts b/src/examples/nullifier.ts index 8f3ea81001..1cee451581 100644 --- a/src/examples/nullifier.ts +++ b/src/examples/nullifier.ts @@ -72,7 +72,7 @@ console.log('compile'); await PayoutOnlyOnce.compile(); console.log('deploy'); -let tx = await Mina.transaction(sender, () => { +let tx = await Mina.transaction(sender, async () => { let senderUpdate = AccountUpdate.fundNewAccount(sender); senderUpdate.send({ to: zkappAddress, amount: initialBalance }); zkapp.deploy({ zkappKey }); @@ -94,7 +94,7 @@ let jsonNullifier = Nullifier.createTestNullifier( console.log(jsonNullifier); console.log('pay out'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { AccountUpdate.fundNewAccount(sender); zkapp.payout(Nullifier.fromJSON(jsonNullifier)); }); @@ -109,7 +109,7 @@ console.log( console.log('trying second pay out'); try { - tx = await Mina.transaction(sender, () => { + tx = await Mina.transaction(sender, async () => { zkapp.payout(Nullifier.fromJSON(jsonNullifier)); }); diff --git a/src/examples/simple-zkapp-berkeley.ts b/src/examples/simple-zkapp-berkeley.ts index 3d59c9c2d9..077d4e3fb2 100644 --- a/src/examples/simple-zkapp-berkeley.ts +++ b/src/examples/simple-zkapp-berkeley.ts @@ -83,7 +83,7 @@ if (!isDeployed) { // the `transaction()` interface is the same as when testing with a local blockchain let transaction = await Mina.transaction( { sender: feePayerAddress, fee: transactionFee }, - () => { + async () => { AccountUpdate.fundNewAccount(feePayerAddress); zkapp.deploy({ verificationKey }); } @@ -102,7 +102,7 @@ if (isDeployed) { console.log(`Found deployed zkapp, updating state ${x} -> ${x.add(10)}.`); let transaction = await Mina.transaction( { sender: feePayerAddress, fee: transactionFee }, - () => { + async () => { zkapp.update(Field(10)); } ); diff --git a/src/examples/simple-zkapp.js b/src/examples/simple-zkapp.js index c4ed4fc7c2..dc349b0a5e 100644 --- a/src/examples/simple-zkapp.js +++ b/src/examples/simple-zkapp.js @@ -59,7 +59,7 @@ console.log('compile'); await SimpleZkapp.compile(); console.log('deploy'); -let tx = await Mina.transaction(feePayer, () => { +let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); zkapp.deploy(); }); @@ -68,7 +68,7 @@ await tx.sign([feePayerKey, zkappKey]).send(); console.log('initial state: ' + zkapp.x.get()); console.log('update'); -tx = await Mina.transaction(feePayer, () => zkapp.update(Field(3))); +tx = await Mina.transaction(feePayer, async () => zkapp.update(Field(3))); await tx.prove(); await tx.sign([feePayerKey]).send(); console.log('final state: ' + zkapp.x.get()); diff --git a/src/examples/simple-zkapp.ts b/src/examples/simple-zkapp.ts index e2768fbe07..c93e0fd3b8 100644 --- a/src/examples/simple-zkapp.ts +++ b/src/examples/simple-zkapp.ts @@ -96,7 +96,7 @@ if (doProofs) { } console.log('deploy'); -let tx = await Mina.transaction(sender, () => { +let tx = await Mina.transaction(sender, async () => { let senderUpdate = AccountUpdate.fundNewAccount(sender); senderUpdate.send({ to: zkappAddress, amount: initialBalance }); zkapp.deploy(); @@ -111,7 +111,7 @@ let account = Mina.getAccount(zkappAddress); console.log('account state is proved:', account.zkapp?.provedState.toBoolean()); console.log('update'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { zkapp.update(Field(3)); }); await tx.prove(); @@ -119,14 +119,14 @@ await tx.sign([senderKey]).send(); // pay more into the zkapp -- this doesn't need a proof console.log('receive'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { let payerAccountUpdate = AccountUpdate.createSigned(sender); payerAccountUpdate.send({ to: zkappAddress, amount: UInt64.from(8e9) }); }); await tx.sign([senderKey]).send(); console.log('payout'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { AccountUpdate.fundNewAccount(sender); zkapp.payout(privilegedKey); }); @@ -138,7 +138,7 @@ console.log('final state: ' + zkapp.x.get()); console.log(`final balance: ${zkapp.account.balance.get().div(1e9)} MINA`); console.log('try to payout a second time..'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { zkapp.payout(privilegedKey); }); try { @@ -150,7 +150,7 @@ try { console.log('try to payout to a different account..'); try { - tx = await Mina.transaction(sender, () => { + tx = await Mina.transaction(sender, async () => { zkapp.payout(Local.testAccounts[2].privateKey); }); await tx.prove(); diff --git a/src/examples/simple-zkapp.web.ts b/src/examples/simple-zkapp.web.ts index 9a10d1e070..e524024a03 100644 --- a/src/examples/simple-zkapp.web.ts +++ b/src/examples/simple-zkapp.web.ts @@ -89,7 +89,7 @@ if (doProofs) { } console.log('deploy'); -let tx = await Mina.transaction(sender, () => { +let tx = await Mina.transaction(sender, async () => { let senderUpdate = AccountUpdate.fundNewAccount(sender); senderUpdate.send({ to: zkappAddress, amount: initialBalance }); zkapp.deploy({ zkappKey }); @@ -104,7 +104,7 @@ let account = Mina.getAccount(zkappAddress); console.log('account state is proved:', account.zkapp?.provedState.toBoolean()); console.log('update'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { zkapp.update(Field(3)); }); await tx.prove(); @@ -112,14 +112,14 @@ await tx.sign([senderKey]).send(); // pay more into the zkapp -- this doesn't need a proof console.log('receive'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { let payerAccountUpdate = AccountUpdate.createSigned(sender); payerAccountUpdate.send({ to: zkappAddress, amount: UInt64.from(8e9) }); }); await tx.sign([senderKey]).send(); console.log('payout'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { AccountUpdate.fundNewAccount(sender); zkapp.payout(privilegedKey); }); diff --git a/src/examples/zkapps/composability.ts b/src/examples/zkapps/composability.ts index 253a992224..6b79697eb2 100644 --- a/src/examples/zkapps/composability.ts +++ b/src/examples/zkapps/composability.ts @@ -85,7 +85,7 @@ if (doProofs) { } console.log('deploy'); -let tx = await Mina.transaction(feePayer, () => { +let tx = await Mina.transaction(feePayer, async () => { // TODO: enable funding multiple accounts properly AccountUpdate.fundNewAccount(feePayer, 3); zkapp.deploy(); @@ -95,7 +95,7 @@ let tx = await Mina.transaction(feePayer, () => { await tx.sign([feePayerKey, zkappKey, adderKey, incrementerKey]).send(); console.log('call interaction'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { // we just call one contract here, nothing special to do zkapp.callAddAndEmit(Field(5), Field(6)); }); diff --git a/src/examples/zkapps/dex/happy-path-with-actions.ts b/src/examples/zkapps/dex/happy-path-with-actions.ts index 78a07961eb..8b03a01a2c 100644 --- a/src/examples/zkapps/dex/happy-path-with-actions.ts +++ b/src/examples/zkapps/dex/happy-path-with-actions.ts @@ -42,7 +42,7 @@ let dexTokenHolderX = new DexTokenHolder(addresses.dex, tokenIds.X); let dexTokenHolderY = new DexTokenHolder(addresses.dex, tokenIds.Y); tic('deploy & init token contracts'); -tx = await Mina.transaction(feePayerAddress, () => { +tx = await Mina.transaction(feePayerAddress, async () => { tokenX.deploy(); tokenY.deploy(); @@ -58,7 +58,7 @@ toc(); console.log('account updates length', tx.transaction.accountUpdates.length); tic('deploy dex contracts'); -tx = await Mina.transaction(feePayerAddress, () => { +tx = await Mina.transaction(feePayerAddress, async () => { // pay fees for creating 3 dex accounts AccountUpdate.createSigned(feePayerAddress).balance.subInPlace( Mina.getNetworkConstants().accountCreationFee.mul(3) @@ -76,7 +76,7 @@ console.log('account updates length', tx.transaction.accountUpdates.length); tic('transfer tokens to user'); let USER_DX = 1_000n; -tx = await Mina.transaction(feePayerAddress, () => { +tx = await Mina.transaction(feePayerAddress, async () => { // pay fees for creating 3 user accounts let feePayer = AccountUpdate.fundNewAccount(feePayerAddress, 3); feePayer.send({ to: addresses.user, amount: 20e9 }); // give users MINA to pay fees @@ -90,7 +90,7 @@ console.log('account updates length', tx.transaction.accountUpdates.length); // this is done in advance to avoid account update limit in `supply` tic("create user's lq token account"); -tx = await Mina.transaction(addresses.user, () => { +tx = await Mina.transaction(addresses.user, async () => { AccountUpdate.fundNewAccount(addresses.user); dex.createAccount(); }); @@ -104,7 +104,7 @@ expect(balances.user.X).toEqual(USER_DX); console.log(balances); tic('supply liquidity'); -tx = await Mina.transaction(addresses.user, () => { +tx = await Mina.transaction(addresses.user, async () => { dex.supplyLiquidityBase(UInt64.from(USER_DX), UInt64.from(USER_DX)); }); await tx.prove(); @@ -117,7 +117,7 @@ console.log(balances); tic('redeem liquidity, step 1'); let USER_DL = 100n; -tx = await Mina.transaction(addresses.user, () => { +tx = await Mina.transaction(addresses.user, async () => { dex.redeemInitialize(UInt64.from(USER_DL)); }); await tx.prove(); @@ -127,7 +127,7 @@ console.log('account updates length', tx.transaction.accountUpdates.length); console.log(getTokenBalances()); tic('redeem liquidity, step 2a (get back token X)'); -tx = await Mina.transaction(addresses.user, () => { +tx = await Mina.transaction(addresses.user, async () => { dexTokenHolderX.redeemLiquidityFinalize(); tokenX.approveAccountUpdate(dexTokenHolderX.self); }); @@ -138,7 +138,7 @@ console.log('account updates length', tx.transaction.accountUpdates.length); console.log(getTokenBalances()); tic('redeem liquidity, step 2b (get back token Y)'); -tx = await Mina.transaction(addresses.user, () => { +tx = await Mina.transaction(addresses.user, async () => { dexTokenHolderY.redeemLiquidityFinalize(); tokenY.approveAccountUpdate(dexTokenHolderY.self); }); @@ -153,7 +153,7 @@ expect(balances.user.X).toEqual(USER_DL / 2n); tic('swap 10 X for Y'); USER_DX = 10n; -tx = await Mina.transaction(addresses.user, () => { +tx = await Mina.transaction(addresses.user, async () => { dex.swapX(UInt64.from(USER_DX)); }); await tx.prove(); diff --git a/src/examples/zkapps/dex/happy-path-with-proofs.ts b/src/examples/zkapps/dex/happy-path-with-proofs.ts index 722caf8a69..456a35b6e4 100644 --- a/src/examples/zkapps/dex/happy-path-with-proofs.ts +++ b/src/examples/zkapps/dex/happy-path-with-proofs.ts @@ -44,7 +44,7 @@ let dexTokenHolderX = new DexTokenHolder(addresses.dex, tokenIds.X); let dexTokenHolderY = new DexTokenHolder(addresses.dex, tokenIds.Y); tic('deploy & init token contracts'); -tx = await Mina.transaction(feePayerAddress, () => { +tx = await Mina.transaction(feePayerAddress, async () => { tokenX.deploy(); tokenY.deploy(); @@ -60,7 +60,7 @@ toc(); console.log('account updates length', tx.transaction.accountUpdates.length); tic('deploy dex contracts'); -tx = await Mina.transaction(feePayerAddress, () => { +tx = await Mina.transaction(feePayerAddress, async () => { // pay fees for creating 3 dex accounts AccountUpdate.createSigned(feePayerAddress).balance.subInPlace( Mina.getNetworkConstants().accountCreationFee.mul(3) @@ -78,7 +78,7 @@ console.log('account updates length', tx.transaction.accountUpdates.length); tic('transfer tokens to user'); let USER_DX = 1_000n; -tx = await Mina.transaction(feePayerAddress, () => { +tx = await Mina.transaction(feePayerAddress, async () => { // pay fees for creating 3 user accounts let feePayer = AccountUpdate.fundNewAccount(feePayerAddress, 3); feePayer.send({ to: addresses.user, amount: 20e9 }); // give users MINA to pay fees @@ -93,7 +93,7 @@ console.log('account updates length', tx.transaction.accountUpdates.length); expect(balances.user.X).toEqual(USER_DX); tic('supply liquidity'); -tx = await Mina.transaction(addresses.user, () => { +tx = await Mina.transaction(addresses.user, async () => { AccountUpdate.fundNewAccount(addresses.user); dex.supplyLiquidityBase(UInt64.from(USER_DX), UInt64.from(USER_DX)); }); @@ -106,7 +106,7 @@ expect(balances.user.X).toEqual(0n); tic('redeem liquidity'); let USER_DL = 100n; -tx = await Mina.transaction(addresses.user, () => { +tx = await Mina.transaction(addresses.user, async () => { dex.redeemLiquidity(UInt64.from(USER_DL)); }); @@ -119,7 +119,7 @@ expect(balances.user.X).toEqual(USER_DL / 2n); tic('swap 10 X for Y'); USER_DX = 10n; -tx = await Mina.transaction(addresses.user, () => { +tx = await Mina.transaction(addresses.user, async () => { dex.swapX(UInt64.from(USER_DX)); }); await tx.prove(); diff --git a/src/examples/zkapps/dex/run-live.ts b/src/examples/zkapps/dex/run-live.ts index 1d766aff83..4c48747fdd 100644 --- a/src/examples/zkapps/dex/run-live.ts +++ b/src/examples/zkapps/dex/run-live.ts @@ -72,7 +72,7 @@ let userSpec = { sender: addresses.user, fee: 0.1e9 }; if (successfulTransactions <= 0) { tic('deploy & init token contracts'); - tx = await Mina.transaction(senderSpec, () => { + tx = await Mina.transaction(senderSpec, async () => { tokenX.deploy(); tokenY.deploy(); @@ -95,7 +95,7 @@ if (successfulTransactions <= 0) { if (successfulTransactions <= 1) { tic('deploy dex contracts'); - tx = await Mina.transaction(senderSpec, () => { + tx = await Mina.transaction(senderSpec, async () => { // pay fees for creating 3 dex accounts AccountUpdate.createSigned(sender).balance.subInPlace( Mina.getNetworkConstants().accountCreationFee.mul(3) @@ -121,7 +121,7 @@ let USER_DX = 1_000n; if (successfulTransactions <= 2) { tic('transfer tokens to user'); - tx = await Mina.transaction(senderSpec, () => { + tx = await Mina.transaction(senderSpec, async () => { // pay fees for creating 3 user accounts let feePayer = AccountUpdate.fundNewAccount(sender, 3); feePayer.send({ to: addresses.user, amount: 8e9 }); // give users MINA to pay fees @@ -142,7 +142,7 @@ if (successfulTransactions <= 2) { if (successfulTransactions <= 3) { // this is done in advance to avoid account update limit in `supply` tic("create user's lq token account"); - tx = await Mina.transaction(userSpec, () => { + tx = await Mina.transaction(userSpec, async () => { AccountUpdate.fundNewAccount(addresses.user); dex.createAccount(); }); @@ -163,7 +163,7 @@ if (successfulTransactions <= 3) { if (successfulTransactions <= 4) { tic('supply liquidity'); - tx = await Mina.transaction(userSpec, () => { + tx = await Mina.transaction(userSpec, async () => { dex.supplyLiquidityBase(UInt64.from(USER_DX), UInt64.from(USER_DX)); }); await tx.prove(); @@ -185,7 +185,7 @@ let USER_DL = 100n; if (successfulTransactions <= 5) { tic('redeem liquidity, step 1'); - tx = await Mina.transaction(userSpec, () => { + tx = await Mina.transaction(userSpec, async () => { dex.redeemInitialize(UInt64.from(USER_DL)); }); await tx.prove(); @@ -203,7 +203,7 @@ if (successfulTransactions <= 5) { if (successfulTransactions <= 6) { tic('redeem liquidity, step 2a (get back token X)'); - tx = await Mina.transaction(userSpec, () => { + tx = await Mina.transaction(userSpec, async () => { dexTokenHolderX.redeemLiquidityFinalize(); tokenX.approveAccountUpdate(dexTokenHolderX.self); }); @@ -222,7 +222,7 @@ if (successfulTransactions <= 6) { if (successfulTransactions <= 7) { tic('redeem liquidity, step 2b (get back token Y)'); - tx = await Mina.transaction(userSpec, () => { + tx = await Mina.transaction(userSpec, async () => { dexTokenHolderY.redeemLiquidityFinalize(); tokenY.approveAccountUpdate(dexTokenHolderY.self); }); @@ -246,7 +246,7 @@ if (successfulTransactions <= 8) { tic('swap 10 X for Y'); USER_DX = 10n; - tx = await Mina.transaction(userSpec, () => { + tx = await Mina.transaction(userSpec, async () => { dex.swapX(UInt64.from(USER_DX)); }); await tx.prove(); diff --git a/src/examples/zkapps/dex/run.ts b/src/examples/zkapps/dex/run.ts index 7f3b5d46b6..bae3a75921 100644 --- a/src/examples/zkapps/dex/run.ts +++ b/src/examples/zkapps/dex/run.ts @@ -75,7 +75,7 @@ async function main({ withVesting }: { withVesting: boolean }) { let dexTokenHolderY = new DexTokenHolder(addresses.dex, tokenIds.Y); console.log('deploy & init token contracts...'); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { tokenX.deploy(); tokenY.deploy(); @@ -96,7 +96,7 @@ async function main({ withVesting }: { withVesting: boolean }) { ); console.log('deploy dex contracts...'); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { // pay fees for creating 3 dex accounts AccountUpdate.fundNewAccount(feePayerAddress, 3); dex.deploy(); @@ -115,7 +115,7 @@ async function main({ withVesting }: { withVesting: boolean }) { sender: feePayerAddress, fee: Mina.getNetworkConstants().accountCreationFee.mul(1), }, - () => { + async () => { let feePayer = AccountUpdate.fundNewAccount(feePayerAddress, 4); feePayer.send({ to: addresses.user, amount: 20e9 }); // give users MINA to pay fees feePayer.send({ to: addresses.user2, amount: 20e9 }); @@ -141,7 +141,7 @@ async function main({ withVesting }: { withVesting: boolean }) { sender: feePayerAddress, fee: Mina.getNetworkConstants().accountCreationFee, }, - () => { + async () => { AccountUpdate.fundNewAccount(feePayerAddress); dex.supplyLiquidityBase(UInt64.from(10_000), UInt64.from(10_000)); } @@ -179,7 +179,7 @@ async function main({ withVesting }: { withVesting: boolean }) { */ let USER_DX = 500_000n; console.log('user supply liquidity (1)'); - tx = await Mina.transaction(addresses.user, () => { + tx = await Mina.transaction(addresses.user, async () => { AccountUpdate.fundNewAccount(addresses.user); dex.supplyLiquidity(UInt64.from(USER_DX)); }); @@ -217,7 +217,7 @@ async function main({ withVesting }: { withVesting: boolean }) { */ USER_DX = 1000n; console.log('user supply liquidity (2)'); - tx = await Mina.transaction(addresses.user, () => { + tx = await Mina.transaction(addresses.user, async () => { dex.supplyLiquidity(UInt64.from(USER_DX)); }); await tx.prove(); @@ -248,7 +248,7 @@ async function main({ withVesting }: { withVesting: boolean }) { * - There is not enough tokens available for user’s tokens accounts, one is willing to supply; */ console.log('supplying with no tokens (should fail)'); - tx = await Mina.transaction(addresses.user2, () => { + tx = await Mina.transaction(addresses.user2, async () => { AccountUpdate.fundNewAccount(addresses.user2); dex.supplyLiquidityBase(UInt64.from(100), UInt64.from(100)); }); @@ -256,7 +256,7 @@ async function main({ withVesting }: { withVesting: boolean }) { tx.sign([keys.user2]); await expect(tx.sendOrThrowIfError()).rejects.toThrow(/Overflow/); console.log('supplying with insufficient tokens (should fail)'); - tx = await Mina.transaction(addresses.user, () => { + tx = await Mina.transaction(addresses.user, async () => { dex.supplyLiquidityBase(UInt64.from(1e9), UInt64.from(1e9)); }); await tx.prove(); @@ -271,7 +271,7 @@ async function main({ withVesting }: { withVesting: boolean }) { * => a targeted test with explicitly constructed account updates might be the better strategy to test overflow */ console.log('prepare supplying overflowing liquidity'); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { AccountUpdate.fundNewAccount(feePayerAddress); tokenY.transfer( addresses.tokenY, @@ -283,7 +283,7 @@ async function main({ withVesting }: { withVesting: boolean }) { await tx.sign([feePayerKey, keys.tokenY]).sendOrThrowIfError(); console.log('supply overflowing liquidity'); await expect(async () => { - tx = await Mina.transaction(addresses.tokenX, () => { + tx = await Mina.transaction(addresses.tokenX, async () => { dex.supplyLiquidityBase( UInt64.MAXINT().sub(200_000), UInt64.MAXINT().sub(200_000) @@ -298,7 +298,7 @@ async function main({ withVesting }: { withVesting: boolean }) { * - Value transfer is restricted (supplier end: withdrawal is prohibited, receiver end: receiving is prohibited) for one or both accounts. */ console.log('prepare test with forbidden send'); - tx = await Mina.transaction(addresses.tokenX, () => { + tx = await Mina.transaction(addresses.tokenX, async () => { let tokenXtokenAccount = AccountUpdate.create(addresses.tokenX, tokenIds.X); tokenXtokenAccount.account.permissions.set({ ...Permissions.initial(), @@ -313,7 +313,7 @@ async function main({ withVesting }: { withVesting: boolean }) { await tx.prove(); await tx.sign([keys.tokenX]).send(); console.log('supply with forbidden withdrawal (should fail)'); - tx = await Mina.transaction(addresses.tokenX, () => { + tx = await Mina.transaction(addresses.tokenX, async () => { AccountUpdate.fundNewAccount(addresses.tokenX); dex.supplyLiquidity(UInt64.from(10)); }); @@ -340,7 +340,7 @@ async function main({ withVesting }: { withVesting: boolean }) { Local.incrementGlobalSlot(1); let USER_DL = 100n; console.log('user redeem liquidity (before liquidity token unlocks)'); - tx = await Mina.transaction(addresses.user, () => { + tx = await Mina.transaction(addresses.user, async () => { dex.redeemLiquidity(UInt64.from(USER_DL)); }); await tx.prove(); @@ -366,7 +366,7 @@ async function main({ withVesting }: { withVesting: boolean }) { */ let USER_DL = 100n; console.log('user redeem liquidity'); - tx = await Mina.transaction(addresses.user, () => { + tx = await Mina.transaction(addresses.user, async () => { dex.redeemLiquidity(UInt64.from(USER_DL)); }); await tx.prove(); @@ -404,7 +404,7 @@ async function main({ withVesting }: { withVesting: boolean }) { if (withVesting) { USER_DX = 1000n; console.log('user supply liquidity -- again, after lock period ended'); - tx = await Mina.transaction(addresses.user, () => { + tx = await Mina.transaction(addresses.user, async () => { dex.supplyLiquidity(UInt64.from(USER_DX)); }); await tx.prove(); @@ -436,7 +436,7 @@ async function main({ withVesting }: { withVesting: boolean }) { */ USER_DL = 80n; console.log('transfer liquidity tokens to user2'); - tx = await Mina.transaction(addresses.user, () => { + tx = await Mina.transaction(addresses.user, async () => { AccountUpdate.fundNewAccount(addresses.user); dex.transfer(addresses.user, addresses.user2, UInt64.from(USER_DL)); }); @@ -447,7 +447,7 @@ async function main({ withVesting }: { withVesting: boolean }) { console.log( 'redeem liquidity with both users in one tx (fails because of conflicting balance preconditions)' ); - tx = await Mina.transaction(addresses.user2, () => { + tx = await Mina.transaction(addresses.user2, async () => { AccountUpdate.createSigned(addresses.user2).balance.subInPlace( Mina.getNetworkConstants().accountCreationFee.mul(2) ); @@ -461,7 +461,7 @@ async function main({ withVesting }: { withVesting: boolean }) { ); console.log('user2 redeem liquidity'); - tx = await Mina.transaction(addresses.user2, () => { + tx = await Mina.transaction(addresses.user2, async () => { AccountUpdate.createSigned(addresses.user2).balance.subInPlace( Mina.getNetworkConstants().accountCreationFee.mul(2) ); @@ -487,7 +487,7 @@ async function main({ withVesting }: { withVesting: boolean }) { * note: user2's account is empty now, so redeeming more liquidity fails */ console.log('user2 redeem liquidity (fails because insufficient balance)'); - tx = await Mina.transaction(addresses.user2, () => { + tx = await Mina.transaction(addresses.user2, async () => { dex.redeemLiquidity(UInt64.from(1n)); }); await tx.prove(); @@ -511,7 +511,7 @@ async function main({ withVesting }: { withVesting: boolean }) { */ USER_DX = 10n; console.log('swap 10 X for Y'); - tx = await Mina.transaction(addresses.user, () => { + tx = await Mina.transaction(addresses.user, async () => { dex.swapX(UInt64.from(USER_DX)); }); await tx.prove(); diff --git a/src/examples/zkapps/dex/upgradability.ts b/src/examples/zkapps/dex/upgradability.ts index 61ff9f44b3..4178499316 100644 --- a/src/examples/zkapps/dex/upgradability.ts +++ b/src/examples/zkapps/dex/upgradability.ts @@ -56,7 +56,7 @@ async function atomicActionsTest({ withVesting }: { withVesting: boolean }) { let dexTokenHolderY = new DexTokenHolder(addresses.dex, tokenIds.Y); console.log('deploy & init token contracts...'); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { tokenX.deploy(); tokenY.deploy(); @@ -91,7 +91,7 @@ async function atomicActionsTest({ withVesting }: { withVesting: boolean }) { */ console.log('deploy dex contracts...'); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { // pay fees for creating 3 dex accounts AccountUpdate.fundNewAccount(feePayerAddress, 3); dex.deploy(); @@ -115,7 +115,7 @@ async function atomicActionsTest({ withVesting }: { withVesting: boolean }) { console.log( 'trying to change delegate (setDelegate=impossible, should fail)' ); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { // setting the delegate field to something, although permissions forbid it let dexAccount = AccountUpdate.create(addresses.dex); dexAccount.account.delegate.set(PrivateKey.random().toPublicKey()); @@ -129,7 +129,7 @@ async function atomicActionsTest({ withVesting }: { withVesting: boolean }) { console.log('changing delegate permission back to normal'); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { let dexAccount = AccountUpdate.create(addresses.dex); dexAccount.account.permissions.set({ ...Permissions.initial(), @@ -143,7 +143,7 @@ async function atomicActionsTest({ withVesting }: { withVesting: boolean }) { console.log('changing delegate field to a new address'); let newDelegate = PrivateKey.random().toPublicKey(); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { let dexAccount = AccountUpdate.create(addresses.dex); dexAccount.account.delegate.set(newDelegate); dexAccount.requireSignature(); @@ -170,7 +170,7 @@ async function atomicActionsTest({ withVesting }: { withVesting: boolean }) { 'changing permission to impossible and then trying to change delegate field - in one transaction' ); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { // changing the permission to impossible and then trying to change the delegate field let permissionUpdate = AccountUpdate.create(addresses.dex); @@ -206,7 +206,7 @@ async function atomicActionsTest({ withVesting }: { withVesting: boolean }) { console.log('creating multiple valid account updates in one transaction'); newDelegate = PrivateKey.random().toPublicKey(); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { // changing field let fieldUpdate = AccountUpdate.create(addresses.dex); fieldUpdate.account.delegate.set(newDelegate); @@ -267,7 +267,7 @@ async function upgradeabilityTests({ withVesting }: { withVesting: boolean }) { let dexTokenHolderY = new DexTokenHolder(addresses.dex, tokenIds.Y); console.log('deploy & init token contracts...'); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { tokenX.deploy(); tokenY.deploy(); @@ -306,7 +306,7 @@ async function upgradeabilityTests({ withVesting }: { withVesting: boolean }) { console.log('deploy dex contracts...'); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { // pay fees for creating 3 dex accounts AccountUpdate.fundNewAccount(feePayerAddress, 3); dex.deploy(); @@ -325,7 +325,7 @@ async function upgradeabilityTests({ withVesting }: { withVesting: boolean }) { sender: feePayerAddress, fee: Mina.getNetworkConstants().accountCreationFee.mul(1), }, - () => { + async () => { let feePayer = AccountUpdate.createSigned(feePayerAddress); feePayer.balance.subInPlace( Mina.getNetworkConstants().accountCreationFee.mul(4) @@ -366,7 +366,7 @@ async function upgradeabilityTests({ withVesting }: { withVesting: boolean }) { tokenIds.Y ); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { modifiedDex.deploy(); modifiedDexTokenHolderX.deploy(); tokenX.approveAccountUpdate(modifiedDexTokenHolderX.self); @@ -397,7 +397,7 @@ async function upgradeabilityTests({ withVesting }: { withVesting: boolean }) { sender: feePayerAddress, fee: Mina.getNetworkConstants().accountCreationFee.mul(1), }, - () => { + async () => { AccountUpdate.fundNewAccount(feePayerAddress); modifiedDex.supplyLiquidityBase(UInt64.from(10_000), UInt64.from(10_000)); } @@ -410,7 +410,7 @@ async function upgradeabilityTests({ withVesting }: { withVesting: boolean }) { let USER_DX = 10n; console.log('swap 10 X for Y'); - tx = await Mina.transaction(addresses.user, () => { + tx = await Mina.transaction(addresses.user, async () => { modifiedDex.swapX(UInt64.from(USER_DX)); }); await tx.prove(); @@ -440,7 +440,7 @@ async function upgradeabilityTests({ withVesting }: { withVesting: boolean }) { console.log('changing upgrade permissions to impossible'); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { // pay fees for creating 3 dex accounts let update = AccountUpdate.createSigned(addresses.dex); update.account.permissions.set({ @@ -457,7 +457,7 @@ async function upgradeabilityTests({ withVesting }: { withVesting: boolean }) { console.log('trying to upgrade contract - should fail'); - tx = await Mina.transaction(feePayerAddress, () => { + tx = await Mina.transaction(feePayerAddress, async () => { modifiedDex.deploy(); // cannot deploy new VK because its forbidden }); await tx.prove(); @@ -469,7 +469,7 @@ async function upgradeabilityTests({ withVesting }: { withVesting: boolean }) { // method should still be valid since the upgrade was forbidden USER_DX = 10n; console.log('swap 10 X for Y'); - tx = await Mina.transaction(addresses.user, () => { + tx = await Mina.transaction(addresses.user, async () => { modifiedDex.swapX(UInt64.from(USER_DX)); }); await tx.prove(); diff --git a/src/examples/zkapps/hashing/run.ts b/src/examples/zkapps/hashing/run.ts index e1568fa95d..78efd2b629 100644 --- a/src/examples/zkapps/hashing/run.ts +++ b/src/examples/zkapps/hashing/run.ts @@ -24,7 +24,7 @@ const zkAppInstance = new HashStorage(zkAppAddress); const hashData = Bytes.from(Array.from({ length: 32 }, (_, i) => i)); console.log('Deploying Hash Example....'); -txn = await Mina.transaction(feePayer.publicKey, () => { +txn = await Mina.transaction(feePayer.publicKey, async () => { AccountUpdate.fundNewAccount(feePayer.publicKey); zkAppInstance.deploy(); }); @@ -37,7 +37,7 @@ let currentState; console.log('Initial State', initialState); console.log(`Updating commitment from ${initialState} using SHA256 ...`); -txn = await Mina.transaction(feePayer.publicKey, () => { +txn = await Mina.transaction(feePayer.publicKey, async () => { zkAppInstance.SHA256(hashData); }); await txn.prove(); @@ -46,7 +46,7 @@ currentState = Mina.getAccount(zkAppAddress).zkapp?.appState?.[0].toString(); console.log(`Current state successfully updated to ${currentState}`); console.log(`Updating commitment from ${initialState} using SHA384 ...`); -txn = await Mina.transaction(feePayer.publicKey, () => { +txn = await Mina.transaction(feePayer.publicKey, async () => { zkAppInstance.SHA384(hashData); }); await txn.prove(); @@ -55,7 +55,7 @@ currentState = Mina.getAccount(zkAppAddress).zkapp?.appState?.[0].toString(); console.log(`Current state successfully updated to ${currentState}`); console.log(`Updating commitment from ${initialState} using SHA512 ...`); -txn = await Mina.transaction(feePayer.publicKey, () => { +txn = await Mina.transaction(feePayer.publicKey, async () => { zkAppInstance.SHA512(hashData); }); await txn.prove(); @@ -64,7 +64,7 @@ currentState = Mina.getAccount(zkAppAddress).zkapp?.appState?.[0].toString(); console.log(`Current state successfully updated to ${currentState}`); console.log(`Updating commitment from ${initialState} using Keccak256...`); -txn = await Mina.transaction(feePayer.publicKey, () => { +txn = await Mina.transaction(feePayer.publicKey, async () => { zkAppInstance.Keccak256(hashData); }); await txn.prove(); diff --git a/src/examples/zkapps/hello-world/run-live.ts b/src/examples/zkapps/hello-world/run-live.ts index 8fa166e632..0bddcc8f48 100644 --- a/src/examples/zkapps/hello-world/run-live.ts +++ b/src/examples/zkapps/hello-world/run-live.ts @@ -51,7 +51,7 @@ console.log(''); console.log(`Deploying zkApp for public key ${zkAppAddress.toBase58()}.`); let transaction = await Mina.transaction( { sender, fee: transactionFee }, - () => { + async () => { AccountUpdate.fundNewAccount(sender); zkApp.deploy({ verificationKey }); } @@ -71,9 +71,12 @@ console.log(''); // zkApp state update console.log('Trying to update deployed zkApp state.'); -transaction = await Mina.transaction({ sender, fee: transactionFee }, () => { - zkApp.update(Field(4), adminPrivateKey); -}); +transaction = await Mina.transaction( + { sender, fee: transactionFee }, + async () => { + zkApp.update(Field(4), adminPrivateKey); + } +); await transaction.sign([senderKey]).prove(); console.log('Sending the transaction.'); pendingTx = await transaction.send(); diff --git a/src/examples/zkapps/hello-world/run.ts b/src/examples/zkapps/hello-world/run.ts index da37518357..61903c5224 100644 --- a/src/examples/zkapps/hello-world/run.ts +++ b/src/examples/zkapps/hello-world/run.ts @@ -23,7 +23,7 @@ const zkAppInstance = new HelloWorld(zkAppAddress); console.log('Deploying Hello World ....'); -txn = await Mina.transaction(feePayer1.publicKey, () => { +txn = await Mina.transaction(feePayer1.publicKey, async () => { AccountUpdate.fundNewAccount(feePayer1.publicKey); zkAppInstance.deploy(); }); @@ -41,7 +41,7 @@ console.log( `Updating state from ${initialState} to 4 with Admin Private Key ...` ); -txn = await Mina.transaction(feePayer1.publicKey, () => { +txn = await Mina.transaction(feePayer1.publicKey, async () => { zkAppInstance.update(Field(4), adminPrivateKey); }); await txn.prove(); @@ -66,7 +66,7 @@ console.log( let correctlyFails = false; try { - txn = await Mina.transaction(feePayer1.publicKey, () => { + txn = await Mina.transaction(feePayer1.publicKey, async () => { zkAppInstance.update(Field(16), wrongAdminPrivateKey); }); await txn.prove(); @@ -87,7 +87,7 @@ try { `Attempting to update state from ${currentState} to the value that fails precondition of 30 ...` ); - txn = await Mina.transaction(feePayer1.publicKey, () => { + txn = await Mina.transaction(feePayer1.publicKey, async () => { zkAppInstance.update(Field(30), adminPrivateKey); }); await txn.prove(); @@ -113,7 +113,7 @@ try { // expected to fail and current state stays at 4 txn = await Mina.transaction( { sender: feePayer1.publicKey, fee: '10' }, - () => { + async () => { zkAppInstance.update(Field(256), adminPrivateKey); } ); @@ -130,9 +130,12 @@ if (!correctlyFails) { } // expected to succeed and update state to 16 -txn2 = await Mina.transaction({ sender: feePayer2.publicKey, fee: '2' }, () => { - zkAppInstance.update(Field(16), adminPrivateKey); -}); +txn2 = await Mina.transaction( + { sender: feePayer2.publicKey, fee: '2' }, + async () => { + zkAppInstance.update(Field(16), adminPrivateKey); + } +); await txn2.prove(); await txn2.sign([feePayer2.privateKey]).sendOrThrowIfError(); @@ -147,9 +150,12 @@ if (currentState !== '16') { console.log(`Update successful. Current state is ${currentState}.`); // expected to succeed and update state to 256 -txn3 = await Mina.transaction({ sender: feePayer3.publicKey, fee: '1' }, () => { - zkAppInstance.update(Field(256), adminPrivateKey); -}); +txn3 = await Mina.transaction( + { sender: feePayer3.publicKey, fee: '1' }, + async () => { + zkAppInstance.update(Field(256), adminPrivateKey); + } +); await txn3.prove(); await txn3.sign([feePayer3.privateKey]).sendOrThrowIfError(); @@ -169,7 +175,7 @@ try { // expected to fail and current state remains 256 txn4 = await Mina.transaction( { sender: feePayer4.publicKey, fee: '1' }, - () => { + async () => { zkAppInstance.update(Field(16), adminPrivateKey); } ); diff --git a/src/examples/zkapps/local-events-zkapp.ts b/src/examples/zkapps/local-events-zkapp.ts index 993ed31e1a..f47bb6713b 100644 --- a/src/examples/zkapps/local-events-zkapp.ts +++ b/src/examples/zkapps/local-events-zkapp.ts @@ -65,21 +65,21 @@ if (doProofs) { } console.log('deploy'); -let tx = await Mina.transaction(feePayer, () => { +let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); zkapp.deploy(); }); await tx.sign([feePayerKey, zkappKey]).send(); console.log('call update'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.update(Field(1)); }); await tx.prove(); await tx.sign([feePayerKey]).send(); console.log('call update'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.update(Field(2)); }); await tx.prove(); diff --git a/src/examples/zkapps/merkle-tree/merkle-zkapp.ts b/src/examples/zkapps/merkle-tree/merkle-zkapp.ts index 3bcb1bfa22..923fb3ac53 100644 --- a/src/examples/zkapps/merkle-tree/merkle-zkapp.ts +++ b/src/examples/zkapps/merkle-tree/merkle-zkapp.ts @@ -133,7 +133,7 @@ console.log('Deploying leaderboard..'); if (doProofs) { await Leaderboard.compile(); } -let tx = await Mina.transaction(feePayer, () => { +let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer).send({ to: zkappAddress, amount: initialBalance, @@ -155,7 +155,7 @@ async function makeGuess(name: Names, index: bigint, guess: number) { let w = Tree.getWitness(index); let witness = new MyMerkleWitness(w); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { leaderboardZkApp.guessPreimage(Field(guess), account, witness); }); await tx.prove(); diff --git a/src/examples/zkapps/reducer/actions-as-merkle-list.ts b/src/examples/zkapps/reducer/actions-as-merkle-list.ts index 1740de72b1..1cd52da348 100644 --- a/src/examples/zkapps/reducer/actions-as-merkle-list.ts +++ b/src/examples/zkapps/reducer/actions-as-merkle-list.ts @@ -121,12 +121,12 @@ console.log( `rows for ${MAX_UPDATES_WITH_ACTIONS} updates with actions`, (await ActionsContract.analyzeMethods()).assertContainsAddress.rows ); -let deployTx = await Mina.transaction(sender, () => zkapp.deploy()); +let deployTx = await Mina.transaction(sender, async () => zkapp.deploy()); await deployTx.sign([senderKey, zkappKey]).send(); // push some actions -let dispatchTx = await Mina.transaction(sender, () => { +let dispatchTx = await Mina.transaction(sender, async () => { zkapp.postAddress(otherAddress); zkapp.postAddress(zkappAddress); zkapp.postTwoAddresses(anotherAddress, sender); @@ -141,7 +141,7 @@ assert(zkapp.reducer.getActions().length === 5); // check if the actions contain the `sender` address Local.setProofsEnabled(true); -let containsTx = await Mina.transaction(sender, () => +let containsTx = await Mina.transaction(sender, async () => zkapp.assertContainsAddress(sender) ); await containsTx.prove(); diff --git a/src/examples/zkapps/reducer/map.ts b/src/examples/zkapps/reducer/map.ts index 8619d9c347..bda597997b 100644 --- a/src/examples/zkapps/reducer/map.ts +++ b/src/examples/zkapps/reducer/map.ts @@ -103,7 +103,7 @@ let zkapp = new StorageContract(zkappAddress); await StorageContract.compile(); -let tx = await Mina.transaction(feePayer, () => { +let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); zkapp.deploy(); }); @@ -130,7 +130,7 @@ let key = map[0].key; let value = map[0].value; console.log(`setting key ${key.toBase58()} with value ${value}`); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.set(key, value); }); await tx.prove(); @@ -140,7 +140,7 @@ key = map[1].key; value = map[1].value; console.log(`setting key ${key.toBase58()} with value ${value}`); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.set(key, value); }); await tx.prove(); @@ -150,7 +150,7 @@ key = map[2].key; value = map[2].value; console.log(`setting key ${key.toBase58()} with value ${value}`); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.set(key, value); }); await tx.prove(); @@ -161,7 +161,7 @@ value = map[0].value; console.log(`getting key ${key.toBase58()} with value ${value}`); let result: any; -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { result = zkapp.get(key); }); await tx.prove(); @@ -174,7 +174,7 @@ key = map[1].key; value = map[1].value; console.log(`getting key ${key.toBase58()} with value ${value}`); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { result = zkapp.get(key); }); await tx.prove(); @@ -184,7 +184,7 @@ console.log('found correct match?', result.isSome.toBoolean()); console.log('matches expected value?', result.value.equals(value).toBoolean()); console.log(`getting key invalid key`); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { result = zkapp.get(PrivateKey.random().toPublicKey()); }); await tx.prove(); diff --git a/src/examples/zkapps/reducer/reducer-composite.ts b/src/examples/zkapps/reducer/reducer-composite.ts index 1ecdc26ef7..3bdccd7e59 100644 --- a/src/examples/zkapps/reducer/reducer-composite.ts +++ b/src/examples/zkapps/reducer/reducer-composite.ts @@ -92,7 +92,7 @@ if (doProofs) { } console.log('deploy'); -let tx = await Mina.transaction(feePayer, () => { +let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); zkapp.deploy(); zkapp.counter.set(initialCounter); @@ -104,21 +104,21 @@ console.log('applying actions..'); console.log('action 1'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.incrementCounter(); }); await tx.prove(); await tx.sign([feePayerKey]).send(); console.log('action 2'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.incrementCounter(); }); await tx.prove(); await tx.sign([feePayerKey]).send(); console.log('action 3'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.incrementCounter(); }); await tx.prove(); @@ -128,7 +128,7 @@ console.log('rolling up pending actions..'); console.log('state before: ' + zkapp.counter.get()); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.rollupIncrements(); }); await tx.prove(); @@ -140,14 +140,14 @@ assert.deepEqual(zkapp.counter.get().toString(), '3'); console.log('applying more actions'); console.log('action 4 (no increment)'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.dispatchData(Field.random()); }); await tx.prove(); await tx.sign([feePayerKey]).send(); console.log('action 5'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.incrementCounter(); }); await tx.prove(); @@ -157,7 +157,7 @@ console.log('rolling up pending actions..'); console.log('state before: ' + zkapp.counter.get()); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.rollupIncrements(); }); await tx.prove(); diff --git a/src/examples/zkapps/reducer/reducer.ts b/src/examples/zkapps/reducer/reducer.ts index d5aed207b4..6d23123ada 100644 --- a/src/examples/zkapps/reducer/reducer.ts +++ b/src/examples/zkapps/reducer/reducer.ts @@ -87,7 +87,7 @@ if (doProofs) { } console.log('deploy'); -let tx = await Mina.transaction(feePayer, () => { +let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); zkapp.deploy(); zkapp.counter.set(initialCounter); @@ -99,21 +99,21 @@ console.log('applying actions..'); console.log('action 1'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.incrementCounter(); }); await tx.prove(); await tx.sign([feePayerKey]).send(); console.log('action 2'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.incrementCounter(); }); await tx.prove(); await tx.sign([feePayerKey]).send(); console.log('action 3'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.incrementCounter(); }); await tx.prove(); @@ -123,7 +123,7 @@ console.log('rolling up pending actions..'); console.log('state before: ' + zkapp.counter.get()); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.rollupIncrements(); }); await tx.prove(); @@ -134,14 +134,14 @@ console.log('state after rollup: ' + zkapp.counter.get()); console.log('applying more actions'); console.log('action 4'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.incrementCounter(); }); await tx.prove(); await tx.sign([feePayerKey]).send(); console.log('action 5'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.incrementCounter(); }); await tx.prove(); @@ -151,7 +151,7 @@ console.log('rolling up pending actions..'); console.log('state before: ' + zkapp.counter.get()); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.rollupIncrements(); }); await tx.prove(); diff --git a/src/examples/zkapps/set-local-preconditions-zkapp.ts b/src/examples/zkapps/set-local-preconditions-zkapp.ts index 2b11b2a494..8318e7f2ba 100644 --- a/src/examples/zkapps/set-local-preconditions-zkapp.ts +++ b/src/examples/zkapps/set-local-preconditions-zkapp.ts @@ -51,7 +51,7 @@ if (doProofs) { } console.log('deploy'); -let tx = await Mina.transaction(feePayer, () => { +let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); zkapp.deploy(); }); @@ -60,7 +60,7 @@ await tx.sign([feePayerKey, zkappKey]).send(); let blockHeight: UInt32 = UInt32.zero; console.log('assert block height 0'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { // block height starts at 0 zkapp.blockheightEquals(UInt32.from(blockHeight)); }); @@ -71,7 +71,7 @@ blockHeight = UInt32.from(500); Local.setBlockchainLength(blockHeight); console.log('assert block height 500'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.blockheightEquals(UInt32.from(blockHeight)); }); await tx.prove(); @@ -81,7 +81,7 @@ blockHeight = UInt32.from(300); Local.setBlockchainLength(UInt32.from(5)); console.log('invalid block height precondition'); try { - tx = await Mina.transaction(feePayer, () => { + tx = await Mina.transaction(feePayer, async () => { zkapp.blockheightEquals(UInt32.from(blockHeight)); }); await tx.prove(); diff --git a/src/examples/zkapps/simple-zkapp-payment.ts b/src/examples/zkapps/simple-zkapp-payment.ts index 2fe6f4d215..afd4bd96c2 100644 --- a/src/examples/zkapps/simple-zkapp-payment.ts +++ b/src/examples/zkapps/simple-zkapp-payment.ts @@ -67,7 +67,7 @@ let zkapp = new SendMINAExample(zkappAddress); let tx; console.log('deploy and fund user accounts'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { let feePayerUpdate = AccountUpdate.fundNewAccount(feePayer, 3); feePayerUpdate.send({ to: account1Address, amount: 2e9 }); feePayerUpdate.send({ to: account2Address, amount: 0 }); // just touch account #2, so it's created @@ -77,7 +77,7 @@ await tx.sign([feePayerKey, zkappKey]).send(); printBalances(); console.log('---------- deposit MINA into zkApp (with proof) ----------'); -tx = await Mina.transaction(account1Address, () => { +tx = await Mina.transaction(account1Address, async () => { zkapp.deposit(UInt64.from(1e9)); }); await tx.prove(); @@ -85,7 +85,7 @@ await tx.sign([account1Key]).send(); printBalances(); console.log('---------- send MINA from zkApp (with proof) ----------'); -tx = await Mina.transaction(account1Address, () => { +tx = await Mina.transaction(account1Address, async () => { zkapp.withdraw(UInt64.from(1e9)); }); await tx.prove(); @@ -95,7 +95,7 @@ printBalances(); console.log( '---------- send MINA between accounts (with signature) ----------' ); -tx = await Mina.transaction(account1Address, () => { +tx = await Mina.transaction(account1Address, async () => { let account1Update = AccountUpdate.createSigned(account1Address); account1Update.send({ to: account2Address, amount: 1e9 }); }); diff --git a/src/examples/zkapps/simple-zkapp-with-proof.ts b/src/examples/zkapps/simple-zkapp-with-proof.ts index 8fbfaeee59..4d4ccb91ac 100644 --- a/src/examples/zkapps/simple-zkapp-with-proof.ts +++ b/src/examples/zkapps/simple-zkapp-with-proof.ts @@ -67,7 +67,7 @@ let { verificationKey: trivialVerificationKey } = await TrivialZkapp.compile(); // would also improve the return type -- `Proof` instead of `(Proof | undefined)[]` console.log('prove (trivial zkapp)'); let [trivialProof] = await ( - await Mina.transaction(feePayer, () => { + await Mina.transaction(feePayer, async () => { new TrivialZkapp(zkappAddress2).proveSomething(Field(1)); }) ).prove(); @@ -84,7 +84,7 @@ let { verificationKey } = await NotSoSimpleZkapp.compile(); let zkapp = new NotSoSimpleZkapp(zkappAddress); console.log('deploy'); -let tx = await Mina.transaction(feePayer, () => { +let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer); zkapp.deploy({ zkappKey }); }); @@ -92,7 +92,7 @@ await tx.prove(); await tx.sign([feePayerKey]).send(); console.log('initialize'); -tx = await Mina.transaction(feePayerKey, () => { +tx = await Mina.transaction(feePayerKey, async () => { zkapp.initialize(trivialProof!); }); let [proof] = await tx.prove(); @@ -107,7 +107,7 @@ proof = await testJsonRoundtripAndVerify( console.log('initial state: ' + zkapp.x.get()); console.log('update'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.update(Field(3), proof!, trivialProof!); }); [proof] = await tx.prove(); @@ -122,7 +122,7 @@ proof = await testJsonRoundtripAndVerify( console.log('state 2: ' + zkapp.x.get()); console.log('update'); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { zkapp.update(Field(3), proof!, trivialProof!); }); [proof] = await tx.prove(); diff --git a/src/examples/zkapps/sudoku/index.ts b/src/examples/zkapps/sudoku/index.ts index c626f175c2..33b4bbfdd1 100644 --- a/src/examples/zkapps/sudoku/index.ts +++ b/src/examples/zkapps/sudoku/index.ts @@ -21,7 +21,7 @@ console.log( console.log('Deploying and initializing Sudoku...'); await SudokuZkApp.compile(); -let tx = await Mina.transaction(account, () => { +let tx = await Mina.transaction(account, async () => { AccountUpdate.fundNewAccount(account); zkApp.deploy(); zkApp.update(Sudoku.from(sudoku)); @@ -47,7 +47,7 @@ noSolution[0][0] = (noSolution[0][0] % 9) + 1; console.log('Submitting wrong solution...'); try { - let tx = await Mina.transaction(account, () => { + let tx = await Mina.transaction(account, async () => { zkApp.submitSolution(Sudoku.from(sudoku), Sudoku.from(noSolution)); }); await tx.prove(); @@ -59,7 +59,7 @@ console.log('Is the sudoku solved?', zkApp.isSolved.get().toBoolean()); // submit the actual solution console.log('Submitting solution...'); -tx = await Mina.transaction(account, () => { +tx = await Mina.transaction(account, async () => { zkApp.submitSolution(Sudoku.from(sudoku), Sudoku.from(solution!)); }); await tx.prove(); diff --git a/src/examples/zkapps/token-with-proofs.ts b/src/examples/zkapps/token-with-proofs.ts index 6ce61bc301..ba82f6b082 100644 --- a/src/examples/zkapps/token-with-proofs.ts +++ b/src/examples/zkapps/token-with-proofs.ts @@ -79,7 +79,7 @@ console.log('compile (ZkAppC)'); await ZkAppC.compile(); console.log('deploy tokenZkApp'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { tokenZkApp.deploy(); AccountUpdate.fundNewAccount(sender).send({ to: tokenZkApp.self, @@ -89,7 +89,7 @@ tx = await Mina.transaction(sender, () => { await tx.sign([senderKey, tokenZkAppKey]).send(); console.log('deploy zkAppB and zkAppC'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { AccountUpdate.fundNewAccount(sender, 2); zkAppC.deploy(); zkAppB.deploy(); @@ -100,14 +100,14 @@ await tx.prove(); await tx.sign([senderKey, zkAppBKey, zkAppCKey]).send(); console.log('mint token to zkAppB'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { tokenZkApp.mint(zkAppBAddress); }); await tx.prove(); await tx.sign([senderKey]).send(); console.log('approve send from zkAppB'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { zkAppB.approveSend(); // we call the token contract with the self update @@ -123,7 +123,7 @@ console.log( ); console.log('approve send from zkAppC'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { // Pay for tokenAccount1's account creation AccountUpdate.fundNewAccount(sender); zkAppC.approveSend(); diff --git a/src/examples/zkapps/voting/demo.ts b/src/examples/zkapps/voting/demo.ts index bb2ca126a0..30f6b303e5 100644 --- a/src/examples/zkapps/voting/demo.ts +++ b/src/examples/zkapps/voting/demo.ts @@ -66,7 +66,7 @@ let candidateStore = new OffchainStorage(3); let votesStore = new OffchainStorage(3); let initialRoot = voterStore.getRoot(); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer, 3); contracts.voting.deploy({ zkappKey: votingKey }); @@ -87,7 +87,7 @@ await tx.sign([feePayerKey]).send(); let m: Member = Member.empty(); // lets register three voters -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { // creating and registering a new voter m = registerMember( /* @@ -107,7 +107,7 @@ await tx.prove(); await tx.sign([feePayerKey]).send(); // lets register three voters -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { // creating and registering a new voter m = registerMember( /* @@ -128,7 +128,7 @@ await tx.prove(); await tx.sign([feePayerKey]).send(); // lets register three voters -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { // creating and registering a new voter m = registerMember( /* @@ -163,7 +163,7 @@ console.log( Lets register two candidates */ -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { // creating and registering 1 new candidate let m = registerMember( /* @@ -183,7 +183,7 @@ tx = await Mina.transaction(feePayer, () => { await tx.prove(); await tx.sign([feePayerKey]).send(); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { // creating and registering 1 new candidate let m = registerMember( /* @@ -238,7 +238,7 @@ console.log( both the on-chain committedMembers variable and the off-chain merkle tree root need to be equal */ -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { contracts.voting.approveRegistrations(); if (!params.doProofs) contracts.voting.sign(votingKey); }); @@ -270,7 +270,7 @@ console.log( */ // we have to up the slot so we are within our election period Local.incrementGlobalSlot(5); -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { let c = candidateStore.get(0n)!; c.witness = new MyMerkleWitness(candidateStore.getWitness(0n)); c.votesWitness = new MyMerkleWitness(votesStore.getWitness(0n)); @@ -294,7 +294,7 @@ console.log( /* counting the votes */ -tx = await Mina.transaction(feePayer, () => { +tx = await Mina.transaction(feePayer, async () => { contracts.voting.countVotes(); if (!params.doProofs) contracts.voting.sign(votingKey); }); diff --git a/src/examples/zkapps/voting/deploy-contracts.ts b/src/examples/zkapps/voting/deploy-contracts.ts index 97ba6fffa5..1a1a0ec9fb 100644 --- a/src/examples/zkapps/voting/deploy-contracts.ts +++ b/src/examples/zkapps/voting/deploy-contracts.ts @@ -63,7 +63,7 @@ export async function deployContracts( let { voterContract, candidateContract, voting } = contracts; console.log('deploying set of 3 contracts'); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer, 3); voting.deploy({ zkappKey: params.votingKey }); @@ -127,7 +127,7 @@ export async function deployInvalidContracts( let { voterContract, candidateContract, voting } = contracts; console.log('deploying set of 3 contracts'); - let tx = await Mina.transaction(feePayer, () => { + let tx = await Mina.transaction(feePayer, async () => { AccountUpdate.fundNewAccount(feePayer, 3); voting.deploy({ zkappKey: params.votingKey }); diff --git a/src/examples/zkapps/voting/run-berkeley.ts b/src/examples/zkapps/voting/run-berkeley.ts index f8b7c1e426..caa62d02ed 100644 --- a/src/examples/zkapps/voting/run-berkeley.ts +++ b/src/examples/zkapps/voting/run-berkeley.ts @@ -91,7 +91,7 @@ let tx = await Mina.transaction( fee: 10_000_000, memo: 'Deploying contracts', }, - () => { + async () => { AccountUpdate.fundNewAccount(feePayerAddress, 3); contracts.voting.deploy({ zkappKey: params.votingKey }); @@ -125,7 +125,7 @@ tx = await Mina.transaction( fee: 10_000_000, memo: 'Registering a voter', }, - () => { + async () => { let m = registerMember( 0n, Member.from(members[0], UInt64.from(150)), @@ -147,7 +147,7 @@ tx = await Mina.transaction( fee: 10_000_000, memo: 'Registering a candidate', }, - () => { + async () => { let m = registerMember( 0n, Member.from(members[1], UInt64.from(150)), @@ -171,7 +171,7 @@ tx = await Mina.transaction( fee: 10_000_000, memo: 'Approving registrations', }, - () => { + async () => { contracts.voting.approveRegistrations(); } ); @@ -184,7 +184,7 @@ await fetchAllAccounts(); console.log('voting for a candidate'); tx = await Mina.transaction( { sender: feePayerAddress, fee: 10_000_000, memo: 'Casting vote' }, - () => { + async () => { let currentCandidate = storage.candidatesStore.get(0n)!; currentCandidate.witness = new MyMerkleWitness( @@ -212,7 +212,7 @@ await fetchAllAccounts(); console.log('counting votes'); tx = await Mina.transaction( { sender: feePayerAddress, fee: 10_000_000, memo: 'Counting votes' }, - () => { + async () => { contracts.voting.countVotes(); } ); diff --git a/src/examples/zkapps/voting/test.ts b/src/examples/zkapps/voting/test.ts index 7253c1d715..dc0081adaf 100644 --- a/src/examples/zkapps/voting/test.ts +++ b/src/examples/zkapps/voting/test.ts @@ -84,7 +84,7 @@ export async function testSet( await assertValidTx( true, - () => { + async () => { verificationKeySet.voting.voterRegistration(m); }, verificationKeySet.feePayer @@ -95,7 +95,7 @@ export async function testSet( await assertValidTx( true, - () => { + async () => { let vkUpdate = AccountUpdate.createSigned(params.votingKey); vkUpdate.account.verificationKey.set({ ...verificationKey, @@ -110,7 +110,7 @@ export async function testSet( await assertValidTx( false, - () => { + async () => { verificationKeySet.voting.voterRegistration(m); }, verificationKeySet.feePayer, @@ -156,7 +156,7 @@ export async function testSet( await assertValidTx( true, - () => { + async () => { permissionedSet.voting.voterRegistration(m); }, permissionedSet.feePayer @@ -166,7 +166,7 @@ export async function testSet( await assertValidTx( true, - () => { + async () => { let permUpdate = AccountUpdate.createSigned(params.voterKey); permUpdate.account.permissions.set({ @@ -185,7 +185,7 @@ export async function testSet( await assertValidTx( false, - () => { + async () => { permissionedSet.voting.voterRegistration(m); }, permissionedSet.feePayer, @@ -228,9 +228,12 @@ export async function testSet( invalidSet.Local.addAccount(m.publicKey, m.balance.toString()); try { - let tx = await Mina.transaction(invalidSet.feePayer.toPublicKey(), () => { - invalidSet.voting.voterRegistration(m); - }); + let tx = await Mina.transaction( + invalidSet.feePayer.toPublicKey(), + async () => { + invalidSet.voting.voterRegistration(m); + } + ); await tx.prove(); await tx.sign([invalidSet.feePayer]).send(); } catch (err: any) { @@ -279,7 +282,7 @@ export async function testSet( try { let tx = await Mina.transaction( sequenceOverflowSet.feePayer.toPublicKey(), - () => { + async () => { let m = Member.from( PrivateKey.random().toPublicKey(), @@ -311,7 +314,7 @@ export async function testSet( try { let tx = await Mina.transaction( sequenceOverflowSet.feePayer.toPublicKey(), - () => { + async () => { sequenceOverflowSet.voting.approveRegistrations(); } ); @@ -381,7 +384,7 @@ export async function testSet( await assertValidTx( true, - () => { + async () => { voting.voterRegistration(newVoter1); }, feePayer @@ -437,7 +440,7 @@ export async function testSet( await assertValidTx( false, - () => { + async () => { voting.voterRegistration(newVoterLow); }, feePayer, @@ -453,7 +456,7 @@ export async function testSet( await assertValidTx( false, - () => { + async () => { voting.voterRegistration(newVoterHigh); }, feePayer, @@ -464,7 +467,7 @@ export async function testSet( await assertValidTx( false, - () => { + async () => { voting.voterRegistration(newVoter1); }, feePayer, @@ -500,7 +503,7 @@ export async function testSet( await assertValidTx( true, - () => { + async () => { let newCandidate = registerMember( 0n, Member.from( @@ -522,7 +525,7 @@ export async function testSet( await assertValidTx( true, - () => { + async () => { let newCandidate = registerMember( 1n, Member.from( @@ -579,7 +582,7 @@ export async function testSet( await assertValidTx( true, - () => { + async () => { // register new candidate voting.approveRegistrations(); }, @@ -647,7 +650,7 @@ export async function testSet( await assertValidTx( false, - () => { + async () => { // register late candidate voting.candidateRegistration(lateCandidate); }, @@ -667,7 +670,7 @@ export async function testSet( await assertValidTx( false, - () => { + async () => { // register late voter voting.voterRegistration(lateVoter); }, @@ -725,7 +728,7 @@ export async function testSet( let beforeCommitted = voting.committedVotes.get(); await assertValidTx( true, - () => { + async () => { voting.countVotes(); }, feePayer @@ -761,7 +764,7 @@ export async function testSet( await assertValidTx( true, - () => { + async () => { // attempting to vote for the registered candidate currentCandidate = candidatesStore.get(0n)!; currentCandidate.witness = new MyMerkleWitness( @@ -816,7 +819,7 @@ export async function testSet( await assertValidTx( false, - () => { + async () => { // attempting to vote for the registered candidate voting.vote(fakeCandidate, votersStore.get(0n)!); @@ -835,7 +838,7 @@ export async function testSet( await assertValidTx( false, - () => { + async () => { voting.vote(fakeVoter, votersStore.get(0n)!); }, feePayer, @@ -846,7 +849,7 @@ export async function testSet( await assertValidTx( false, - () => { + async () => { const voter = votersStore.get(0n)!; voting.vote(voter, votersStore.get(0n)!); }, @@ -874,7 +877,7 @@ export async function testSet( await assertValidTx( true, - () => { + async () => { voting.countVotes(); }, feePayer @@ -927,7 +930,7 @@ export async function testSet( await assertValidTx( false, - () => { + async () => { voting.voterRegistration(voter); }, feePayer, @@ -944,7 +947,7 @@ export async function testSet( await assertValidTx( false, - () => { + async () => { voting.candidateRegistration(candidate); }, feePayer, diff --git a/src/examples/zkapps/voting/voting-lib.ts b/src/examples/zkapps/voting/voting-lib.ts index af6cb62e20..a3e90c5192 100644 --- a/src/examples/zkapps/voting/voting-lib.ts +++ b/src/examples/zkapps/voting/voting-lib.ts @@ -72,7 +72,7 @@ export function getResults( */ export async function assertValidTx( expectToBeValid: boolean, - cb: () => void, + cb: () => Promise, feePayer: PrivateKey, msg?: string ) { diff --git a/src/examples/zkapps/zkapp-self-update.ts b/src/examples/zkapps/zkapp-self-update.ts index d2964fa331..0ee45ce3f5 100644 --- a/src/examples/zkapps/zkapp-self-update.ts +++ b/src/examples/zkapps/zkapp-self-update.ts @@ -57,7 +57,7 @@ const { privateKey: deployerKey, publicKey: deployerAccount } = await Foo.compile(); -const tx = await Mina.transaction(deployerAccount, () => { +const tx = await Mina.transaction(deployerAccount, async () => { AccountUpdate.fundNewAccount(deployerAccount); zkApp.deploy(); }); @@ -71,7 +71,7 @@ Provable.log('original verification key', fooVerificationKey); const { verificationKey: barVerificationKey } = await Bar.compile(); -const tx2 = await Mina.transaction(deployerAccount, () => { +const tx2 = await Mina.transaction(deployerAccount, async () => { zkApp.replaceVerificationKey(barVerificationKey); }); await tx2.prove(); diff --git a/src/lib/zkapp.ts b/src/lib/zkapp.ts index b20c25045a..33761c64e5 100644 --- a/src/lib/zkapp.ts +++ b/src/lib/zkapp.ts @@ -653,7 +653,7 @@ class SmartContract extends SmartContractBase { * Deploys a {@link SmartContract}. * * ```ts - * let tx = await Mina.transaction(sender, () => { + * let tx = await Mina.transaction(sender, async () => { * AccountUpdate.fundNewAccount(sender); * zkapp.deploy(); * }); diff --git a/src/tests/fake-proof.ts b/src/tests/fake-proof.ts index 3607494be1..0490d69f9e 100644 --- a/src/tests/fake-proof.ts +++ b/src/tests/fake-proof.ts @@ -70,7 +70,7 @@ for (let proof of [fakeProof, dummyProof]) { // contract rejects proof await assert.rejects(async () => { - let tx = await Mina.transaction(() => zkApp.verifyReal(proof)); + let tx = await Mina.transaction(async () => zkApp.verifyReal(proof)); await tx.prove(); }, 'recursive contract rejects fake proof'); } @@ -86,7 +86,7 @@ assert( ); // contract accepts proof -let tx = await Mina.transaction(() => zkApp.verifyReal(realProof)); +let tx = await Mina.transaction(async () => zkApp.verifyReal(realProof)); let [contractProof] = await tx.prove(); assert( await verify(contractProof!, contractVk.data), diff --git a/src/tests/transaction-flow.ts b/src/tests/transaction-flow.ts index 90a3721d74..d0d1fd3987 100644 --- a/src/tests/transaction-flow.ts +++ b/src/tests/transaction-flow.ts @@ -146,7 +146,7 @@ console.log(''); console.log('Testing network auxiliary functions do not throw'); await testLocalAndRemote(async () => { await assert.doesNotReject(async () => { - await Mina.transaction({ sender, fee: transactionFee }, () => { + await Mina.transaction({ sender, fee: transactionFee }, async () => { Mina.getNetworkConstants(); Mina.getNetworkState(); Mina.getNetworkId(); @@ -177,7 +177,7 @@ await testLocalAndRemote(async () => { await assert.doesNotReject(async () => { const transaction = await Mina.transaction( { sender, fee: transactionFee }, - () => { + async () => { zkApp.deploy({ verificationKey }); } ); @@ -194,7 +194,7 @@ await testLocalAndRemote(async () => { await assert.doesNotReject(async () => { const transaction = await Mina.transaction( { sender, fee: transactionFee }, - () => { + async () => { zkApp.update(Field(1), PrivateKey.random().toPublicKey()); } ); @@ -213,7 +213,7 @@ await testLocalAndRemote(async () => { await assert.doesNotReject(async () => { const transaction = await Mina.transaction( { sender, fee: transactionFee }, - () => { + async () => { zkApp.update(Field(1), PrivateKey.random().toPublicKey()); } ); @@ -234,7 +234,7 @@ console.log( await testLocalAndRemote(async () => { const transaction = await Mina.transaction( { sender, fee: transactionFee }, - () => { + async () => { AccountUpdate.fundNewAccount(zkAppAddress); zkApp.update(Field(1), PrivateKey.random().toPublicKey()); } @@ -252,7 +252,7 @@ await testLocalAndRemote(async () => { await assert.rejects(async () => { const transaction = await Mina.transaction( { sender, fee: transactionFee }, - () => { + async () => { AccountUpdate.fundNewAccount(zkAppAddress); zkApp.update(Field(1), PrivateKey.random().toPublicKey()); } @@ -268,7 +268,7 @@ await testLocalAndRemote(async () => { try { let transaction = await Mina.transaction( { sender, fee: transactionFee }, - () => { + async () => { zkApp.incrementCounter(); } ); @@ -277,7 +277,7 @@ await testLocalAndRemote(async () => { transaction = await Mina.transaction( { sender, fee: transactionFee }, - () => { + async () => { zkApp.rollupIncrements(); } ); @@ -286,7 +286,7 @@ await testLocalAndRemote(async () => { transaction = await Mina.transaction( { sender, fee: transactionFee }, - () => { + async () => { zkApp.incrementCounter(); zkApp.incrementCounter(); zkApp.incrementCounter(); @@ -299,7 +299,7 @@ await testLocalAndRemote(async () => { transaction = await Mina.transaction( { sender, fee: transactionFee }, - () => { + async () => { zkApp.rollupIncrements(); } ); diff --git a/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js b/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js index 22f7dc0f54..636efac328 100644 --- a/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js +++ b/tests/artifacts/javascript/on-chain-state-mgmt-zkapp-ui.js @@ -44,7 +44,7 @@ deployButton.addEventListener('click', async () => { try { await HelloWorld.compile(); - const deploymentTransaction = await Mina.transaction(feePayer, () => { + const deploymentTransaction = await Mina.transaction(feePayer, async () => { if (!eventsContainer.innerHTML.includes('zkApp Deployed successfully')) { AccountUpdate.fundNewAccount(feePayer); } @@ -84,7 +84,7 @@ updateButton.addEventListener('click', async (event) => { `Updating zkApp State from ${currentState} to ${zkAppStateValue.value} with Admin Private Key and using form data: ${formData}...`, eventsContainer ); - const transaction = await Mina.transaction(feePayer, () => { + const transaction = await Mina.transaction(feePayer, async () => { zkAppInstance.update( Field(parseInt(zkAppStateValue.value)), adminPrivateKey diff --git a/tests/integration/simple-zkapp-mock-apply.js b/tests/integration/simple-zkapp-mock-apply.js index a5edb82849..fc45e436c6 100644 --- a/tests/integration/simple-zkapp-mock-apply.js +++ b/tests/integration/simple-zkapp-mock-apply.js @@ -66,7 +66,7 @@ let { verificationKey } = await SimpleZkapp.compile(); toc(); tic('create deploy transaction (with proof)'); -let deployTx = await Mina.transaction(sender, () => { +let deployTx = await Mina.transaction(sender, async () => { AccountUpdate.fundNewAccount(sender); zkapp.deploy(); }); @@ -90,7 +90,7 @@ zkappState.assertEquals(1); console.log('got initial state: ' + zkappState); tic('create update transaction (no proof)'); -let tx = await Mina.transaction(sender, () => { +let tx = await Mina.transaction(sender, async () => { zkapp.update(Field(2)); zkapp.requireSignature(); }); @@ -107,7 +107,7 @@ zkappState.assertEquals(3); console.log('got updated state: ' + zkappState); tic('create update transaction (with proof)'); -tx = await Mina.transaction(sender, () => { +tx = await Mina.transaction(sender, async () => { zkapp.update(Field(2)); }); [proof] = await tx.prove(); diff --git a/tests/integration/simple-zkapp.js b/tests/integration/simple-zkapp.js index 5df6113c3d..75f46601d6 100644 --- a/tests/integration/simple-zkapp.js +++ b/tests/integration/simple-zkapp.js @@ -138,7 +138,7 @@ await NotSoSimpleZkapp.compile(); console.log('deploying contract\n'); let tx = await Mina.transaction( { sender: feePayerAddress, fee: 100_000_000 }, - () => { + async () => { AccountUpdate.fundNewAccount(feePayerAddress); zkapp.deploy(); @@ -159,7 +159,7 @@ expectAssertEquals(zkappAccount.balance, UInt64.from(0)); console.log('deposit funds\n'); tx = await Mina.transaction( { sender: feePayerAddress, fee: 100_000_000 }, - () => { + async () => { zkapp.deposit(UInt64.from(initialBalance)); } ); @@ -175,7 +175,7 @@ expectAssertEquals(zkappAccount.balance, UInt64.from(initialBalance)); console.log('update 1\n'); tx = await Mina.transaction( { sender: feePayerAddress, fee: 100_000_000 }, - () => { + async () => { zkapp.update(Field(30)); } ); @@ -185,7 +185,7 @@ await (await tx.sign([feePayerKey]).send()).wait(waitParams); console.log('update 2\n'); tx = await Mina.transaction( { sender: feePayerAddress, fee: 100_000_000 }, - () => { + async () => { zkapp.update(Field(100)); } ); @@ -204,7 +204,7 @@ expectAssertEquals(zkappAccount.zkapp.appState[0], Field(131)); console.log('payout 1\n'); tx = await Mina.transaction( { sender: feePayerAddress, fee: 100_000_000 }, - () => { + async () => { AccountUpdate.fundNewAccount(feePayerAddress); zkapp.payout(privilegedKey); } @@ -221,7 +221,7 @@ expectAssertEquals(zkappAccount.balance, UInt64.from(initialBalance / 2)); console.log('payout 2 (expected to fail)\n'); tx = await Mina.transaction( { sender: feePayerAddress, fee: 100_000_000 }, - () => { + async () => { zkapp.payout(privilegedKey); } ); From 86992b63e911324971252cd04670b0c2a189f637 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 29 Feb 2024 10:00:36 +0100 Subject: [PATCH 07/10] runtime error when the tx callback is not a promise --- src/lib/mina/transaction.ts | 5 +++-- src/lib/util/assert.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib/mina/transaction.ts b/src/lib/mina/transaction.ts index ef0646db3b..863ee94a90 100644 --- a/src/lib/mina/transaction.ts +++ b/src/lib/mina/transaction.ts @@ -25,6 +25,7 @@ import { import * as Fetch from '../fetch.js'; import { type SendZkAppResponse, sendZkappQuery } from './graphql.js'; import { type FetchMode } from './transaction-context.js'; +import { assertPromise } from '../util/assert.js'; export { type Transaction, @@ -308,14 +309,14 @@ async function createTransaction( try { if (fetchMode === 'test') { await Provable.runUnchecked(async () => { - await f(); + await assertPromise(f()); Provable.asProver(() => { let tx = currentTransaction.get(); tx.layout.toConstantInPlace(); }); }); } else { - await f(); + await assertPromise(f()); } } catch (err) { currentTransaction.leave(transactionId); diff --git a/src/lib/util/assert.ts b/src/lib/util/assert.ts index d92057621e..122880686c 100644 --- a/src/lib/util/assert.ts +++ b/src/lib/util/assert.ts @@ -6,7 +6,7 @@ function assert(stmt: boolean, message?: string): asserts stmt { } } -function assertPromise>(value: T): T { +function assertPromise(value: Promise): Promise { assert(value instanceof Promise, 'Expected a promise'); return value; } From 4667d3efdc58b11c6889b2aef79be81380ca1c78 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 29 Feb 2024 10:06:15 +0100 Subject: [PATCH 08/10] bindings --- src/bindings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bindings b/src/bindings index f9a994b1f3..efbba4ec2b 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit f9a994b1f36ef42dbefaf189f6708bc54e6669d8 +Subproject commit efbba4ec2b65eaa874fc6f776d0a72bff7d6b765 From dbca23283a33661c1da77c0908efa514bb483c19 Mon Sep 17 00:00:00 2001 From: Gregor Date: Thu, 29 Feb 2024 10:17:18 +0100 Subject: [PATCH 09/10] changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3301f51639..cbb6559946 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Breaking changes +- Require the callback to `Mina.transaction()` to be async https://github.com/o1-labs/o1js/pull/1468 + - This change was done in support to support async contract methods - Fixed parity between `Mina.LocalBlockchain` and `Mina.Network` to have the same behaviors https://github.com/o1-labs/o1js/pull/1422 - Changed the `TransactionId` type to `Transaction`. Additionally added `PendingTransaction` and `RejectedTransaction` types to better represent the state of a transaction. - `transaction.send()` no longer throws an error if the transaction was not successful for `Mina.LocalBlockchain` and `Mina.Network`. Instead, it returns a `PendingTransaction` object that contains the error. Use `transaction.sendOrThrowIfError` to throw the error if the transaction was not successful. @@ -36,6 +38,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added +- `Provable.witnessAsync()` to introduce provable values from an async callback https://github.com/o1-labs/o1js/pull/1468 - Support for custom network identifiers other than `mainnet` or `testnet` https://github.com/o1-labs/o1js/pull/1444 - `PrivateKey.randomKeypair()` to generate private and public key in one command https://github.com/o1-labs/o1js/pull/1446 - `setNumberOfWorkers()` to allow developer to override the number of workers used during compilation and proof generation/verification https://github.com/o1-labs/o1js/pull/1456 From 52d3ac4ef265eac623916ca26ecebbe60aebd0bf Mon Sep 17 00:00:00 2001 From: Gregor Date: Tue, 5 Mar 2024 16:45:39 +0100 Subject: [PATCH 10/10] adapt to snarky not exposing state --- src/bindings | 2 +- src/lib/provable-core/exists.ts | 48 +++++++++++++-------------------- src/snarky.d.ts | 12 +++++++-- 3 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/bindings b/src/bindings index efbba4ec2b..56f76dcbac 160000 --- a/src/bindings +++ b/src/bindings @@ -1 +1 @@ -Subproject commit efbba4ec2b65eaa874fc6f776d0a72bff7d6b765 +Subproject commit 56f76dcbacb5e17297a8e981abedded49581faf3 diff --git a/src/lib/provable-core/exists.ts b/src/lib/provable-core/exists.ts index 082fa59684..863d197d84 100644 --- a/src/lib/provable-core/exists.ts +++ b/src/lib/provable-core/exists.ts @@ -1,41 +1,31 @@ import { Snarky } from '../../snarky.js'; -import { FieldConst, FieldVar } from '../field.js'; -import { MlBool } from '../ml/base.js'; +import { FieldConst, type VarFieldVar } from '../field.js'; +import { MlArray, MlOption } from '../ml/base.js'; export { existsAsync }; -const SnarkyState = Snarky.run.state; - async function existsAsync( size: number, compute: (() => Promise) | (() => bigint[]) -): Promise { - let state = SnarkyState.state[1]; +): Promise { + // enter prover block + let finish = Snarky.run.enterAsProver(size); - if (SnarkyState.hasWitness(state)) { - let oldAsProver = SnarkyState.asProver(state); - SnarkyState.setAsProver(state, MlBool(true)); + if (!Snarky.run.inProver()) { + return MlArray.from(finish(MlOption())); + } - try { - // run the async callback to get values to witness - let values = await compute(); - if (values.length !== size) - throw Error( - `Expected witnessed values of length ${size}, got ${values.length}.` - ); + // TODO would be nice to be able to step outside the as_prover block + // with a try-catch if the callback throws an error - // if we're nested in a prover block, return constants instead of storing - if (oldAsProver) return values.map(FieldVar.constant); + // run the async callback to get values to witness + let values = await compute(); + if (values.length !== size) + throw Error( + `Expected witnessed values of length ${size}, got ${values.length}.` + ); - // store the values as witnesses and return them - return values.map((x) => - SnarkyState.storeFieldElt(state, FieldConst.fromBigint(x)) - ); - } finally { - SnarkyState.setAsProver(state, oldAsProver); - } - } else { - // if we're in compile mode (no witness), just allocate "empty" variables - return Array.from({ length: size }, () => SnarkyState.allocVar(state)); - } + let inputValues = MlArray.mapTo(values, FieldConst.fromBigint); + let vars = finish(MlOption(inputValues)); + return MlArray.from(vars); } diff --git a/src/snarky.d.ts b/src/snarky.d.ts index c1f091965b..bb4d9f1b91 100644 --- a/src/snarky.d.ts +++ b/src/snarky.d.ts @@ -193,6 +193,10 @@ declare const Snarky: { * APIs that have to do with running provable code */ run: { + /** + * Checks whether Snarky runs in "prover mode", that is, with witnesses + */ + inProver(): MlBool; /** * Runs code as a prover. */ @@ -217,13 +221,17 @@ declare const Snarky: { public_inputs: FieldVector, auxiliary_inputs: FieldVector ]; + /** + * Starts an asProver / witness block and returns a function to finish it. + */ + enterAsProver( + size: number + ): (fields: MlOption>) => MlArray; /** * Snarky's internal state */ state: { - state: MlRef; - allocVar(state: SnarkyState): FieldVar; storeFieldElt(state: SnarkyState, x: FieldConst): FieldVar; getVariableValue(state: SnarkyState, x: FieldVar): FieldConst;