Skip to content

Commit

Permalink
Merge pull request #1468 from o1-labs/feature/async-methods
Browse files Browse the repository at this point in the history
Async circuits, pt 2 - witness and transaction callback
  • Loading branch information
mitschabaude committed Mar 7, 2024
2 parents 84233e9 + 652a9f5 commit 61fea3b
Show file tree
Hide file tree
Showing 57 changed files with 452 additions and 311 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
- Change `{SmartContract,ZkProgram}.analyzeMethods()` to be async https://github.com/o1-labs/o1js/pull/1450
- `Provable.runAndCheck()`, `Provable.constraintSystem()` and `{SmartContract,ZkProgram}.digest()` are also async now
- These changes were made to add internal support for async circuits
Expand Down Expand Up @@ -48,6 +50,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
Expand Down
6 changes: 3 additions & 3 deletions src/examples/circuit-string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/examples/commonjs.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
Expand All @@ -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());
Expand Down
2 changes: 1 addition & 1 deletion src/examples/fetch-live.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
6 changes: 3 additions & 3 deletions src/examples/nullifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Expand All @@ -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));
});
Expand All @@ -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));
});

Expand Down
4 changes: 2 additions & 2 deletions src/examples/simple-zkapp-berkeley.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
}
Expand All @@ -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));
}
);
Expand Down
4 changes: 2 additions & 2 deletions src/examples/simple-zkapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
Expand All @@ -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());
Expand Down
12 changes: 6 additions & 6 deletions src/examples/simple-zkapp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -111,22 +111,22 @@ 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();
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);
});
Expand All @@ -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 {
Expand All @@ -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();
Expand Down
8 changes: 4 additions & 4 deletions src/examples/simple-zkapp.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Expand All @@ -104,22 +104,22 @@ 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();
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);
});
Expand Down
4 changes: 2 additions & 2 deletions src/examples/zkapps/composability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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));
});
Expand Down
18 changes: 9 additions & 9 deletions src/examples/zkapps/dex/happy-path-with-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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();
});
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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);
});
Expand All @@ -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);
});
Expand All @@ -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();
Expand Down
12 changes: 6 additions & 6 deletions src/examples/zkapps/dex/happy-path-with-proofs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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));
});
Expand All @@ -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));
});

Expand All @@ -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();
Expand Down
Loading

0 comments on commit 61fea3b

Please sign in to comment.