@aztec/stdlib 3.0.0-nightly.20251015 → 3.0.0-nightly.20251022

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 (66) hide show
  1. package/dest/block/attestation_info.d.ts +30 -0
  2. package/dest/block/attestation_info.d.ts.map +1 -0
  3. package/dest/block/attestation_info.js +39 -0
  4. package/dest/block/index.d.ts +1 -0
  5. package/dest/block/index.d.ts.map +1 -1
  6. package/dest/block/index.js +1 -0
  7. package/dest/block/published_l2_block.d.ts +0 -2
  8. package/dest/block/published_l2_block.d.ts.map +1 -1
  9. package/dest/block/published_l2_block.js +0 -6
  10. package/dest/interfaces/aztec-node-admin.d.ts +3 -0
  11. package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
  12. package/dest/interfaces/configs.d.ts +5 -0
  13. package/dest/interfaces/configs.d.ts.map +1 -1
  14. package/dest/interfaces/configs.js +2 -1
  15. package/dest/interfaces/p2p.d.ts +2 -0
  16. package/dest/interfaces/p2p.d.ts.map +1 -1
  17. package/dest/interfaces/p2p.js +2 -1
  18. package/dest/logs/directional_app_tagging_secret.d.ts +1 -1
  19. package/dest/logs/directional_app_tagging_secret.js +1 -1
  20. package/dest/logs/index.d.ts +1 -1
  21. package/dest/logs/index.d.ts.map +1 -1
  22. package/dest/logs/index.js +1 -1
  23. package/dest/logs/{indexed_tagging_secret.d.ts → pre_tag.d.ts} +3 -3
  24. package/dest/logs/pre_tag.d.ts.map +1 -0
  25. package/dest/logs/{indexed_tagging_secret.js → pre_tag.js} +1 -1
  26. package/dest/note/notes_filter.d.ts +0 -5
  27. package/dest/note/notes_filter.d.ts.map +1 -1
  28. package/dest/note/notes_filter.js +0 -3
  29. package/dest/p2p/block_attestation.d.ts +44 -3
  30. package/dest/p2p/block_attestation.d.ts.map +1 -1
  31. package/dest/p2p/block_attestation.js +36 -12
  32. package/dest/p2p/block_proposal.d.ts +2 -1
  33. package/dest/p2p/block_proposal.d.ts.map +1 -1
  34. package/dest/p2p/block_proposal.js +3 -2
  35. package/dest/tests/mocks.d.ts +3 -1
  36. package/dest/tests/mocks.d.ts.map +1 -1
  37. package/dest/tests/mocks.js +31 -9
  38. package/dest/tx/private_execution_result.d.ts +5 -5
  39. package/dest/tx/private_execution_result.d.ts.map +1 -1
  40. package/dest/tx/private_execution_result.js +6 -6
  41. package/dest/tx/tx.d.ts +6 -0
  42. package/dest/tx/tx.d.ts.map +1 -1
  43. package/dest/tx/tx.js +8 -0
  44. package/dest/versioning/versioning.d.ts.map +1 -1
  45. package/dest/versioning/versioning.js +10 -5
  46. package/dest/zkpassport/index.d.ts +15 -9
  47. package/dest/zkpassport/index.d.ts.map +1 -1
  48. package/dest/zkpassport/index.js +17 -11
  49. package/package.json +9 -9
  50. package/src/block/attestation_info.ts +62 -0
  51. package/src/block/index.ts +1 -0
  52. package/src/block/published_l2_block.ts +0 -11
  53. package/src/interfaces/configs.ts +3 -0
  54. package/src/interfaces/p2p.ts +4 -0
  55. package/src/logs/directional_app_tagging_secret.ts +1 -1
  56. package/src/logs/index.ts +1 -1
  57. package/src/logs/{indexed_tagging_secret.ts → pre_tag.ts} +2 -2
  58. package/src/note/notes_filter.ts +0 -7
  59. package/src/p2p/block_attestation.ts +49 -10
  60. package/src/p2p/block_proposal.ts +4 -3
  61. package/src/tests/mocks.ts +51 -12
  62. package/src/tx/private_execution_result.ts +5 -5
  63. package/src/tx/tx.ts +10 -0
  64. package/src/versioning/versioning.ts +10 -5
  65. package/src/zkpassport/index.ts +40 -28
  66. package/dest/logs/indexed_tagging_secret.d.ts.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { Buffer32 } from '@aztec/foundation/buffer';
2
- import { keccak256, recoverAddress } from '@aztec/foundation/crypto';
2
+ import { keccak256, tryRecoverAddress } from '@aztec/foundation/crypto';
3
3
  import type { EthAddress } from '@aztec/foundation/eth-address';
4
4
  import { Signature } from '@aztec/foundation/eth-signature';
5
5
  import { Fr } from '@aztec/foundation/fields';
@@ -30,6 +30,7 @@ export class BlockAttestation extends Gossipable {
30
30
  static override p2pTopic = TopicType.block_attestation;
31
31
 
32
32
  private sender: EthAddress | undefined;
33
+ private proposer: EthAddress | undefined;
33
34
 
34
35
  constructor(
35
36
  /** The block number of the attestation. */
@@ -40,6 +41,9 @@ export class BlockAttestation extends Gossipable {
40
41
 
41
42
  /** The signature of the block attester */
42
43
  public readonly signature: Signature,
44
+
45
+ /** The signature from the block proposer */
46
+ public readonly proposerSignature: Signature,
43
47
  ) {
44
48
  super();
45
49
  }
@@ -50,8 +54,9 @@ export class BlockAttestation extends Gossipable {
50
54
  blockNumber: schemas.UInt32,
51
55
  payload: ConsensusPayload.schema,
52
56
  signature: Signature.schema,
57
+ proposerSignature: Signature.schema,
53
58
  })
54
- .transform(obj => new BlockAttestation(obj.blockNumber, obj.payload, obj.signature));
59
+ .transform(obj => new BlockAttestation(obj.blockNumber, obj.payload, obj.signature, obj.proposerSignature));
55
60
  }
56
61
 
57
62
  override generateP2PMessageIdentifier(): Promise<Buffer32> {
@@ -68,41 +73,75 @@ export class BlockAttestation extends Gossipable {
68
73
 
69
74
  /**
70
75
  * Lazily evaluate and cache the signer of the attestation
71
- * @returns The signer of the attestation
76
+ * @returns The signer of the attestation, or undefined if signature recovery fails
72
77
  */
73
- getSender(): EthAddress {
78
+ getSender(): EthAddress | undefined {
74
79
  if (!this.sender) {
75
80
  // Recover the sender from the attestation
76
81
  const hashed = getHashedSignaturePayloadEthSignedMessage(this.payload, SignatureDomainSeparator.blockAttestation);
77
82
  // Cache the sender for later use
78
- this.sender = recoverAddress(hashed, this.signature);
83
+ this.sender = tryRecoverAddress(hashed, this.signature);
79
84
  }
80
85
 
81
86
  return this.sender;
82
87
  }
83
88
 
89
+ /**
90
+ * Lazily evaluate and cache the proposer of the block
91
+ * @returns The proposer of the block
92
+ */
93
+ getProposer(): EthAddress {
94
+ if (!this.proposer) {
95
+ // Recover the proposer from the proposal signature
96
+ const hashed = getHashedSignaturePayloadEthSignedMessage(this.payload, SignatureDomainSeparator.blockProposal);
97
+ // Cache the proposer for later use
98
+ this.proposer = tryRecoverAddress(hashed, this.proposerSignature)!;
99
+ }
100
+
101
+ return this.proposer;
102
+ }
103
+
84
104
  getPayload(): Buffer {
85
105
  return this.payload.getPayloadToSign(SignatureDomainSeparator.blockAttestation);
86
106
  }
87
107
 
88
108
  toBuffer(): Buffer {
89
- return serializeToBuffer([this.blockNumber, this.payload, this.signature]);
109
+ return serializeToBuffer([this.blockNumber, this.payload, this.signature, this.proposerSignature]);
90
110
  }
91
111
 
92
112
  static fromBuffer(buf: Buffer | BufferReader): BlockAttestation {
93
113
  const reader = BufferReader.asReader(buf);
94
- return new BlockAttestation(reader.readNumber(), reader.readObject(ConsensusPayload), reader.readObject(Signature));
114
+ return new BlockAttestation(
115
+ reader.readNumber(),
116
+ reader.readObject(ConsensusPayload),
117
+ reader.readObject(Signature),
118
+ reader.readObject(Signature),
119
+ );
95
120
  }
96
121
 
97
122
  static empty(): BlockAttestation {
98
- return new BlockAttestation(0, ConsensusPayload.empty(), Signature.empty());
123
+ return new BlockAttestation(0, ConsensusPayload.empty(), Signature.empty(), Signature.empty());
99
124
  }
100
125
 
101
126
  static random(): BlockAttestation {
102
- return new BlockAttestation(Math.floor(Math.random() * 1000) + 1, ConsensusPayload.random(), Signature.random());
127
+ return new BlockAttestation(
128
+ Math.floor(Math.random() * 1000) + 1,
129
+ ConsensusPayload.random(),
130
+ Signature.random(),
131
+ Signature.random(),
132
+ );
103
133
  }
104
134
 
105
135
  getSize(): number {
106
- return 4 /* blockNumber */ + this.payload.getSize() + this.signature.getSize();
136
+ return 4 /* blockNumber */ + this.payload.getSize() + this.signature.getSize() + this.proposerSignature.getSize();
137
+ }
138
+
139
+ toInspect() {
140
+ return {
141
+ blockNumber: this.blockNumber,
142
+ payload: this.payload.toInspect(),
143
+ signature: this.signature.toString(),
144
+ proposerSignature: this.proposerSignature.toString(),
145
+ };
107
146
  }
108
147
  }
@@ -1,5 +1,5 @@
1
1
  import { Buffer32 } from '@aztec/foundation/buffer';
2
- import { keccak256, recoverAddress } from '@aztec/foundation/crypto';
2
+ import { keccak256, tryRecoverAddress } from '@aztec/foundation/crypto';
3
3
  import type { EthAddress } from '@aztec/foundation/eth-address';
4
4
  import { Signature } from '@aztec/foundation/eth-signature';
5
5
  import { Fr } from '@aztec/foundation/fields';
@@ -100,12 +100,13 @@ export class BlockProposal extends Gossipable {
100
100
 
101
101
  /**Get Sender
102
102
  * Lazily evaluate the sender of the proposal; result is cached
103
+ * @returns The sender address, or undefined if signature recovery fails
103
104
  */
104
- getSender() {
105
+ getSender(): EthAddress | undefined {
105
106
  if (!this.sender) {
106
107
  const hashed = getHashedSignaturePayloadEthSignedMessage(this.payload, SignatureDomainSeparator.blockProposal);
107
108
  // Cache the sender for later use
108
- this.sender = recoverAddress(hashed, this.signature);
109
+ this.sender = tryRecoverAddress(hashed, this.signature);
109
110
  }
110
111
 
111
112
  return this.sender;
@@ -246,6 +246,8 @@ export const randomDeployedContract = async () => {
246
246
 
247
247
  export interface MakeConsensusPayloadOptions {
248
248
  signer?: Secp256k1Signer;
249
+ attesterSigner?: Secp256k1Signer;
250
+ proposerSigner?: Secp256k1Signer;
249
251
  header?: L2BlockHeader;
250
252
  archive?: Fr;
251
253
  stateReference?: StateReference;
@@ -294,21 +296,58 @@ export const makeBlockProposal = (options?: MakeConsensusPayloadOptions): BlockP
294
296
 
295
297
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8028)
296
298
  export const makeBlockAttestation = (options?: MakeConsensusPayloadOptions): BlockAttestation => {
297
- const { blockNumber, payload, signature } = makeAndSignConsensusPayload(
298
- SignatureDomainSeparator.blockAttestation,
299
- options,
300
- );
301
- return new BlockAttestation(blockNumber, payload, signature);
299
+ const header = options?.header ?? makeL2BlockHeader(1);
300
+ const {
301
+ signer,
302
+ attesterSigner = signer ?? Secp256k1Signer.random(),
303
+ proposerSigner = signer ?? Secp256k1Signer.random(),
304
+ archive = Fr.random(),
305
+ stateReference = header.state,
306
+ } = options ?? {};
307
+
308
+ const payload = ConsensusPayload.fromFields({
309
+ header: header.toCheckpointHeader(),
310
+ archive,
311
+ stateReference,
312
+ });
313
+
314
+ // Sign as attester
315
+ const attestationHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
316
+ const attestationSignature = attesterSigner.sign(attestationHash);
317
+
318
+ // Sign as proposer
319
+ const proposalHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockProposal);
320
+ const proposerSignature = proposerSigner.sign(proposalHash);
321
+
322
+ return new BlockAttestation(header.globalVariables.blockNumber, payload, attestationSignature, proposerSignature);
302
323
  };
303
324
 
304
- export const makeBlockAttestationFromBlock = (block: L2Block, signer?: Secp256k1Signer): BlockAttestation => {
305
- return makeBlockAttestation({
306
- signer,
307
- header: block.header,
308
- archive: block.archive.root,
309
- stateReference: block.header.state,
310
- txHashes: block.body.txEffects.map(tx => tx.txHash),
325
+ export const makeBlockAttestationFromBlock = (
326
+ block: L2Block,
327
+ attesterSigner?: Secp256k1Signer,
328
+ proposerSigner?: Secp256k1Signer,
329
+ ): BlockAttestation => {
330
+ const header = block.header;
331
+ const archive = block.archive.root;
332
+ const stateReference = block.header.state;
333
+
334
+ const payload = ConsensusPayload.fromFields({
335
+ header: header.toCheckpointHeader(),
336
+ archive,
337
+ stateReference,
311
338
  });
339
+
340
+ // Sign as attester
341
+ const attestationHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
342
+ const attestationSigner = attesterSigner ?? Secp256k1Signer.random();
343
+ const attestationSignature = attestationSigner.sign(attestationHash);
344
+
345
+ // Sign as proposer
346
+ const proposalHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockProposal);
347
+ const proposalSignerToUse = proposerSigner ?? Secp256k1Signer.random();
348
+ const proposerSignature = proposalSignerToUse.sign(proposalHash);
349
+
350
+ return new BlockAttestation(header.globalVariables.blockNumber, payload, attestationSignature, proposerSignature);
312
351
  };
313
352
 
314
353
  export async function randomPublishedL2Block(
@@ -10,7 +10,7 @@ import { PrivateCircuitPublicInputs } from '../kernel/private_circuit_public_inp
10
10
  import type { IsEmpty } from '../kernel/utils/interfaces.js';
11
11
  import { sortByCounter } from '../kernel/utils/order_and_comparison.js';
12
12
  import { ContractClassLog, ContractClassLogFields } from '../logs/contract_class_log.js';
13
- import { type IndexedTaggingSecret, IndexedTaggingSecretSchema } from '../logs/indexed_tagging_secret.js';
13
+ import { type PreTag, PreTagSchema } from '../logs/pre_tag.js';
14
14
  import { Note } from '../note/note.js';
15
15
  import { type ZodFor, mapSchema, schemas } from '../schemas/index.js';
16
16
  import type { UInt32 } from '../types/index.js';
@@ -136,8 +136,8 @@ export class PrivateCallExecutionResult {
136
136
  public returnValues: Fr[],
137
137
  /** The offchain effects emitted during execution of this function call via the `emit_offchain_effect` oracle. */
138
138
  public offchainEffects: { data: Fr[] }[],
139
- /** The tagging indexes incremented by this execution along with the directional app tagging secrets. */
140
- public indexedTaggingSecrets: IndexedTaggingSecret[],
139
+ /** The pre tags used in this tx to compute tags for private logs */
140
+ public preTags: PreTag[],
141
141
  /** The nested executions. */
142
142
  public nestedExecutionResults: PrivateCallExecutionResult[],
143
143
  /**
@@ -161,7 +161,7 @@ export class PrivateCallExecutionResult {
161
161
  noteHashNullifierCounterMap: mapSchema(z.coerce.number(), z.number()),
162
162
  returnValues: z.array(schemas.Fr),
163
163
  offchainEffects: z.array(z.object({ data: z.array(schemas.Fr) })),
164
- indexedTaggingSecrets: z.array(IndexedTaggingSecretSchema),
164
+ preTags: z.array(PreTagSchema),
165
165
  nestedExecutionResults: z.array(z.lazy(() => PrivateCallExecutionResult.schema)),
166
166
  contractClassLogs: z.array(CountedContractClassLog.schema),
167
167
  })
@@ -179,7 +179,7 @@ export class PrivateCallExecutionResult {
179
179
  fields.noteHashNullifierCounterMap,
180
180
  fields.returnValues,
181
181
  fields.offchainEffects,
182
- fields.indexedTaggingSecrets,
182
+ fields.preTags,
183
183
  fields.nestedExecutionResults,
184
184
  fields.contractClassLogs,
185
185
  );
package/src/tx/tx.ts CHANGED
@@ -161,6 +161,16 @@ export class Tx extends Gossipable {
161
161
  );
162
162
  }
163
163
 
164
+ /**
165
+ * Validates that the tx hash matches the computed hash from the tx data.
166
+ * This should be called when deserializing a tx from an untrusted source.
167
+ * @returns true if the hash is valid, false otherwise
168
+ */
169
+ async validateTxHash(): Promise<boolean> {
170
+ const expectedHash = await Tx.computeTxHash(this);
171
+ return this.txHash.equals(expectedHash);
172
+ }
173
+
164
174
  /**
165
175
  * Gets public logs emitted by this tx.
166
176
  * @param logsSource - An instance of `L2LogsSource` which can be used to obtain the logs.
@@ -117,11 +117,16 @@ export function validatePartialComponentVersionsMatch(
117
117
  /** Returns a Koa middleware that injects the versioning info as headers. */
118
118
  export function getVersioningMiddleware(versions: Partial<ComponentsVersions>) {
119
119
  return async (ctx: Koa.Context, next: () => Promise<void>) => {
120
- await next();
121
- for (const key in versions) {
122
- const value = versions[key as keyof ComponentsVersions];
123
- if (value !== undefined) {
124
- ctx.set(`x-aztec-${key}`, value.toString());
120
+ try {
121
+ await next();
122
+ } finally {
123
+ // Always add version headers, even if there was an error
124
+ // This allows the client to detect version mismatches before processing other errors
125
+ for (const key in versions) {
126
+ const value = versions[key as keyof ComponentsVersions];
127
+ if (value !== undefined) {
128
+ ctx.set(`x-aztec-${key}`, value.toString());
129
+ }
125
130
  }
126
131
  }
127
132
  };
@@ -5,15 +5,21 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
5
5
  import { withoutHexPrefix } from '@aztec/foundation/string';
6
6
 
7
7
  export type ViemZkPassportProofParams = {
8
- vkeyHash: `0x${string}`;
9
- proof: `0x${string}`;
10
- publicInputs: `0x${string}`[];
11
- committedInputs: `0x${string}`;
12
- committedInputCounts: bigint[];
13
- validityPeriodInSeconds: bigint;
14
- domain: string;
15
- scope: string;
16
- devMode: boolean;
8
+ proofVerificationData: {
9
+ vkeyHash: `0x${string}`;
10
+ proof: `0x${string}`;
11
+ publicInputs: `0x${string}`[];
12
+ };
13
+ commitments: {
14
+ committedInputs: `0x${string}`;
15
+ committedInputCounts: bigint[];
16
+ };
17
+ serviceConfig: {
18
+ validityPeriodInSeconds: bigint;
19
+ domain: string;
20
+ scope: string;
21
+ devMode: boolean;
22
+ };
17
23
  };
18
24
 
19
25
  // NOTE: Must match the ZkPassportProofParams struct in the zkpassport verifier contract
@@ -64,7 +70,7 @@ export class ZkPassportProofParams {
64
70
  publicInputs,
65
71
  committedInputs,
66
72
  committedInputCounts,
67
- BigInt(100 * 60 * 60 * 24),
73
+ BigInt(7 * 24 * 60 * 60), // 7 days
68
74
  'sequencer.alpha-testnet.aztec.network',
69
75
  'personhood',
70
76
  );
@@ -87,29 +93,35 @@ export class ZkPassportProofParams {
87
93
 
88
94
  static fromViem(params: ViemZkPassportProofParams) {
89
95
  return new ZkPassportProofParams(
90
- params.devMode,
91
- Buffer32.fromString(params.vkeyHash),
92
- Buffer.from(withoutHexPrefix(params.proof), 'hex'),
93
- params.publicInputs.map(input => Fr.fromString(input)),
94
- Buffer.from(withoutHexPrefix(params.committedInputs), 'hex'),
95
- params.committedInputCounts,
96
- params.validityPeriodInSeconds,
97
- params.domain,
98
- params.scope,
96
+ params.serviceConfig.devMode,
97
+ Buffer32.fromString(params.proofVerificationData.vkeyHash),
98
+ Buffer.from(withoutHexPrefix(params.proofVerificationData.proof), 'hex'),
99
+ params.proofVerificationData.publicInputs.map(input => Fr.fromString(input)),
100
+ Buffer.from(withoutHexPrefix(params.commitments.committedInputs), 'hex'),
101
+ params.commitments.committedInputCounts,
102
+ params.serviceConfig.validityPeriodInSeconds,
103
+ params.serviceConfig.domain,
104
+ params.serviceConfig.scope,
99
105
  );
100
106
  }
101
107
 
102
108
  toViem(): ViemZkPassportProofParams {
103
109
  return {
104
- devMode: this.devMode,
105
- vkeyHash: this.vkeyHash.toString(),
106
- proof: `0x${this.proof.toString('hex')}`,
107
- publicInputs: this.publicInputs.map(input => input.toString()),
108
- committedInputs: `0x${this.committedInputs.toString('hex')}`,
109
- committedInputCounts: this.committedInputCounts,
110
- validityPeriodInSeconds: this.validityPeriodInSeconds,
111
- domain: this.domain,
112
- scope: this.scope,
110
+ serviceConfig: {
111
+ devMode: this.devMode,
112
+ validityPeriodInSeconds: this.validityPeriodInSeconds,
113
+ domain: this.domain,
114
+ scope: this.scope,
115
+ },
116
+ proofVerificationData: {
117
+ vkeyHash: this.vkeyHash.toString(),
118
+ proof: `0x${this.proof.toString('hex')}`,
119
+ publicInputs: this.publicInputs.map(input => input.toString()),
120
+ },
121
+ commitments: {
122
+ committedInputs: `0x${this.committedInputs.toString('hex')}`,
123
+ committedInputCounts: this.committedInputCounts,
124
+ },
113
125
  };
114
126
  }
115
127
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"indexed_tagging_secret.d.ts","sourceRoot":"","sources":["../../src/logs/indexed_tagging_secret.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EACL,KAAK,2BAA2B,EAEjC,MAAM,qCAAqC,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,2BAA2B,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;EAGrC,CAAC"}