@aztec/aztec.js 0.30.1 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +1 -1
  2. package/dest/account/index.d.ts +1 -1
  3. package/dest/account/index.d.ts.map +1 -1
  4. package/dest/account/interface.d.ts +12 -21
  5. package/dest/account/interface.d.ts.map +1 -1
  6. package/dest/account/interface.js +1 -1
  7. package/dest/api/account.d.ts +1 -1
  8. package/dest/api/account.d.ts.map +1 -1
  9. package/dest/api/account.js +1 -1
  10. package/dest/api/entrypoint.d.ts +2 -0
  11. package/dest/api/entrypoint.d.ts.map +1 -0
  12. package/dest/api/entrypoint.js +2 -0
  13. package/dest/contract/base_contract_interaction.d.ts +1 -1
  14. package/dest/contract/base_contract_interaction.d.ts.map +1 -1
  15. package/dest/contract/checker.js +2 -2
  16. package/dest/contract/deploy_method.d.ts +2 -2
  17. package/dest/contract/deploy_method.d.ts.map +1 -1
  18. package/dest/contract/deploy_method.js +4 -9
  19. package/dest/contract/sent_tx.d.ts +2 -0
  20. package/dest/contract/sent_tx.d.ts.map +1 -1
  21. package/dest/contract/sent_tx.js +3 -3
  22. package/dest/deployment/broadcast_function.d.ts.map +1 -1
  23. package/dest/deployment/broadcast_function.js +16 -31
  24. package/dest/entrypoint/default_entrypoint.d.ts +12 -0
  25. package/dest/entrypoint/default_entrypoint.d.ts.map +1 -0
  26. package/dest/entrypoint/default_entrypoint.js +18 -0
  27. package/dest/entrypoint/entrypoint.d.ts +23 -0
  28. package/dest/entrypoint/entrypoint.d.ts.map +1 -0
  29. package/dest/entrypoint/entrypoint.js +2 -0
  30. package/dest/fee/private_fee_payment_method.d.ts.map +1 -1
  31. package/dest/fee/private_fee_payment_method.js +2 -2
  32. package/dest/fee/public_fee_payment_method.d.ts.map +1 -1
  33. package/dest/fee/public_fee_payment_method.js +2 -2
  34. package/dest/utils/authwit.d.ts +8 -4
  35. package/dest/utils/authwit.d.ts.map +1 -1
  36. package/dest/utils/authwit.js +11 -7
  37. package/dest/wallet/account_wallet.d.ts +45 -7
  38. package/dest/wallet/account_wallet.d.ts.map +1 -1
  39. package/dest/wallet/account_wallet.js +75 -17
  40. package/dest/wallet/base_wallet.d.ts +8 -1
  41. package/dest/wallet/base_wallet.d.ts.map +1 -1
  42. package/dest/wallet/base_wallet.js +4 -1
  43. package/dest/wallet/signerless_wallet.d.ts +7 -2
  44. package/dest/wallet/signerless_wallet.d.ts.map +1 -1
  45. package/dest/wallet/signerless_wallet.js +18 -11
  46. package/package.json +8 -7
  47. package/src/account/index.ts +1 -1
  48. package/src/account/interface.ts +14 -23
  49. package/src/api/account.ts +1 -9
  50. package/src/api/entrypoint.ts +1 -0
  51. package/src/contract/base_contract_interaction.ts +1 -1
  52. package/src/contract/checker.ts +1 -1
  53. package/src/contract/deploy_method.ts +3 -9
  54. package/src/contract/sent_tx.ts +4 -2
  55. package/src/deployment/broadcast_function.ts +39 -47
  56. package/src/entrypoint/default_entrypoint.ts +27 -0
  57. package/src/entrypoint/entrypoint.ts +25 -0
  58. package/src/fee/private_fee_payment_method.ts +10 -5
  59. package/src/fee/public_fee_payment_method.ts +14 -8
  60. package/src/utils/authwit.ts +11 -5
  61. package/src/wallet/account_wallet.ts +123 -18
  62. package/src/wallet/base_wallet.ts +12 -1
  63. package/src/wallet/signerless_wallet.ts +23 -19
@@ -1,6 +1,6 @@
1
1
  import { PXE, Tx, TxExecutionRequest } from '@aztec/circuit-types';
2
2
 
3
- import { FeeOptions } from '../account/interface.js';
3
+ import { FeeOptions } from '../entrypoint/entrypoint.js';
4
4
  import { SentTx } from './sent_tx.js';
5
5
 
6
6
  /**
@@ -25,7 +25,7 @@ export function abiChecker(artifact: ContractArtifact) {
25
25
  }
26
26
 
27
27
  // TODO: implement a better check for bytecode (right now only checks if it's > 0)
28
- if (!('bytecode' in func && typeof func.bytecode === 'string' && func.bytecode.length > 0)) {
28
+ if (!('bytecode' in func && func.bytecode.length > 0)) {
29
29
  throw new Error('ABI function parameter has incorrect bytecode');
30
30
  }
31
31
 
@@ -5,7 +5,7 @@ import {
5
5
  getContractClassFromArtifact,
6
6
  getContractInstanceFromDeployParams,
7
7
  } from '@aztec/circuits.js';
8
- import { ContractArtifact, FunctionArtifact, getDefaultInitializer } from '@aztec/foundation/abi';
8
+ import { ContractArtifact, FunctionArtifact, getInitializer } from '@aztec/foundation/abi';
9
9
  import { EthAddress } from '@aztec/foundation/eth-address';
10
10
  import { Fr } from '@aztec/foundation/fields';
11
11
  import { createDebugLogger } from '@aztec/foundation/log';
@@ -63,16 +63,10 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas
63
63
  private artifact: ContractArtifact,
64
64
  private postDeployCtor: (address: AztecAddress, wallet: Wallet) => Promise<TContract>,
65
65
  private args: any[] = [],
66
- constructorName?: string,
66
+ constructorNameOrArtifact?: string | FunctionArtifact,
67
67
  ) {
68
68
  super(wallet);
69
- this.constructorArtifact = constructorName
70
- ? artifact.functions.find(f => f.name === constructorName)
71
- : getDefaultInitializer(artifact);
72
-
73
- if (constructorName && !this.constructorArtifact) {
74
- throw new Error(`Constructor method ${constructorName} not found in contract artifact`);
75
- }
69
+ this.constructorArtifact = getInitializer(artifact, constructorNameOrArtifact);
76
70
  }
77
71
 
78
72
  /**
@@ -15,6 +15,8 @@ export type WaitOpts = {
15
15
  waitForNotesSync?: boolean;
16
16
  /** Whether to include information useful for debugging/testing in the receipt. */
17
17
  debug?: boolean;
18
+ /** Whether to accept a revert as a status code for the tx when waiting for it. If false, will throw if the tx reverts. */
19
+ dontThrowOnRevert?: boolean;
18
20
  };
19
21
 
20
22
  export const DefaultWaitOpts: WaitOpts = {
@@ -60,10 +62,10 @@ export class SentTx {
60
62
  */
61
63
  public async wait(opts?: WaitOpts): Promise<FieldsOf<TxReceipt>> {
62
64
  if (opts?.debug && opts.waitForNotesSync === false) {
63
- throw new Error('Cannot set getNotes to true if waitForNotesSync is false');
65
+ throw new Error('Cannot set debug to true if waitForNotesSync is false');
64
66
  }
65
67
  const receipt = await this.waitForReceipt(opts);
66
- if (receipt.status !== TxStatus.MINED) {
68
+ if (!(receipt.status === TxStatus.MINED || (receipt.status === TxStatus.REVERTED && opts?.dontThrowOnRevert))) {
67
69
  throw new Error(
68
70
  `Transaction ${await this.getTxHash()} was ${receipt.status}. Reason: ${receipt.error ?? 'unknown'}`,
69
71
  );
@@ -1,11 +1,9 @@
1
1
  import {
2
2
  ARTIFACT_FUNCTION_TREE_MAX_HEIGHT,
3
3
  MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS,
4
- computeArtifactFunctionTree,
5
- computeArtifactFunctionTreeRoot,
6
- computeArtifactMetadataHash,
7
- computeFunctionArtifactHash,
8
- computePrivateFunctionsTree,
4
+ computeVerificationKeyHash,
5
+ createPrivateFunctionMembershipProof,
6
+ createUnconstrainedFunctionMembershipProof,
9
7
  getContractClassFromArtifact,
10
8
  } from '@aztec/circuits.js';
11
9
  import { ContractArtifact, FunctionSelector, FunctionType, bufferAsFields } from '@aztec/foundation/abi';
@@ -31,42 +29,38 @@ export function broadcastPrivateFunction(
31
29
  selector: FunctionSelector,
32
30
  ): ContractFunctionInteraction {
33
31
  const contractClass = getContractClassFromArtifact(artifact);
34
- const privateFunction = contractClass.privateFunctions.find(fn => fn.selector.equals(selector));
35
- if (!privateFunction) {
32
+ const privateFunctionArtifact = artifact.functions.find(fn => selector.equals(fn));
33
+ if (!privateFunctionArtifact) {
36
34
  throw new Error(`Private function with selector ${selector.toString()} not found`);
37
35
  }
38
- const privateFunctionArtifact = artifact.functions.find(fn =>
39
- FunctionSelector.fromNameAndParameters(fn).equals(selector),
40
- )!;
41
36
 
42
- // TODO(@spalladino): The following is computing the unconstrained root hash twice.
43
- // Feels like we need a nicer API for returning a hash along with all its preimages,
44
- // since it's common to provide all hash preimages to a function that verifies them.
45
- const artifactMetadataHash = computeArtifactMetadataHash(artifact);
46
- const unconstrainedArtifactFunctionTreeRoot = computeArtifactFunctionTreeRoot(artifact, FunctionType.OPEN);
37
+ const {
38
+ artifactTreeSiblingPath,
39
+ artifactTreeLeafIndex,
40
+ artifactMetadataHash,
41
+ functionMetadataHash,
42
+ unconstrainedFunctionsArtifactTreeRoot,
43
+ privateFunctionTreeSiblingPath,
44
+ privateFunctionTreeLeafIndex,
45
+ } = createPrivateFunctionMembershipProof(selector, artifact);
47
46
 
48
- // We need two sibling paths because private function information is split across two trees:
49
- // The "private function tree" captures the selectors and verification keys, and is used in the kernel circuit for verifying the proof generated by the app circuit.
50
- // The "artifact tree" captures function bytecode and metadata, and is used by the pxe to check that its executing the code it's supposed to be executing, but it never goes into circuits.
51
- const privateFunctionTreePath = computePrivateFunctionsTree(contractClass.privateFunctions).getSiblingPath(0);
52
- const artifactFunctionTreePath = computeArtifactFunctionTree(artifact, FunctionType.SECRET)!.getSiblingPath(0);
53
-
54
- const vkHash = privateFunction.vkHash;
55
- const metadataHash = computeFunctionArtifactHash(privateFunctionArtifact);
47
+ const vkHash = computeVerificationKeyHash(privateFunctionArtifact.verificationKey!);
56
48
  const bytecode = bufferAsFields(
57
- Buffer.from(privateFunctionArtifact.bytecode, 'hex'),
49
+ privateFunctionArtifact.bytecode,
58
50
  MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS,
59
51
  );
60
52
 
61
53
  const registerer = getRegistererContract(wallet);
62
54
  return registerer.methods.broadcast_private_function(
63
55
  contractClass.id,
64
- Fr.fromBufferReduce(artifactMetadataHash),
65
- Fr.fromBufferReduce(unconstrainedArtifactFunctionTreeRoot),
66
- privateFunctionTreePath.map(Fr.fromBufferReduce),
67
- padArrayEnd(artifactFunctionTreePath.map(Fr.fromBufferReduce), Fr.ZERO, ARTIFACT_FUNCTION_TREE_MAX_HEIGHT),
56
+ artifactMetadataHash,
57
+ unconstrainedFunctionsArtifactTreeRoot,
58
+ privateFunctionTreeSiblingPath,
59
+ privateFunctionTreeLeafIndex,
60
+ padArrayEnd(artifactTreeSiblingPath, Fr.ZERO, ARTIFACT_FUNCTION_TREE_MAX_HEIGHT),
61
+ artifactTreeLeafIndex,
68
62
  // eslint-disable-next-line camelcase
69
- { selector, metadata_hash: Fr.fromBufferReduce(metadataHash), bytecode, vk_hash: vkHash },
63
+ { selector, metadata_hash: functionMetadataHash, bytecode, vk_hash: vkHash },
70
64
  );
71
65
  }
72
66
 
@@ -84,35 +78,33 @@ export function broadcastUnconstrainedFunction(
84
78
  artifact: ContractArtifact,
85
79
  selector: FunctionSelector,
86
80
  ): ContractFunctionInteraction {
81
+ const contractClass = getContractClassFromArtifact(artifact);
87
82
  const functionArtifactIndex = artifact.functions.findIndex(
88
- fn => fn.functionType === FunctionType.UNCONSTRAINED && FunctionSelector.fromNameAndParameters(fn).equals(selector),
83
+ fn => fn.functionType === FunctionType.UNCONSTRAINED && selector.equals(fn),
89
84
  );
90
85
  if (functionArtifactIndex < 0) {
91
86
  throw new Error(`Unconstrained function with selector ${selector.toString()} not found`);
92
87
  }
93
88
  const functionArtifact = artifact.functions[functionArtifactIndex];
94
89
 
95
- // TODO(@spalladino): Same comment as above on computing duplicated hashes.
96
- const artifactMetadataHash = computeArtifactMetadataHash(artifact);
97
- const privateArtifactFunctionTreeRoot = computeArtifactFunctionTreeRoot(artifact, FunctionType.SECRET);
98
- const functionTreePath = computeArtifactFunctionTree(artifact, FunctionType.UNCONSTRAINED)!.getSiblingPath(
99
- functionArtifactIndex,
100
- );
90
+ const {
91
+ artifactMetadataHash,
92
+ artifactTreeLeafIndex,
93
+ artifactTreeSiblingPath,
94
+ functionMetadataHash,
95
+ privateFunctionsArtifactTreeRoot,
96
+ } = createUnconstrainedFunctionMembershipProof(selector, artifact);
101
97
 
102
- const contractClassId = getContractClassFromArtifact(artifact).id;
103
- const metadataHash = computeFunctionArtifactHash(functionArtifact);
104
- const bytecode = bufferAsFields(
105
- Buffer.from(functionArtifact.bytecode, 'hex'),
106
- MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS,
107
- );
98
+ const bytecode = bufferAsFields(functionArtifact.bytecode, MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS);
108
99
 
109
100
  const registerer = getRegistererContract(wallet);
110
101
  return registerer.methods.broadcast_unconstrained_function(
111
- contractClassId,
112
- Fr.fromBufferReduce(artifactMetadataHash),
113
- Fr.fromBufferReduce(privateArtifactFunctionTreeRoot),
114
- padArrayEnd(functionTreePath.map(Fr.fromBufferReduce), Fr.ZERO, ARTIFACT_FUNCTION_TREE_MAX_HEIGHT),
102
+ contractClass.id,
103
+ artifactMetadataHash,
104
+ privateFunctionsArtifactTreeRoot,
105
+ padArrayEnd(artifactTreeSiblingPath, Fr.ZERO, ARTIFACT_FUNCTION_TREE_MAX_HEIGHT),
106
+ artifactTreeLeafIndex,
115
107
  // eslint-disable-next-line camelcase
116
- { selector, metadata_hash: Fr.fromBufferReduce(metadataHash), bytecode },
108
+ { selector, metadata_hash: functionMetadataHash, bytecode },
117
109
  );
118
110
  }
@@ -0,0 +1,27 @@
1
+ import { FunctionCall, PackedArguments, TxExecutionRequest } from '@aztec/circuit-types';
2
+ import { TxContext } from '@aztec/circuits.js';
3
+
4
+ import { EntrypointInterface } from './entrypoint.js';
5
+
6
+ /**
7
+ * Default implementation of the entrypoint interface. It calls a function on a contract directly
8
+ */
9
+ export class DefaultEntrypoint implements EntrypointInterface {
10
+ constructor(private chainId: number, private protocolVersion: number) {}
11
+
12
+ createTxExecutionRequest(executions: FunctionCall[]): Promise<TxExecutionRequest> {
13
+ const [execution] = executions;
14
+ const packedArguments = PackedArguments.fromArgs(execution.args);
15
+ const txContext = TxContext.empty(this.chainId, this.protocolVersion);
16
+ return Promise.resolve(
17
+ new TxExecutionRequest(
18
+ execution.to,
19
+ execution.functionData,
20
+ packedArguments.hash,
21
+ txContext,
22
+ [packedArguments],
23
+ [],
24
+ ),
25
+ );
26
+ }
27
+ }
@@ -0,0 +1,25 @@
1
+ import { FunctionCall, TxExecutionRequest } from '@aztec/circuit-types';
2
+ import { Fr } from '@aztec/foundation/fields';
3
+
4
+ import { FeePaymentMethod } from '../fee/fee_payment_method.js';
5
+
6
+ /**
7
+ * Fee payment options for a transaction.
8
+ */
9
+ export type FeeOptions = {
10
+ /** The fee payment method to use */
11
+ paymentMethod: FeePaymentMethod;
12
+ /** The fee limit to pay */
13
+ maxFee: bigint | number | Fr;
14
+ };
15
+
16
+ /** Creates transaction execution requests out of a set of function calls. */
17
+ export interface EntrypointInterface {
18
+ /**
19
+ * Generates an execution request out of set of function calls.
20
+ * @param executions - The execution intents to be run.
21
+ * @param feeOpts - The fee to be paid for the transaction.
22
+ * @returns The authenticated transaction execution request.
23
+ */
24
+ createTxExecutionRequest(executions: FunctionCall[], feeOpts?: FeeOptions): Promise<TxExecutionRequest>;
25
+ }
@@ -58,11 +58,16 @@ export class PrivateFeePaymentMethod implements FeePaymentMethod {
58
58
  */
59
59
  async getFunctionCalls(maxFee: Fr): Promise<FunctionCall[]> {
60
60
  const nonce = Fr.random();
61
- const messageHash = computeAuthWitMessageHash(this.paymentContract, {
62
- args: [this.wallet.getCompleteAddress().address, this.paymentContract, maxFee, nonce],
63
- functionData: new FunctionData(FunctionSelector.fromSignature('unshield((Field),(Field),Field,Field)'), true),
64
- to: this.asset,
65
- });
61
+ const messageHash = computeAuthWitMessageHash(
62
+ this.paymentContract,
63
+ this.wallet.getChainId(),
64
+ this.wallet.getVersion(),
65
+ {
66
+ args: [this.wallet.getCompleteAddress().address, this.paymentContract, maxFee, nonce],
67
+ functionData: new FunctionData(FunctionSelector.fromSignature('unshield((Field),(Field),Field,Field)'), true),
68
+ to: this.asset,
69
+ },
70
+ );
66
71
  await this.wallet.createAuthWit(messageHash);
67
72
 
68
73
  const secretHashForRebate = computeMessageSecretHash(this.rebateSecret);
@@ -51,14 +51,20 @@ export class PublicFeePaymentMethod implements FeePaymentMethod {
51
51
  */
52
52
  getFunctionCalls(maxFee: Fr): Promise<FunctionCall[]> {
53
53
  const nonce = Fr.random();
54
- const messageHash = computeAuthWitMessageHash(this.paymentContract, {
55
- args: [this.wallet.getAddress(), this.paymentContract, maxFee, nonce],
56
- functionData: new FunctionData(
57
- FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'),
58
- false,
59
- ),
60
- to: this.asset,
61
- });
54
+
55
+ const messageHash = computeAuthWitMessageHash(
56
+ this.paymentContract,
57
+ this.wallet.getChainId(),
58
+ this.wallet.getVersion(),
59
+ {
60
+ args: [this.wallet.getAddress(), this.paymentContract, maxFee, nonce],
61
+ functionData: new FunctionData(
62
+ FunctionSelector.fromSignature('transfer_public((Field),(Field),Field,Field)'),
63
+ false,
64
+ ),
65
+ to: this.asset,
66
+ },
67
+ );
62
68
 
63
69
  return Promise.resolve([
64
70
  this.wallet.setPublicAuthWit(messageHash, true).request(),
@@ -5,19 +5,23 @@ import { pedersenHash } from '@aztec/foundation/crypto';
5
5
  // docs:start:authwit_computeAuthWitMessageHash
6
6
  /**
7
7
  * Compute an authentication witness message hash from a caller and a request
8
- * H(target: AztecAddress, H(caller: AztecAddress, selector: Field, args_hash: Field))
8
+ * H(target: AztecAddress, chainId: Field, version: Field, H(caller: AztecAddress, selector: Field, args_hash: Field))
9
9
  * Example usage would be `bob` authenticating `alice` to perform a transfer of `10`
10
10
  * tokens from his account to herself:
11
- * H(token, H(alice, transfer_selector, H(bob, alice, 10, nonce)))
11
+ * H(token, 1, 1, H(alice, transfer_selector, H(bob, alice, 10, nonce)))
12
12
  * `bob` then signs the message hash and gives it to `alice` who can then perform the
13
13
  * action.
14
14
  * @param caller - The caller approved to make the call
15
+ * @param chainId - The chain id for the message
16
+ * @param version - The version for the message
15
17
  * @param action - The request to be made (function call)
16
18
  * @returns The message hash for the witness
17
19
  */
18
- export const computeAuthWitMessageHash = (caller: AztecAddress, action: FunctionCall) => {
20
+ export const computeAuthWitMessageHash = (caller: AztecAddress, chainId: Fr, version: Fr, action: FunctionCall) => {
19
21
  return computeOuterAuthWitHash(
20
22
  action.to.toField(),
23
+ chainId,
24
+ version,
21
25
  computeInnerAuthWitHash([
22
26
  caller.toField(),
23
27
  action.functionData.selector.toField(),
@@ -51,12 +55,14 @@ export const computeInnerAuthWitHash = (args: Fr[]) => {
51
55
  * It is used as part of the `computeAuthWitMessageHash` but can also be used
52
56
  * in case the message is not a "call" to a function, but arbitrary data.
53
57
  * @param consumer - The address that can "consume" the authwit
58
+ * @param chainId - The chain id that can "consume" the authwit
59
+ * @param version - The version that can "consume" the authwit
54
60
  * @param innerHash - The inner hash for the witness
55
61
  * @returns The outer hash for the witness
56
62
  */
57
- export const computeOuterAuthWitHash = (consumer: AztecAddress, innerHash: Fr) => {
63
+ export const computeOuterAuthWitHash = (consumer: AztecAddress, chainId: Fr, version: Fr, innerHash: Fr) => {
58
64
  return pedersenHash(
59
- [consumer.toField(), innerHash].map(fr => fr.toBuffer()),
65
+ [consumer.toField(), chainId, version, innerHash].map(fr => fr.toBuffer()),
60
66
  GeneratorIndex.AUTHWIT_OUTER,
61
67
  );
62
68
  };
@@ -2,8 +2,9 @@ import { AuthWitness, FunctionCall, PXE, TxExecutionRequest } from '@aztec/circu
2
2
  import { AztecAddress, Fr } from '@aztec/circuits.js';
3
3
  import { ABIParameterVisibility, FunctionAbi, FunctionType } from '@aztec/foundation/abi';
4
4
 
5
- import { AccountInterface, FeeOptions } from '../account/interface.js';
5
+ import { AccountInterface } from '../account/interface.js';
6
6
  import { ContractFunctionInteraction } from '../contract/contract_function_interaction.js';
7
+ import { FeeOptions } from '../entrypoint/entrypoint.js';
7
8
  import { computeAuthWitMessageHash } from '../utils/authwit.js';
8
9
  import { BaseWallet } from './base_wallet.js';
9
10
 
@@ -19,6 +20,14 @@ export class AccountWallet extends BaseWallet {
19
20
  return this.account.createTxExecutionRequest(execs, fee);
20
21
  }
21
22
 
23
+ getChainId(): Fr {
24
+ return this.account.getChainId();
25
+ }
26
+
27
+ getVersion(): Fr {
28
+ return this.account.getVersion();
29
+ }
30
+
22
31
  /**
23
32
  * Computes an authentication witness from either a message or a caller and an action.
24
33
  * If a message is provided, it will create a witness for the message directly.
@@ -35,6 +44,10 @@ export class AccountWallet extends BaseWallet {
35
44
  caller: AztecAddress;
36
45
  /** The action to approve */
37
46
  action: ContractFunctionInteraction | FunctionCall;
47
+ /** The chain id to approve */
48
+ chainId?: Fr;
49
+ /** The version to approve */
50
+ version?: Fr;
38
51
  },
39
52
  ): Promise<AuthWitness> {
40
53
  const messageHash = this.getMessageHash(messageHashOrIntent);
@@ -43,6 +56,37 @@ export class AccountWallet extends BaseWallet {
43
56
  return witness;
44
57
  }
45
58
 
59
+ /**
60
+ * Returns a function interaction to set a message hash as authorized or revoked in this account.
61
+ * Public calls can then consume this authorization.
62
+ * @param messageHashOrIntent - The message or the caller and action to authorize/revoke
63
+ * @param authorized - True to authorize, false to revoke authorization.
64
+ * @returns - A function interaction.
65
+ */
66
+ public setPublicAuthWit(
67
+ messageHashOrIntent:
68
+ | Fr
69
+ | Buffer
70
+ | {
71
+ /** The caller to approve */
72
+ caller: AztecAddress;
73
+ /** The action to approve */
74
+ action: ContractFunctionInteraction | FunctionCall;
75
+ /** The chain id to approve */
76
+ chainId?: Fr;
77
+ /** The version to approve */
78
+ version?: Fr;
79
+ },
80
+ authorized: boolean,
81
+ ): ContractFunctionInteraction {
82
+ const message = this.getMessageHash(messageHashOrIntent);
83
+ if (authorized) {
84
+ return new ContractFunctionInteraction(this, this.getAddress(), this.getApprovePublicAuthwitAbi(), [message]);
85
+ } else {
86
+ return this.cancelAuthWit(message);
87
+ }
88
+ }
89
+
46
90
  /**
47
91
  * Returns the message hash for the given message or authwit input.
48
92
  * @param messageHashOrIntent - The message hash or the caller and action to authorize
@@ -57,26 +101,37 @@ export class AccountWallet extends BaseWallet {
57
101
  caller: AztecAddress;
58
102
  /** The action to approve */
59
103
  action: ContractFunctionInteraction | FunctionCall;
104
+ /** The chain id to approve */
105
+ chainId?: Fr;
106
+ /** The version to approve */
107
+ version?: Fr;
60
108
  },
61
109
  ): Fr {
62
110
  if (Buffer.isBuffer(messageHashOrIntent)) {
63
111
  return Fr.fromBuffer(messageHashOrIntent);
64
112
  } else if (messageHashOrIntent instanceof Fr) {
65
113
  return messageHashOrIntent;
66
- } else if (messageHashOrIntent.action instanceof ContractFunctionInteraction) {
67
- return computeAuthWitMessageHash(messageHashOrIntent.caller, messageHashOrIntent.action.request());
114
+ } else {
115
+ return computeAuthWitMessageHash(
116
+ messageHashOrIntent.caller,
117
+ messageHashOrIntent.chainId || this.getChainId(),
118
+ messageHashOrIntent.version || this.getVersion(),
119
+ messageHashOrIntent.action instanceof ContractFunctionInteraction
120
+ ? messageHashOrIntent.action.request()
121
+ : messageHashOrIntent.action,
122
+ );
68
123
  }
69
- return computeAuthWitMessageHash(messageHashOrIntent.caller, messageHashOrIntent.action);
70
124
  }
71
125
 
72
126
  /**
73
- * Returns a function interaction to set a message hash as authorized or revoked in this account.
74
- * Public calls can then consume this authorization.
75
- * @param messageHashOrIntent - The message or the caller and action to authorize/revoke
76
- * @param authorized - True to authorize, false to revoke authorization.
77
- * @returns - A function interaction.
127
+ * Lookup the validity of an authwit in private and public contexts.
128
+ * If the authwit have been consumed already (nullifier spent), will return false in both contexts.
129
+ * @param target - The target contract address
130
+ * @param messageHashOrIntent - The message hash or the caller and action to authorize/revoke
131
+ * @returns - A struct containing the validity of the authwit in private and public contexts.
78
132
  */
79
- public setPublicAuthWit(
133
+ async lookupValidity(
134
+ target: AztecAddress,
80
135
  messageHashOrIntent:
81
136
  | Fr
82
137
  | Buffer
@@ -85,15 +140,29 @@ export class AccountWallet extends BaseWallet {
85
140
  caller: AztecAddress;
86
141
  /** The action to approve */
87
142
  action: ContractFunctionInteraction | FunctionCall;
143
+ /** The chain id to approve */
144
+ chainId?: Fr;
145
+ /** The version to approve */
146
+ version?: Fr;
88
147
  },
89
- authorized: boolean,
90
- ): ContractFunctionInteraction {
91
- const message = this.getMessageHash(messageHashOrIntent);
92
- if (authorized) {
93
- return new ContractFunctionInteraction(this, this.getAddress(), this.getApprovePublicAuthwitAbi(), [message]);
94
- } else {
95
- return this.cancelAuthWit(message);
96
- }
148
+ ): Promise<{
149
+ /** boolean flag indicating if the authwit is valid in private context */
150
+ isValidInPrivate: boolean;
151
+ /** boolean flag indicating if the authwit is valid in public context */
152
+ isValidInPublic: boolean;
153
+ }> {
154
+ const messageHash = this.getMessageHash(messageHashOrIntent);
155
+ const witness = await this.getAuthWitness(messageHash);
156
+ const blockNumber = await this.getBlockNumber();
157
+ const interaction = new ContractFunctionInteraction(this, target, this.getLookupValidityAbi(), [
158
+ target,
159
+ blockNumber,
160
+ witness != undefined,
161
+ messageHash,
162
+ ]);
163
+
164
+ const [isValidInPrivate, isValidInPublic] = await interaction.view();
165
+ return { isValidInPrivate, isValidInPublic };
97
166
  }
98
167
 
99
168
  /**
@@ -110,6 +179,10 @@ export class AccountWallet extends BaseWallet {
110
179
  caller: AztecAddress;
111
180
  /** The action to approve */
112
181
  action: ContractFunctionInteraction | FunctionCall;
182
+ /** The chain id to approve */
183
+ chainId?: Fr;
184
+ /** The version to approve */
185
+ version?: Fr;
113
186
  },
114
187
  ): ContractFunctionInteraction {
115
188
  const message = this.getMessageHash(messageHashOrIntent);
@@ -160,4 +233,36 @@ export class AccountWallet extends BaseWallet {
160
233
  returnTypes: [],
161
234
  };
162
235
  }
236
+
237
+ private getLookupValidityAbi(): FunctionAbi {
238
+ return {
239
+ name: 'lookup_validity',
240
+ isInitializer: false,
241
+ functionType: FunctionType.UNCONSTRAINED,
242
+ isInternal: false,
243
+ parameters: [
244
+ {
245
+ name: 'myself',
246
+ type: {
247
+ kind: 'struct',
248
+ path: 'authwit::aztec::protocol_types::address::aztec_address::AztecAddress',
249
+ fields: [{ name: 'inner', type: { kind: 'field' } }],
250
+ },
251
+ visibility: 'private' as ABIParameterVisibility,
252
+ },
253
+ {
254
+ name: 'block_number',
255
+ type: { kind: 'integer', sign: 'unsigned', width: 32 },
256
+ visibility: 'private' as ABIParameterVisibility,
257
+ },
258
+ {
259
+ name: 'check_private',
260
+ type: { kind: 'boolean' },
261
+ visibility: 'private' as ABIParameterVisibility,
262
+ },
263
+ { name: 'message_hash', type: { kind: 'field' }, visibility: 'private' as ABIParameterVisibility },
264
+ ],
265
+ returnTypes: [{ kind: 'array', length: 2, type: { kind: 'boolean' } }],
266
+ };
267
+ }
163
268
  }
@@ -19,9 +19,9 @@ import { ContractArtifact } from '@aztec/foundation/abi';
19
19
  import { ContractClassWithId, ContractInstanceWithAddress } from '@aztec/types/contracts';
20
20
  import { NodeInfo } from '@aztec/types/interfaces';
21
21
 
22
- import { FeeOptions } from '../account/interface.js';
23
22
  import { Wallet } from '../account/wallet.js';
24
23
  import { ContractFunctionInteraction } from '../contract/contract_function_interaction.js';
24
+ import { FeeOptions } from '../entrypoint/entrypoint.js';
25
25
 
26
26
  /**
27
27
  * A base class for Wallet implementations
@@ -31,6 +31,10 @@ export abstract class BaseWallet implements Wallet {
31
31
 
32
32
  abstract getCompleteAddress(): CompleteAddress;
33
33
 
34
+ abstract getChainId(): Fr;
35
+
36
+ abstract getVersion(): Fr;
37
+
34
38
  abstract createTxExecutionRequest(execs: FunctionCall[], fee?: FeeOptions): Promise<TxExecutionRequest>;
35
39
 
36
40
  abstract createAuthWit(
@@ -42,6 +46,10 @@ export abstract class BaseWallet implements Wallet {
42
46
  caller: AztecAddress;
43
47
  /** The action to approve */
44
48
  action: ContractFunctionInteraction | FunctionCall;
49
+ /** The chain id to approve */
50
+ chainId?: Fr;
51
+ /** The version to approve */
52
+ version?: Fr;
45
53
  },
46
54
  ): Promise<AuthWitness>;
47
55
 
@@ -139,6 +147,9 @@ export abstract class BaseWallet implements Wallet {
139
147
  addAuthWitness(authWitness: AuthWitness) {
140
148
  return this.pxe.addAuthWitness(authWitness);
141
149
  }
150
+ getAuthWitness(messageHash: Fr) {
151
+ return this.pxe.getAuthWitness(messageHash);
152
+ }
142
153
  isContractClassPubliclyRegistered(id: Fr): Promise<boolean> {
143
154
  return this.pxe.isContractClassPubliclyRegistered(id);
144
155
  }
@@ -1,37 +1,41 @@
1
- import { AuthWitness, FunctionCall, PackedArguments, TxExecutionRequest } from '@aztec/circuit-types';
2
- import { CompleteAddress, Fr, TxContext } from '@aztec/circuits.js';
1
+ import { AuthWitness, FunctionCall, PXE, TxExecutionRequest } from '@aztec/circuit-types';
2
+ import { CompleteAddress, Fr } from '@aztec/circuits.js';
3
3
 
4
+ import { DefaultEntrypoint } from '../entrypoint/default_entrypoint.js';
5
+ import { EntrypointInterface } from '../entrypoint/entrypoint.js';
4
6
  import { BaseWallet } from './base_wallet.js';
5
7
 
6
8
  /**
7
9
  * Wallet implementation which creates a transaction request directly to the requested contract without any signing.
8
10
  */
9
11
  export class SignerlessWallet extends BaseWallet {
12
+ constructor(pxe: PXE, private entrypoint?: EntrypointInterface) {
13
+ super(pxe);
14
+ }
15
+
10
16
  async createTxExecutionRequest(executions: FunctionCall[]): Promise<TxExecutionRequest> {
11
- if (executions.length !== 1) {
12
- throw new Error(`Unexpected number of executions. Expected 1 but received ${executions.length}.`);
17
+ let entrypoint = this.entrypoint;
18
+ if (!entrypoint) {
19
+ const { chainId, protocolVersion } = await this.pxe.getNodeInfo();
20
+ entrypoint = new DefaultEntrypoint(chainId, protocolVersion);
13
21
  }
14
- const [execution] = executions;
15
- const packedArguments = PackedArguments.fromArgs(execution.args);
16
- const { chainId, protocolVersion } = await this.pxe.getNodeInfo();
17
- const txContext = TxContext.empty(chainId, protocolVersion);
18
- return Promise.resolve(
19
- new TxExecutionRequest(
20
- execution.to,
21
- execution.functionData,
22
- packedArguments.hash,
23
- txContext,
24
- [packedArguments],
25
- [],
26
- ),
27
- );
22
+
23
+ return entrypoint.createTxExecutionRequest(executions);
24
+ }
25
+
26
+ getChainId(): Fr {
27
+ throw new Error('Method not implemented.');
28
+ }
29
+
30
+ getVersion(): Fr {
31
+ throw new Error('Method not implemented.');
28
32
  }
29
33
 
30
34
  getCompleteAddress(): CompleteAddress {
31
35
  throw new Error('Method not implemented.');
32
36
  }
33
37
 
34
- createAuthWit(_message: Fr): Promise<AuthWitness> {
38
+ createAuthWit(_messageHash: Fr): Promise<AuthWitness> {
35
39
  throw new Error('Method not implemented.');
36
40
  }
37
41
  }