From 883e0821f4bbe94138a1cfe0e2c43ecf5b46e97a Mon Sep 17 00:00:00 2001 From: LHerskind Date: Mon, 11 Mar 2024 13:32:33 +0000 Subject: [PATCH] chore: align functions with authwit naming --- .../resources/common_patterns/authwit.md | 6 +- docs/docs/developers/wallets/main.md | 2 +- noir-projects/aztec-nr/authwit/src/auth.nr | 4 +- .../src/defaults/account_interface.ts | 4 +- .../accounts/src/ecdsa/account_contract.ts | 2 +- .../accounts/src/schnorr/account_contract.ts | 2 +- .../src/single_key/account_contract.ts | 2 +- .../aztec.js/src/account/interface.ts | 21 ++- .../src/fee/private_fee_payment_method.ts | 2 +- .../src/fee/public_fee_payment_method.ts | 2 +- .../aztec.js/src/wallet/account_wallet.ts | 85 ++++++++-- .../aztec.js/src/wallet/base_wallet.ts | 13 +- .../aztec.js/src/wallet/signerless_wallet.ts | 2 +- .../end-to-end/src/e2e_authwit.test.ts | 8 +- .../src/e2e_blacklist_token_contract.test.ts | 75 +++------ .../src/e2e_cross_chain_messaging.test.ts | 10 +- .../src/e2e_crowdfunding_and_claim.test.ts | 7 +- .../src/e2e_dapp_subscription.test.ts | 4 +- .../src/e2e_lending_contract.test.ts | 65 ++++---- .../e2e_public_cross_chain_messaging.test.ts | 2 +- .../end-to-end/src/e2e_token_contract.test.ts | 148 +++++++++++------- .../writing_an_account_contract.test.ts | 2 +- .../end-to-end/src/shared/uniswap_l1_l2.ts | 61 ++++---- .../entrypoints/src/account_entrypoint.ts | 4 +- .../entrypoints/src/dapp_entrypoint.ts | 2 +- 25 files changed, 319 insertions(+), 216 deletions(-) diff --git a/docs/docs/developers/contracts/resources/common_patterns/authwit.md b/docs/docs/developers/contracts/resources/common_patterns/authwit.md index bb3c5eb367a5..10480a7de40e 100644 --- a/docs/docs/developers/contracts/resources/common_patterns/authwit.md +++ b/docs/docs/developers/contracts/resources/common_patterns/authwit.md @@ -88,16 +88,12 @@ For our purposes here (not building a wallet), the most important part of the li ### General utilities -The primary general utility is the `compute_authwit_message_hash` function which computes the action hash from its components. This is useful for when you need to generate a hash that is not for the current call, such as when you want to update a public approval state value that is later used for [authentication in public](#updating-approval-state-in-noir). You can view the implementation of this function [here](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/aztec-nr/authwit/src/auth.nr). +The primary general utility is the `compute_call_authwit_hash` function which computes the action hash from its components. This is useful for when you need to generate a hash that is not for the current call, such as when you want to update a public approval state value that is later used for [authentication in public](#updating-approval-state-in-noir). You can view the implementation of this function [here](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/aztec-nr/authwit/src/auth.nr). #### TypeScript utilities To make it convenient to compute the message hashes in TypeScript, the `aztec.js` package includes a `computeAuthWitMessageHash` function that you can use. Implementation [here](https://github.com/AztecProtocol/aztec-packages/blob/master/yarn-project/aztec.js/src/utils/authwit.ts). -As you can see above, this function takes a `caller` and a `request`. The `request` can be easily prepared similarly to how we are making contract calls from TypeScript. - -#include_code authwit_computeAuthWitMessageHash /yarn-project/end-to-end/src/e2e_token_contract.test.ts typescript - ### Utilities for private calls For private calls where we allow execution on behalf of others, we generally want to check if the current call is authenticated by `on_behalf_of`. To easily do so, we can use the `assert_current_call_valid_authwit` which fetches information from the current context without us needing to provide much beyond the `on_behalf_of`. diff --git a/docs/docs/developers/wallets/main.md b/docs/docs/developers/wallets/main.md index 1e1b127ca7a6..a35ce8a7f8fc 100644 --- a/docs/docs/developers/wallets/main.md +++ b/docs/docs/developers/wallets/main.md @@ -44,7 +44,7 @@ There are no proofs generated as of the Sandbox release. This will be included i Account contracts in Aztec expose an interface for other contracts to validate [whether an action is authorized by the account or not](../../learn/concepts/accounts/main.md#authorizing-actions). For example, an application contract may want to transfer tokens on behalf of a user, in which case the token contract will check with the account contract whether the application is authorized to do so. These actions may be carried out in private or in public functions, and in transactions originated by the user or by someone else. -Wallets should manage these authorizations, prompting the user when they are requested by an application. Authorizations in private executions come in the form of _auth witnesses_, which are usually signatures over an identifier for an action. Applications can request the wallet to produce an auth witness via the `createAuthWitness` call. In public functions, authorizations are pre-stored in the account contract storage, which is handled by a call to an internal function in the account contract implementation. +Wallets should manage these authorizations, prompting the user when they are requested by an application. Authorizations in private executions come in the form of _auth witnesses_, which are usually signatures over an identifier for an action. Applications can request the wallet to produce an auth witness via the `createAuthWit` call. In public functions, authorizations are pre-stored in the account contract storage, which is handled by a call to an internal function in the account contract implementation. ## Key management diff --git a/noir-projects/aztec-nr/authwit/src/auth.nr b/noir-projects/aztec-nr/authwit/src/auth.nr index e1904352cf23..e098fdd5fd7b 100644 --- a/noir-projects/aztec-nr/authwit/src/auth.nr +++ b/noir-projects/aztec-nr/authwit/src/auth.nr @@ -27,14 +27,14 @@ pub fn assert_current_call_valid_authwit_public(context: &mut PublicContext, on_ } // docs:end:assert_current_call_valid_authwit_public -// docs:start:compute_authwit_message_hash +// docs:start:compute_call_authwit_hash // Compute the message hash to be used by an authentication witness pub fn compute_call_authwit_hash(caller: AztecAddress, consumer: AztecAddress, selector: FunctionSelector, args: [Field; N]) -> Field { let args_hash = hash_args(args); let inner_hash = compute_inner_authwit_hash([caller.to_field(), selector.to_field(), args_hash]); compute_outer_authwit_hash(consumer, inner_hash) } -// docs:end:compute_authwit_message_hash +// docs:end:compute_call_authwit_hash pub fn compute_inner_authwit_hash(args: [Field; N]) -> Field { pedersen_hash(args, GENERATOR_INDEX__AUTHWIT_INNER) diff --git a/yarn-project/accounts/src/defaults/account_interface.ts b/yarn-project/accounts/src/defaults/account_interface.ts index c02dd6d5505f..120e5b683061 100644 --- a/yarn-project/accounts/src/defaults/account_interface.ts +++ b/yarn-project/accounts/src/defaults/account_interface.ts @@ -28,8 +28,8 @@ export class DefaultAccountInterface implements AccountInterface { return this.entrypoint.createTxExecutionRequest(executions, fee); } - createAuthWitness(message: Fr): Promise { - return this.authWitnessProvider.createAuthWitness(message); + createAuthWit(message: Fr): Promise { + return this.authWitnessProvider.createAuthWit(message); } getCompleteAddress(): CompleteAddress { diff --git a/yarn-project/accounts/src/ecdsa/account_contract.ts b/yarn-project/accounts/src/ecdsa/account_contract.ts index 250c1c0ce83a..22c28d699a43 100644 --- a/yarn-project/accounts/src/ecdsa/account_contract.ts +++ b/yarn-project/accounts/src/ecdsa/account_contract.ts @@ -30,7 +30,7 @@ export class EcdsaAccountContract extends DefaultAccountContract { class EcdsaAuthWitnessProvider implements AuthWitnessProvider { constructor(private signingPrivateKey: Buffer) {} - createAuthWitness(message: Fr): Promise { + createAuthWit(message: Fr): Promise { const ecdsa = new Ecdsa(); const signature = ecdsa.constructSignature(message.toBuffer(), this.signingPrivateKey); return Promise.resolve(new AuthWitness(message, [...signature.r, ...signature.s])); diff --git a/yarn-project/accounts/src/schnorr/account_contract.ts b/yarn-project/accounts/src/schnorr/account_contract.ts index 38fc197b6d37..8e3f19c91545 100644 --- a/yarn-project/accounts/src/schnorr/account_contract.ts +++ b/yarn-project/accounts/src/schnorr/account_contract.ts @@ -30,7 +30,7 @@ export class SchnorrAccountContract extends DefaultAccountContract { class SchnorrAuthWitnessProvider implements AuthWitnessProvider { constructor(private signingPrivateKey: GrumpkinPrivateKey) {} - createAuthWitness(message: Fr): Promise { + createAuthWit(message: Fr): Promise { const schnorr = new Schnorr(); const signature = schnorr.constructSignature(message.toBuffer(), this.signingPrivateKey).toBuffer(); return Promise.resolve(new AuthWitness(message, [...signature])); diff --git a/yarn-project/accounts/src/single_key/account_contract.ts b/yarn-project/accounts/src/single_key/account_contract.ts index 5af791767586..9f42e2e39dcb 100644 --- a/yarn-project/accounts/src/single_key/account_contract.ts +++ b/yarn-project/accounts/src/single_key/account_contract.ts @@ -35,7 +35,7 @@ export class SingleKeyAccountContract extends DefaultAccountContract { class SingleKeyAuthWitnessProvider implements AuthWitnessProvider { constructor(private privateKey: GrumpkinPrivateKey, private partialAddress: PartialAddress) {} - createAuthWitness(message: Fr): Promise { + createAuthWit(message: Fr): Promise { const schnorr = new Schnorr(); const signature = schnorr.constructSignature(message.toBuffer(), this.privateKey); const publicKey = generatePublicKey(this.privateKey); diff --git a/yarn-project/aztec.js/src/account/interface.ts b/yarn-project/aztec.js/src/account/interface.ts index 32ecce8425ed..ad694658a1fd 100644 --- a/yarn-project/aztec.js/src/account/interface.ts +++ b/yarn-project/aztec.js/src/account/interface.ts @@ -1,6 +1,8 @@ import { AuthWitness, CompleteAddress, FunctionCall, TxExecutionRequest } from '@aztec/circuit-types'; +import { AztecAddress } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; +import { ContractFunctionInteraction } from '../contract/contract_function_interaction.js'; import { FeePaymentMethod } from '../fee/fee_payment_method.js'; /** @@ -17,10 +19,23 @@ export type FeeOptions = { /** Creates authorization witnesses. */ export interface AuthWitnessProvider { /** - * Create an authorization witness for the given message. - * @param message - Message to authorize. + * Computes an authentication witness from either a message or a caller and an action. + * If a message is provided, it will create a witness for the message directly. + * Otherwise, it will compute the message using the caller and the action. + * @param messageOrAuthWitInput - The message or the caller and action to approve + * @returns The authentication witness */ - createAuthWitness(message: Fr): Promise; + createAuthWit( + messageOrAuthWitInput: + | Fr + | Buffer + | { + /** The caller to approve */ + caller: AztecAddress; + /** The action to approve */ + action: ContractFunctionInteraction | FunctionCall; + }, + ): Promise; } /** Creates transaction execution requests out of a set of function calls. */ diff --git a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts index 7539294f6a0f..080d50afc2e9 100644 --- a/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/private_fee_payment_method.ts @@ -61,7 +61,7 @@ export class PrivateFeePaymentMethod implements FeePaymentMethod { ), to: this.asset, }); - await this.wallet.createAuthWitness(messageHash); + await this.wallet.createAuthWit(messageHash); return [ { diff --git a/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts b/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts index 9a367f565d44..196fd34ecccb 100644 --- a/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts +++ b/yarn-project/aztec.js/src/fee/public_fee_payment_method.ts @@ -63,7 +63,7 @@ export class PublicFeePaymentMethod implements FeePaymentMethod { }); return Promise.resolve([ - this.wallet.setPublicAuth(messageHash, true).request(), + this.wallet.setPublicAuthWit(messageHash, true).request(), { to: this.getPaymentContract(), functionData: new FunctionData( diff --git a/yarn-project/aztec.js/src/wallet/account_wallet.ts b/yarn-project/aztec.js/src/wallet/account_wallet.ts index b8db6836ff49..83258057e465 100644 --- a/yarn-project/aztec.js/src/wallet/account_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/account_wallet.ts @@ -1,9 +1,10 @@ import { AuthWitness, FunctionCall, PXE, TxExecutionRequest } from '@aztec/circuit-types'; -import { Fr } from '@aztec/circuits.js'; +import { AztecAddress, Fr } from '@aztec/circuits.js'; import { ABIParameterVisibility, FunctionAbi, FunctionType } from '@aztec/foundation/abi'; import { AccountInterface, FeeOptions } from '../account/interface.js'; import { ContractFunctionInteraction } from '../contract/contract_function_interaction.js'; +import { computeAuthWitMessageHash } from '../utils/authwit.js'; import { BaseWallet } from './base_wallet.js'; /** @@ -18,21 +19,76 @@ export class AccountWallet extends BaseWallet { return this.account.createTxExecutionRequest(execs, fee); } - async createAuthWitness(message: Fr | Buffer): Promise { - message = Buffer.isBuffer(message) ? Fr.fromBuffer(message) : message; - const witness = await this.account.createAuthWitness(message); + /** + * Computes an authentication witness from either a message or a caller and an action. + * If a message is provided, it will create a witness for the message directly. + * Otherwise, it will compute the message using the caller and the action. + * @param messageOrAuthWitInput - The message or the caller and action to approve + * @returns The authentication witness + */ + async createAuthWit( + messageOrAuthWitInput: + | Fr + | Buffer + | { + /** The caller to approve */ + caller: AztecAddress; + /** The action to approve */ + action: ContractFunctionInteraction | FunctionCall; + }, + ): Promise { + const message = this.getMessage(messageOrAuthWitInput); + const witness = await this.account.createAuthWit(message); await this.pxe.addAuthWitness(witness); return witness; } /** - * Returns a function interaction to set a message hash as authorized in this account. + * Returns the message hash for the given message or authwit input. + * @param messageOrAuthWitInput - The message or the caller and action to authorize + * @returns Message hash + */ + private getMessage( + messageOrAuthWitInput: + | Fr + | Buffer + | { + /** The caller to approve */ + caller: AztecAddress; + /** The action to approve */ + action: ContractFunctionInteraction | FunctionCall; + }, + ): Fr { + if (Buffer.isBuffer(messageOrAuthWitInput)) { + return Fr.fromBuffer(messageOrAuthWitInput); + } else if (messageOrAuthWitInput instanceof Fr) { + return messageOrAuthWitInput; + } else if (messageOrAuthWitInput.action instanceof ContractFunctionInteraction) { + return computeAuthWitMessageHash(messageOrAuthWitInput.caller, messageOrAuthWitInput.action.request()); + } + return computeAuthWitMessageHash(messageOrAuthWitInput.caller, messageOrAuthWitInput.action); + } + + /** + * Returns a function interaction to set a message hash as authorized or revoked in this account. * Public calls can then consume this authorization. - * @param message - Message hash to authorize. + * @param messageOrAuthWitInput - The message or the caller and action to authorize/revoke * @param authorized - True to authorize, false to revoke authorization. * @returns - A function interaction. */ - public setPublicAuth(message: Fr | Buffer, authorized: boolean): ContractFunctionInteraction { + public setPublicAuthWit( + messageOrAuthWitInput: + | Fr + | Buffer + | { + /** The caller to approve */ + caller: AztecAddress; + /** The action to approve */ + action: ContractFunctionInteraction | FunctionCall; + }, + authorized: boolean, + ): ContractFunctionInteraction { + const message = this.getMessage(messageOrAuthWitInput); if (authorized) { return new ContractFunctionInteraction(this, this.getAddress(), this.getApprovePublicAuthwitAbi(), [message]); } else { @@ -42,10 +98,21 @@ export class AccountWallet extends BaseWallet { /** * Returns a function interaction to cancel a message hash as authorized in this account. - * @param message - Message hash to authorize. + * @param messageOrAuthWitInput - The message or the caller and action to authorize/revoke * @returns - A function interaction. */ - public cancelAuthWit(message: Fr | Buffer): ContractFunctionInteraction { + public cancelAuthWit( + messageOrAuthWitInput: + | Fr + | Buffer + | { + /** The caller to approve */ + caller: AztecAddress; + /** The action to approve */ + action: ContractFunctionInteraction | FunctionCall; + }, + ): ContractFunctionInteraction { + const message = this.getMessage(messageOrAuthWitInput); const args = [message]; return new ContractFunctionInteraction(this, this.getAddress(), this.getCancelAuthwitAbi(), args); } diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index 832987a741ab..e2da1f14b265 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -23,6 +23,7 @@ import { NodeInfo } from '@aztec/types/interfaces'; import { FeeOptions } from '../account/interface.js'; import { Wallet } from '../account/wallet.js'; +import { ContractFunctionInteraction } from '../contract/contract_function_interaction.js'; /** * A base class for Wallet implementations @@ -34,7 +35,17 @@ export abstract class BaseWallet implements Wallet { abstract createTxExecutionRequest(execs: FunctionCall[], fee?: FeeOptions): Promise; - abstract createAuthWitness(message: Fr): Promise; + abstract createAuthWit( + messageOrAuthWitInput: + | Fr + | Buffer + | { + /** The caller to approve */ + caller: AztecAddress; + /** The action to approve */ + action: ContractFunctionInteraction | FunctionCall; + }, + ): Promise; getContractInstance(address: AztecAddress): Promise { return this.pxe.getContractInstance(address); diff --git a/yarn-project/aztec.js/src/wallet/signerless_wallet.ts b/yarn-project/aztec.js/src/wallet/signerless_wallet.ts index 135a3bc5b34d..e99e383a7579 100644 --- a/yarn-project/aztec.js/src/wallet/signerless_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/signerless_wallet.ts @@ -31,7 +31,7 @@ export class SignerlessWallet extends BaseWallet { throw new Error('Method not implemented.'); } - createAuthWitness(_message: Fr): Promise { + createAuthWit(_message: Fr): Promise { throw new Error('Method not implemented.'); } } diff --git a/yarn-project/end-to-end/src/e2e_authwit.test.ts b/yarn-project/end-to-end/src/e2e_authwit.test.ts index 4eef8e659b27..4c8844dd2843 100644 --- a/yarn-project/end-to-end/src/e2e_authwit.test.ts +++ b/yarn-project/end-to-end/src/e2e_authwit.test.ts @@ -24,7 +24,7 @@ describe('e2e_authwit_tests', () => { const innerHash = computeInnerAuthWitHash([Fr.fromString('0xdead')]); const outerHash = computeOuterAuthWitHash(wallets[1].getAddress(), innerHash); - const witness = await wallets[0].createAuthWitness(outerHash); + const witness = await wallets[0].createAuthWit(outerHash); await wallets[1].addAuthWitness(witness); const c = await SchnorrAccountContract.at(wallets[0].getAddress(), wallets[0]); @@ -36,7 +36,7 @@ describe('e2e_authwit_tests', () => { const innerHash = computeInnerAuthWitHash([Fr.fromString('0xdead'), Fr.fromString('0xbeef')]); const outerHash = computeOuterAuthWitHash(wallets[1].getAddress(), innerHash); - const witness = await wallets[0].createAuthWitness(outerHash); + const witness = await wallets[0].createAuthWit(outerHash); await wallets[1].addAuthWitness(witness); await wallets[0].cancelAuthWit(outerHash).send().wait(); @@ -55,7 +55,7 @@ describe('e2e_authwit_tests', () => { const innerHash = computeInnerAuthWitHash([Fr.fromString('0xdead'), Fr.fromString('0x01')]); const outerHash = computeOuterAuthWitHash(wallets[1].getAddress(), innerHash); - await wallets[0].setPublicAuth(outerHash, true).send().wait(); + await wallets[0].setPublicAuthWit(outerHash, true).send().wait(); const c = await SchnorrAccountContract.at(wallets[0].getAddress(), wallets[0]); await c.withWallet(wallets[1]).methods.spend_public_authwit(innerHash).send().wait(); @@ -66,7 +66,7 @@ describe('e2e_authwit_tests', () => { const innerHash = computeInnerAuthWitHash([Fr.fromString('0xdead'), Fr.fromString('0x02')]); const outerHash = computeOuterAuthWitHash(wallets[1].getAddress(), innerHash); - await wallets[0].setPublicAuth(outerHash, true).send().wait(); + await wallets[0].setPublicAuthWit(outerHash, true).send().wait(); await wallets[0].cancelAuthWit(outerHash).send().wait(); diff --git a/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts b/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts index 91d1a33619a3..f117fc7a3fd5 100644 --- a/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_blacklist_token_contract.test.ts @@ -495,9 +495,8 @@ describe('e2e_blacklist_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); // docs:end:authwit_public_transfer_example // Perform the transfer @@ -556,10 +555,9 @@ describe('e2e_blacklist_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); // We need to compute the message we want to sign and add it to the wallet as approved - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); // Perform the transfer await expect(action.simulate()).rejects.toThrowError(U128_UNDERFLOW_ERROR); @@ -579,9 +577,8 @@ describe('e2e_blacklist_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[0].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[0].address, action }, true).send().wait(); // Perform the transfer await expect(action.simulate()).rejects.toThrowError('Assertion failed: Message not authorized by account'); @@ -601,8 +598,7 @@ describe('e2e_blacklist_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[0].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[0].address, action }, true).send().wait(); // Perform the transfer await expect(action.simulate()).rejects.toThrowError('Assertion failed: Message not authorized by account'); @@ -677,10 +673,9 @@ describe('e2e_blacklist_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); // docs:end:authwit_computeAuthWitMessageHash - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); // docs:end:authwit_transfer_example await wallets[1].addCapsule( @@ -753,12 +748,10 @@ describe('e2e_blacklist_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - // Both wallets are connected to same node and PXE so we could just insert directly using - // await wallet.signAndAddAuthWitness(messageHash, ); + // Both wallets are connected to same node and PXE so we could just insert directly // But doing it in two actions to show the flow. - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); await wallets[1].addCapsule( getMembershipCapsule(await getMembershipProof(accounts[1].address.toBigInt(), true)), @@ -813,10 +806,9 @@ describe('e2e_blacklist_token_contract', () => { const action = asset .withWallet(wallets[2]) .methods.transfer(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); const expectedMessageHash = computeAuthWitMessageHash(accounts[2].address, action.request()); - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[2].addAuthWitness(witness); await wallets[2].addCapsule( getMembershipCapsule(await getMembershipProof(accounts[1].address.toBigInt(), true)), @@ -896,8 +888,7 @@ describe('e2e_blacklist_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.shield(accounts[0].address, amount, secretHash, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); const tx = action.send(); const receipt = await tx.wait(); @@ -952,8 +943,7 @@ describe('e2e_blacklist_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.shield(accounts[0].address, amount, secretHash, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); await expect(action.simulate()).rejects.toThrowError(U128_UNDERFLOW_ERROR); }); @@ -966,8 +956,7 @@ describe('e2e_blacklist_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[2]).methods.shield(accounts[0].address, amount, secretHash, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); await expect(action.simulate()).rejects.toThrowError('Assertion failed: Message not authorized by account'); }); @@ -1021,12 +1010,10 @@ describe('e2e_blacklist_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.unshield(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - // Both wallets are connected to same node and PXE so we could just insert directly using - // await wallet.signAndAddAuthWitness(messageHash, ); + // Both wallets are connected to same node and PXE so we could just insert directly // But doing it in two actions to show the flow. - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); const tx = action.send(); @@ -1090,12 +1077,10 @@ describe('e2e_blacklist_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.unshield(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - // Both wallets are connected to same node and PXE so we could just insert directly using - // await wallet.signAndAddAuthWitness(messageHash, ); + // Both wallets are connected to same node and PXE so we could just insert directly // But doing it in two actions to show the flow. - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); await wallets[1].addCapsule( getMembershipCapsule(await getMembershipProof(accounts[1].address.toBigInt(), true)), @@ -1117,13 +1102,11 @@ describe('e2e_blacklist_token_contract', () => { const action = asset .withWallet(wallets[2]) .methods.unshield(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); const expectedMessageHash = computeAuthWitMessageHash(accounts[2].address, action.request()); - // Both wallets are connected to same node and PXE so we could just insert directly using - // await wallet.signAndAddAuthWitness(messageHash, ); + // Both wallets are connected to same node and PXE so we could just insert directly // But doing it in two actions to show the flow. - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[2].addAuthWitness(witness); await wallets[2].addCapsule( getMembershipCapsule(await getMembershipProof(accounts[1].address.toBigInt(), true)), @@ -1184,8 +1167,7 @@ describe('e2e_blacklist_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.burn_public(accounts[0].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); const tx = action.send(); const receipt = await tx.wait(); @@ -1235,8 +1217,7 @@ describe('e2e_blacklist_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.burn_public(accounts[0].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); await expect(action.simulate()).rejects.toThrowError(U128_UNDERFLOW_ERROR); }); @@ -1249,8 +1230,7 @@ describe('e2e_blacklist_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.burn_public(accounts[0].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[0].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[0].address, action }, true).send().wait(); await expect( asset.withWallet(wallets[1]).methods.burn_public(accounts[0].address, amount, nonce).simulate(), @@ -1287,12 +1267,10 @@ describe('e2e_blacklist_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.burn(accounts[0].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - // Both wallets are connected to same node and PXE so we could just insert directly using - // await wallet.signAndAddAuthWitness(messageHash, ); + // Both wallets are connected to same node and PXE so we could just insert directly // But doing it in two actions to show the flow. - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); await wallets[1].addCapsule( getMembershipCapsule(await getMembershipProof(accounts[0].address.toBigInt(), true)), @@ -1344,12 +1322,10 @@ describe('e2e_blacklist_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.burn(accounts[0].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - // Both wallets are connected to same node and PXE so we could just insert directly using - // await wallet.signAndAddAuthWitness(messageHash, ); + // Both wallets are connected to same node and PXE so we could just insert directly // But doing it in two actions to show the flow. - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); await wallets[1].addCapsule( getMembershipCapsule(await getMembershipProof(accounts[0].address.toBigInt(), true)), @@ -1387,10 +1363,9 @@ describe('e2e_blacklist_token_contract', () => { getMembershipCapsule(await getMembershipProof(accounts[0].address.toBigInt(), true)), ); const action = asset.withWallet(wallets[2]).methods.burn(accounts[0].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); const expectedMessageHash = computeAuthWitMessageHash(accounts[2].address, action.request()); - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[2].addAuthWitness(witness); await expect(action.simulate()).rejects.toThrowError( diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts index ad81de5cea76..435101b249e4 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts @@ -105,12 +105,10 @@ describe('e2e_cross_chain_messaging', () => { // 4. Give approval to bridge to burn owner's funds: const withdrawAmount = 9n; const nonce = Fr.random(); - const burnMessageHash = computeAuthWitMessageHash( - l2Bridge.address, - l2Token.methods.burn(ownerAddress, withdrawAmount, nonce).request(), - ); - const witness = await user1Wallet.createAuthWitness(burnMessageHash); - await user1Wallet.addAuthWitness(witness); + await user1Wallet.createAuthWit({ + caller: l2Bridge.address, + action: l2Token.methods.burn(ownerAddress, withdrawAmount, nonce), + }); // docs:end:authwit_to_another_sc // 5. Withdraw owner's funds from L2 to L1 diff --git a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts index 26a4c06cea38..fe80bcddaca5 100644 --- a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts +++ b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts @@ -9,7 +9,6 @@ import { Note, PXE, TxHash, - computeAuthWitMessageHash, computeMessageSecretHash, generatePublicKey, getContractInstanceFromDeployParams, @@ -209,8 +208,7 @@ describe('e2e_crowdfunding_and_claim', () => { const action = donationToken .withWallet(donorWallets[0]) .methods.transfer(donorWallets[0].getAddress(), crowdfundingContract.address, donationAmount, 0); - const messageHash = computeAuthWitMessageHash(crowdfundingContract.address, action.request()); - const witness = await donorWallets[0].createAuthWitness(messageHash); + const witness = await donorWallets[0].createAuthWit({ caller: crowdfundingContract.address, action }); await donorWallets[0].addAuthWitness(witness); } @@ -304,8 +302,7 @@ describe('e2e_crowdfunding_and_claim', () => { const action = donationToken .withWallet(donorWallets[1]) .methods.transfer(donorWallets[1].getAddress(), crowdfundingContract.address, donationAmount, 0); - const messageHash = computeAuthWitMessageHash(crowdfundingContract.address, action.request()); - const witness = await donorWallets[1].createAuthWitness(messageHash); + const witness = await donorWallets[1].createAuthWit({ caller: crowdfundingContract.address, action }); await donorWallets[1].addAuthWitness(witness); } diff --git a/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts b/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts index 0fb56170ce3d..fbbb10fbad3a 100644 --- a/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts +++ b/yarn-project/end-to-end/src/e2e_dapp_subscription.test.ts @@ -6,7 +6,6 @@ import { PrivateFeePaymentMethod, PublicFeePaymentMethod, SentTx, - computeAuthWitMessageHash, } from '@aztec/aztec.js'; import { DefaultDappEntrypoint } from '@aztec/entrypoints/dapp'; import { @@ -235,8 +234,7 @@ describe('e2e_dapp_subscription', () => { ) { const nonce = Fr.random(); const action = bananaCoin.methods.transfer(aliceAddress, bobAddress, SUBSCRIPTION_AMOUNT, nonce); - const messageHash = computeAuthWitMessageHash(subscriptionContract.address, action.request()); - await aliceWallet.createAuthWitness(messageHash); + await aliceWallet.createAuthWit({ caller: subscriptionContract.address, action }); return subscriptionContract .withWallet(aliceWallet) diff --git a/yarn-project/end-to-end/src/e2e_lending_contract.test.ts b/yarn-project/end-to-end/src/e2e_lending_contract.test.ts index 52c23f8129ff..77ad37925a3b 100644 --- a/yarn-project/end-to-end/src/e2e_lending_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_lending_contract.test.ts @@ -148,14 +148,10 @@ describe('e2e_lending_contract', () => { it('Depositing 🥸 : 💰 -> 🏦', async () => { const depositAmount = 420n; const nonce = Fr.random(); - const messageHash = computeAuthWitMessageHash( - lendingContract.address, - collateralAsset.methods - .unshield(lendingAccount.address, lendingContract.address, depositAmount, nonce) - .request(), - ); - - await wallet.createAuthWitness(messageHash); + await wallet.createAuthWit({ + caller: lendingContract.address, + action: collateralAsset.methods.unshield(lendingAccount.address, lendingContract.address, depositAmount, nonce), + }); await lendingSim.progressTime(TIME_JUMP); lendingSim.depositPrivate(lendingAccount.address, lendingAccount.key(), depositAmount); @@ -182,13 +178,10 @@ describe('e2e_lending_contract', () => { it('Depositing 🥸 on behalf of recipient: 💰 -> 🏦', async () => { const depositAmount = 421n; const nonce = Fr.random(); - const messageHash = computeAuthWitMessageHash( - lendingContract.address, - collateralAsset.methods - .unshield(lendingAccount.address, lendingContract.address, depositAmount, nonce) - .request(), - ); - await wallet.createAuthWitness(messageHash); + await wallet.createAuthWit({ + caller: lendingContract.address, + action: collateralAsset.methods.unshield(lendingAccount.address, lendingContract.address, depositAmount, nonce), + }); await lendingSim.progressTime(TIME_JUMP); lendingSim.depositPrivate(lendingAccount.address, lendingAccount.address.toField(), depositAmount); @@ -216,15 +209,23 @@ describe('e2e_lending_contract', () => { const depositAmount = 211n; const nonce = Fr.random(); - const messageHash = computeAuthWitMessageHash( - lendingContract.address, - collateralAsset.methods - .transfer_public(lendingAccount.address, lendingContract.address, depositAmount, nonce) - .request(), - ); // Add it to the wallet as approved - await wallet.setPublicAuth(messageHash, true).send().wait(); + await wallet + .setPublicAuthWit( + { + caller: lendingContract.address, + action: collateralAsset.methods.transfer_public( + lendingAccount.address, + lendingContract.address, + depositAmount, + nonce, + ), + }, + true, + ) + .send() + .wait(); await lendingSim.progressTime(TIME_JUMP); lendingSim.depositPublic(lendingAccount.address, lendingAccount.address.toField(), depositAmount); @@ -282,11 +283,10 @@ describe('e2e_lending_contract', () => { it('Repay 🥸 : 🍌 -> 🏦', async () => { const repayAmount = 20n; const nonce = Fr.random(); - const messageHash = computeAuthWitMessageHash( - lendingContract.address, - stableCoin.methods.burn(lendingAccount.address, repayAmount, nonce).request(), - ); - await wallet.createAuthWitness(messageHash); + await wallet.createAuthWit({ + caller: lendingContract.address, + action: stableCoin.methods.burn(lendingAccount.address, repayAmount, nonce), + }); await lendingSim.progressTime(TIME_JUMP); lendingSim.repayPrivate(lendingAccount.address, lendingAccount.key(), repayAmount); @@ -308,11 +308,10 @@ describe('e2e_lending_contract', () => { it('Repay 🥸 on behalf of public: 🍌 -> 🏦', async () => { const repayAmount = 21n; const nonce = Fr.random(); - const messageHash = computeAuthWitMessageHash( - lendingContract.address, - stableCoin.methods.burn(lendingAccount.address, repayAmount, nonce).request(), - ); - await wallet.createAuthWitness(messageHash); + await wallet.createAuthWit({ + caller: lendingContract.address, + action: stableCoin.methods.burn(lendingAccount.address, repayAmount, nonce), + }); await lendingSim.progressTime(TIME_JUMP); lendingSim.repayPrivate(lendingAccount.address, lendingAccount.address.toField(), repayAmount); @@ -341,7 +340,7 @@ describe('e2e_lending_contract', () => { ); // Add it to the wallet as approved - await wallet.setPublicAuth(messageHash, true).send().wait(); + await wallet.setPublicAuthWit(messageHash, true).send().wait(); await lendingSim.progressTime(TIME_JUMP); lendingSim.repayPublic(lendingAccount.address, lendingAccount.address.toField(), repayAmount); diff --git a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts index b6da1029eb0a..45e9b9d9d632 100644 --- a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts +++ b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts @@ -115,7 +115,7 @@ describe('e2e_public_cross_chain_messaging', () => { l2Bridge.address, l2Token.methods.burn_public(ownerAddress, withdrawAmount, nonce).request(), ); - await user1Wallet.setPublicAuth(burnMessageHash, true).send().wait(); + await user1Wallet.setPublicAuthWit(burnMessageHash, true).send().wait(); // 5. Withdraw owner's funds from L2 to L1 const entryKey = await crossChainTestHarness.checkEntryIsNotInOutbox(withdrawAmount); diff --git a/yarn-project/end-to-end/src/e2e_token_contract.test.ts b/yarn-project/end-to-end/src/e2e_token_contract.test.ts index 8a000a73af75..deae7eb5f36d 100644 --- a/yarn-project/end-to-end/src/e2e_token_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_token_contract.test.ts @@ -367,9 +367,8 @@ describe('e2e_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); // docs:end:authwit_public_transfer_example // Perform the transfer @@ -428,10 +427,9 @@ describe('e2e_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); // We need to compute the message we want to sign and add it to the wallet as approved - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); // Perform the transfer await expect(action.simulate()).rejects.toThrowError(U128_UNDERFLOW_ERROR); @@ -451,9 +449,8 @@ describe('e2e_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[0].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[0].address, action }, true).send().wait(); // Perform the transfer await expect(action.simulate()).rejects.toThrowError('Assertion failed: Message not authorized by account'); @@ -473,8 +470,7 @@ describe('e2e_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[0].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[0].address, action }, true).send().wait(); // Perform the transfer await expect(action.simulate()).rejects.toThrowError('Assertion failed: Message not authorized by account'); @@ -489,12 +485,56 @@ describe('e2e_token_contract', () => { expect(amount).toBeGreaterThan(0n); const nonce = Fr.random(); + const action = asset + .withWallet(wallets[1]) + .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce); + + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); + + await wallets[0].cancelAuthWit({ caller: accounts[1].address, action }).send().wait(); + + // Check that the message hash is no longer valid. Need to try to send since nullifiers are handled by sequencer. + const txCancelledAuthwit = asset + .withWallet(wallets[1]) + .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce) + .send(); + await expect(txCancelledAuthwit.wait()).rejects.toThrowError('Transaction '); + }); + + it('transfer on behalf of other, cancelled authwit, flow 2', async () => { + const balance0 = await asset.methods.balance_of_public(accounts[0].address).view(); + const amount = balance0 / 2n; + expect(amount).toBeGreaterThan(0n); + const nonce = Fr.random(); + + const action = asset + .withWallet(wallets[1]) + .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce); + + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); + + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, false).send().wait(); + + // Check that the message hash is no longer valid. Need to try to send since nullifiers are handled by sequencer. + const txCancelledAuthwit = asset + .withWallet(wallets[1]) + .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce) + .send(); + await expect(txCancelledAuthwit.wait()).rejects.toThrowError('Transaction '); + }); + + it('transfer on behalf of other, cancelled authwit, flow 3', async () => { + const balance0 = await asset.methods.balance_of_public(accounts[0].address).view(); + const amount = balance0 / 2n; + expect(amount).toBeGreaterThan(0n); + const nonce = Fr.random(); + const action = asset .withWallet(wallets[1]) .methods.transfer_public(accounts[0].address, accounts[1].address, amount, nonce); const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit(messageHash, true).send().wait(); await wallets[0].cancelAuthWit(messageHash).send().wait(); @@ -561,10 +601,8 @@ describe('e2e_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - // docs:end:authwit_computeAuthWitMessageHash - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); // docs:end:authwit_transfer_example @@ -612,12 +650,11 @@ describe('e2e_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); // Both wallets are connected to same node and PXE so we could just insert directly using // await wallet.signAndAddAuthWitness(messageHash, ); // But doing it in two actions to show the flow. - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); // Perform the transfer @@ -660,10 +697,9 @@ describe('e2e_token_contract', () => { const action = asset .withWallet(wallets[2]) .methods.transfer(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); const expectedMessageHash = computeAuthWitMessageHash(accounts[2].address, action.request()); - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[2].addAuthWitness(witness); await expect(action.simulate()).rejects.toThrowError( @@ -682,12 +718,35 @@ describe('e2e_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.transfer(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); - await wallets[0].cancelAuthWit(messageHash).send().wait(); + await wallets[0].cancelAuthWit(witness.requestHash).send().wait(); + + // Perform the transfer, should fail because nullifier already emitted + const txCancelledAuthwit = asset + .withWallet(wallets[1]) + .methods.transfer(accounts[0].address, accounts[1].address, amount, nonce) + .send(); + await expect(txCancelledAuthwit.wait()).rejects.toThrowError('Transaction '); + }); + + it('transfer on behalf of other, cancelled authwit, flow 2', async () => { + const balance0 = await asset.methods.balance_of_private(accounts[0].address).view(); + const amount = balance0 / 2n; + const nonce = Fr.random(); + expect(amount).toBeGreaterThan(0n); + + // We need to compute the message we want to sign and add it to the wallet as approved + const action = asset + .withWallet(wallets[1]) + .methods.transfer(accounts[0].address, accounts[1].address, amount, nonce); + + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); + await wallets[1].addAuthWitness(witness); + + await wallets[0].cancelAuthWit({ caller: accounts[1].address, action }).send().wait(); // Perform the transfer, should fail because nullifier already emitted const txCancelledAuthwit = asset @@ -750,8 +809,7 @@ describe('e2e_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.shield(accounts[0].address, amount, secretHash, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); const tx = action.send(); const receipt = await tx.wait(); @@ -805,8 +863,7 @@ describe('e2e_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.shield(accounts[0].address, amount, secretHash, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); await expect(action.simulate()).rejects.toThrowError(U128_UNDERFLOW_ERROR); }); @@ -819,8 +876,7 @@ describe('e2e_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[2]).methods.shield(accounts[0].address, amount, secretHash, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); await expect(action.simulate()).rejects.toThrowError('Assertion failed: Message not authorized by account'); }); @@ -861,12 +917,10 @@ describe('e2e_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.unshield(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - // Both wallets are connected to same node and PXE so we could just insert directly using - // await wallet.signAndAddAuthWitness(messageHash, ); + // Both wallets are connected to same node and PXE so we could just insert directly // But doing it in two actions to show the flow. - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); const tx = action.send(); @@ -913,12 +967,10 @@ describe('e2e_token_contract', () => { const action = asset .withWallet(wallets[1]) .methods.unshield(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - // Both wallets are connected to same node and PXE so we could just insert directly using - // await wallet.signAndAddAuthWitness(messageHash, ); + // Both wallets are connected to same node and PXE so we could just insert directly // But doing it in two actions to show the flow. - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); await expect(action.simulate()).rejects.toThrowError('Assertion failed: Balance too low'); @@ -934,13 +986,11 @@ describe('e2e_token_contract', () => { const action = asset .withWallet(wallets[2]) .methods.unshield(accounts[0].address, accounts[1].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); const expectedMessageHash = computeAuthWitMessageHash(accounts[2].address, action.request()); - // Both wallets are connected to same node and PXE so we could just insert directly using - // await wallet.signAndAddAuthWitness(messageHash, ); + // Both wallets are connected to same node and PXE so we could just insert directly // But doing it in two actions to show the flow. - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[2].addAuthWitness(witness); await expect(action.simulate()).rejects.toThrowError( @@ -971,8 +1021,7 @@ describe('e2e_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.burn_public(accounts[0].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); const tx = action.send(); const receipt = await tx.wait(); @@ -1022,8 +1071,7 @@ describe('e2e_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.burn_public(accounts[0].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[1].address, action }, true).send().wait(); await expect(action.simulate()).rejects.toThrowError(U128_UNDERFLOW_ERROR); }); @@ -1036,8 +1084,7 @@ describe('e2e_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.burn_public(accounts[0].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[0].address, action.request()); - await wallets[0].setPublicAuth(messageHash, true).send().wait(); + await wallets[0].setPublicAuthWit({ caller: accounts[0].address, action }, true).send().wait(); await expect( asset.withWallet(wallets[1]).methods.burn_public(accounts[0].address, amount, nonce).simulate(), @@ -1065,12 +1112,10 @@ describe('e2e_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.burn(accounts[0].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - // Both wallets are connected to same node and PXE so we could just insert directly using - // await wallet.signAndAddAuthWitness(messageHash, ); + // Both wallets are connected to same node and PXE so we could just insert directly // But doing it in two actions to show the flow. - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); const tx = asset.withWallet(wallets[1]).methods.burn(accounts[0].address, amount, nonce).send(); @@ -1110,12 +1155,10 @@ describe('e2e_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[1]).methods.burn(accounts[0].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); - // Both wallets are connected to same node and PXE so we could just insert directly using - // await wallet.signAndAddAuthWitness(messageHash, ); + // Both wallets are connected to same node and PXE so we could just insert directly // But doing it in two actions to show the flow. - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[1].addAuthWitness(witness); await expect(action.simulate()).rejects.toThrowError('Assertion failed: Balance too low'); @@ -1144,10 +1187,9 @@ describe('e2e_token_contract', () => { // We need to compute the message we want to sign and add it to the wallet as approved const action = asset.withWallet(wallets[2]).methods.burn(accounts[0].address, amount, nonce); - const messageHash = computeAuthWitMessageHash(accounts[1].address, action.request()); const expectedMessageHash = computeAuthWitMessageHash(accounts[2].address, action.request()); - const witness = await wallets[0].createAuthWitness(messageHash); + const witness = await wallets[0].createAuthWit({ caller: accounts[1].address, action }); await wallets[2].addAuthWitness(witness); await expect(action.simulate()).rejects.toThrowError( diff --git a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts index 10618ba5dea9..d756f95bc3bf 100644 --- a/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts +++ b/yarn-project/end-to-end/src/guides/writing_an_account_contract.test.ts @@ -34,7 +34,7 @@ class SchnorrHardcodedKeyAccountContract extends DefaultAccountContract { getAuthWitnessProvider(_address: CompleteAddress): AuthWitnessProvider { const privateKey = this.privateKey; return { - createAuthWitness(message: Fr): Promise { + createAuthWit(message: Fr): Promise { const signer = new Schnorr(); const signature = signer.constructSignature(message.toBuffer(), privateKey); return Promise.resolve(new AuthWitness(message, [...signature.toBuffer()])); diff --git a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts index 6bdaf5caaae2..e8376008ff4b 100644 --- a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts +++ b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts @@ -202,13 +202,15 @@ export const uniswapL1L2TestSuite = ( // 3. Owner gives uniswap approval to unshield funds to self on its behalf logger('Approving uniswap to unshield funds to self on my behalf'); const nonceForWETHUnshieldApproval = new Fr(1n); - const unshieldToUniswapMessageHash = computeAuthWitMessageHash( - uniswapL2Contract.address, - wethCrossChainHarness.l2Token.methods - .unshield(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHUnshieldApproval) - .request(), - ); - await ownerWallet.createAuthWitness(unshieldToUniswapMessageHash); + await ownerWallet.createAuthWit({ + caller: uniswapL2Contract.address, + action: wethCrossChainHarness.l2Token.methods.unshield( + ownerAddress, + uniswapL2Contract.address, + wethAmountToBridge, + nonceForWETHUnshieldApproval, + ), + }); // 4. Swap on L1 - sends L2 to L1 message to withdraw WETH to L1 and another message to swap assets. logger('Withdrawing weth to L1 and sending message to swap to dai'); @@ -339,7 +341,7 @@ export const uniswapL1L2TestSuite = ( .transfer_public(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHTransferApproval) .request(), ); - await ownerWallet.setPublicAuth(transferMessageHash, true).send().wait(); + await ownerWallet.setPublicAuthWit(transferMessageHash, true).send().wait(); // before swap - check nonce_for_burn_approval stored on uniswap // (which is used by uniswap to approve the bridge to burn funds on its behalf to exit to L1) @@ -369,7 +371,7 @@ export const uniswapL1L2TestSuite = ( nonceForSwap, ); const swapMessageHash = computeAuthWitMessageHash(sponsorAddress, action.request()); - await ownerWallet.setPublicAuth(swapMessageHash, true).send().wait(); + await ownerWallet.setPublicAuthWit(swapMessageHash, true).send().wait(); // 4.2 Call swap_public from user2 on behalf of owner const withdrawReceipt = await action.send().wait(); @@ -474,13 +476,15 @@ export const uniswapL1L2TestSuite = ( // 2. owner gives uniswap approval to unshield funds: logger('Approving uniswap to unshield funds to self on my behalf'); const nonceForWETHUnshieldApproval = new Fr(3n); - const unshieldToUniswapMessageHash = computeAuthWitMessageHash( - uniswapL2Contract.address, - wethCrossChainHarness.l2Token.methods - .unshield(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHUnshieldApproval) - .request(), - ); - await ownerWallet.createAuthWitness(unshieldToUniswapMessageHash); + await ownerWallet.createAuthWit({ + caller: uniswapL2Contract.address, + action: wethCrossChainHarness.l2Token.methods.unshield( + ownerAddress, + uniswapL2Contract.address, + wethAmountToBridge, + nonceForWETHUnshieldApproval, + ), + }); // 3. Swap but send the wrong token address logger('Swap but send the wrong token address'); @@ -518,7 +522,7 @@ export const uniswapL1L2TestSuite = ( .transfer_public(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHTransferApproval) .request(), ); - await ownerWallet.setPublicAuth(transferMessageHash, true).send().wait(); + await ownerWallet.setPublicAuthWit(transferMessageHash, true).send().wait(); // No approval to call `swap` but should work even without it: const [_, secretHashForDepositingSwappedDai] = daiCrossChainHarness.generateClaimSecret(); @@ -571,7 +575,7 @@ export const uniswapL1L2TestSuite = ( nonceForSwap, ); const swapMessageHash = computeAuthWitMessageHash(approvedUser, action.request()); - await ownerWallet.setPublicAuth(swapMessageHash, true).send().wait(); + await ownerWallet.setPublicAuthWit(swapMessageHash, true).send().wait(); // Swap! await expect(action.simulate()).rejects.toThrow( @@ -589,7 +593,7 @@ export const uniswapL1L2TestSuite = ( .transfer_public(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHTransferApproval) .request(), ); - await ownerWallet.setPublicAuth(transferMessageHash, true).send().wait(); + await ownerWallet.setPublicAuthWit(transferMessageHash, true).send().wait(); await expect( uniswapL2Contract.methods @@ -623,14 +627,15 @@ export const uniswapL1L2TestSuite = ( // Owner gives uniswap approval to unshield funds to self on its behalf logger('Approving uniswap to unshield funds to self on my behalf'); const nonceForWETHUnshieldApproval = new Fr(4n); - - const unshieldToUniswapMessageHash = computeAuthWitMessageHash( - uniswapL2Contract.address, - wethCrossChainHarness.l2Token.methods - .unshield(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHUnshieldApproval) - .request(), - ); - await ownerWallet.createAuthWitness(unshieldToUniswapMessageHash); + await ownerWallet.createAuthWit({ + caller: uniswapL2Contract.address, + action: wethCrossChainHarness.l2Token.methods.unshield( + ownerAddress, + uniswapL2Contract.address, + wethAmountToBridge, + nonceForWETHUnshieldApproval, + ), + }); const wethL2BalanceBeforeSwap = await wethCrossChainHarness.getL2PrivateBalanceOf(ownerAddress); // Swap @@ -691,7 +696,7 @@ export const uniswapL1L2TestSuite = ( .transfer_public(ownerAddress, uniswapL2Contract.address, wethAmountToBridge, nonceForWETHTransferApproval) .request(), ); - await ownerWallet.setPublicAuth(transferMessageHash, true).send().wait(); + await ownerWallet.setPublicAuthWit(transferMessageHash, true).send().wait(); // Call swap_public on L2 const secretHashForDepositingSwappedDai = Fr.random(); diff --git a/yarn-project/entrypoints/src/account_entrypoint.ts b/yarn-project/entrypoints/src/account_entrypoint.ts index 1dd3762b5d61..7571bc09ca64 100644 --- a/yarn-project/entrypoints/src/account_entrypoint.ts +++ b/yarn-project/entrypoints/src/account_entrypoint.ts @@ -25,8 +25,8 @@ export class DefaultAccountEntrypoint implements EntrypointInterface { const abi = this.getEntrypointAbi(); const entrypointPackedArgs = PackedArguments.fromArgs(encodeArguments(abi, [appPayload, feePayload])); - const appAuthWitness = await this.auth.createAuthWitness(hashPayload(appPayload, GeneratorIndex.SIGNATURE_PAYLOAD)); - const feeAuthWitness = await this.auth.createAuthWitness(hashPayload(feePayload, GeneratorIndex.FEE_PAYLOAD)); + const appAuthWitness = await this.auth.createAuthWit(hashPayload(appPayload, GeneratorIndex.SIGNATURE_PAYLOAD)); + const feeAuthWitness = await this.auth.createAuthWit(hashPayload(feePayload, GeneratorIndex.FEE_PAYLOAD)); const txRequest = TxExecutionRequest.from({ argsHash: entrypointPackedArgs.hash, diff --git a/yarn-project/entrypoints/src/dapp_entrypoint.ts b/yarn-project/entrypoints/src/dapp_entrypoint.ts index 810b25e6ae28..0ea5b48cdd41 100644 --- a/yarn-project/entrypoints/src/dapp_entrypoint.ts +++ b/yarn-project/entrypoints/src/dapp_entrypoint.ts @@ -34,7 +34,7 @@ export class DefaultDappEntrypoint implements EntrypointInterface { const innerHash = computeInnerAuthWitHash([Fr.ZERO, functionData.selector.toField(), entrypointPackedArgs.hash]); const outerHash = computeOuterAuthWitHash(this.dappEntrypointAddress, innerHash); - const authWitness = await this.userAuthWitnessProvider.createAuthWitness(outerHash); + const authWitness = await this.userAuthWitnessProvider.createAuthWit(outerHash); const txRequest = TxExecutionRequest.from({ argsHash: entrypointPackedArgs.hash,