@aztec/foundation 0.0.1-commit.1142ef1 → 0.0.1-commit.1bea0213

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 (105) hide show
  1. package/dest/branded-types/block_number.d.ts +4 -1
  2. package/dest/branded-types/block_number.d.ts.map +1 -1
  3. package/dest/branded-types/block_number.js +3 -0
  4. package/dest/branded-types/index.d.ts +2 -1
  5. package/dest/branded-types/index.d.ts.map +1 -1
  6. package/dest/branded-types/index.js +1 -0
  7. package/dest/branded-types/index_within_checkpoint.d.ts +42 -0
  8. package/dest/branded-types/index_within_checkpoint.d.ts.map +1 -0
  9. package/dest/branded-types/index_within_checkpoint.js +59 -0
  10. package/dest/buffer/buffer16.d.ts +4 -1
  11. package/dest/buffer/buffer16.d.ts.map +1 -1
  12. package/dest/buffer/buffer32.d.ts +4 -1
  13. package/dest/buffer/buffer32.d.ts.map +1 -1
  14. package/dest/collection/array.d.ts +6 -1
  15. package/dest/collection/array.d.ts.map +1 -1
  16. package/dest/collection/array.js +27 -0
  17. package/dest/config/env_var.d.ts +2 -2
  18. package/dest/config/env_var.d.ts.map +1 -1
  19. package/dest/config/index.d.ts +5 -1
  20. package/dest/config/index.d.ts.map +1 -1
  21. package/dest/config/index.js +14 -0
  22. package/dest/crypto/ecdsa/signature.d.ts +10 -1
  23. package/dest/crypto/ecdsa/signature.d.ts.map +1 -1
  24. package/dest/crypto/poseidon/index.d.ts +1 -2
  25. package/dest/crypto/poseidon/index.d.ts.map +1 -1
  26. package/dest/crypto/poseidon/index.js +0 -9
  27. package/dest/crypto/sync/poseidon/index.d.ts +1 -2
  28. package/dest/crypto/sync/poseidon/index.d.ts.map +1 -1
  29. package/dest/crypto/sync/poseidon/index.js +0 -8
  30. package/dest/curves/bls12/point.d.ts +10 -1
  31. package/dest/curves/bls12/point.d.ts.map +1 -1
  32. package/dest/curves/grumpkin/point.d.ts +11 -2
  33. package/dest/curves/grumpkin/point.d.ts.map +1 -1
  34. package/dest/error/index.d.ts +4 -4
  35. package/dest/error/index.d.ts.map +1 -1
  36. package/dest/eth-signature/eth_signature.d.ts +4 -1
  37. package/dest/eth-signature/eth_signature.d.ts.map +1 -1
  38. package/dest/json-rpc/client/undici.d.ts +1 -1
  39. package/dest/json-rpc/client/undici.d.ts.map +1 -1
  40. package/dest/json-rpc/client/undici.js +21 -4
  41. package/dest/json-rpc/fixtures/class_a.d.ts +3 -3
  42. package/dest/json-rpc/fixtures/class_a.d.ts.map +1 -1
  43. package/dest/json-rpc/fixtures/class_b.d.ts +3 -3
  44. package/dest/json-rpc/fixtures/class_b.d.ts.map +1 -1
  45. package/dest/json-rpc/server/safe_json_rpc_server.js +1 -1
  46. package/dest/retry/index.d.ts +11 -1
  47. package/dest/retry/index.d.ts.map +1 -1
  48. package/dest/retry/index.js +11 -0
  49. package/dest/serialize/buffer_reader.d.ts +7 -4
  50. package/dest/serialize/buffer_reader.d.ts.map +1 -1
  51. package/dest/serialize/buffer_reader.js +13 -4
  52. package/dest/trees/balanced_merkle_tree_root.d.ts +17 -0
  53. package/dest/trees/balanced_merkle_tree_root.d.ts.map +1 -0
  54. package/dest/trees/{balanced_merkle_tree.js → balanced_merkle_tree_root.js} +2 -17
  55. package/dest/trees/hasher.d.ts +3 -1
  56. package/dest/trees/hasher.d.ts.map +1 -1
  57. package/dest/trees/hasher.js +10 -5
  58. package/dest/trees/index.d.ts +4 -4
  59. package/dest/trees/index.d.ts.map +1 -1
  60. package/dest/trees/index.js +3 -3
  61. package/dest/trees/membership_witness.d.ts +11 -1
  62. package/dest/trees/membership_witness.d.ts.map +1 -1
  63. package/dest/trees/membership_witness.js +9 -0
  64. package/dest/trees/merkle_tree_calculator.d.ts +1 -1
  65. package/dest/trees/merkle_tree_calculator.d.ts.map +1 -1
  66. package/dest/trees/merkle_tree_calculator.js +2 -2
  67. package/dest/trees/sibling_path.d.ts +2 -1
  68. package/dest/trees/sibling_path.d.ts.map +1 -1
  69. package/dest/trees/sibling_path.js +2 -2
  70. package/dest/trees/unbalanced_merkle_tree_calculator.d.ts +2 -2
  71. package/dest/trees/unbalanced_merkle_tree_calculator.d.ts.map +1 -1
  72. package/dest/trees/unbalanced_merkle_tree_calculator.js +1 -1
  73. package/dest/trees/{unbalanced_merkle_tree.d.ts → unbalanced_merkle_tree_root.d.ts} +3 -7
  74. package/dest/trees/unbalanced_merkle_tree_root.d.ts.map +1 -0
  75. package/dest/trees/{unbalanced_merkle_tree.js → unbalanced_merkle_tree_root.js} +8 -52
  76. package/dest/trees/unbalanced_tree_store.d.ts +5 -1
  77. package/dest/trees/unbalanced_tree_store.d.ts.map +1 -1
  78. package/dest/trees/unbalanced_tree_store.js +49 -1
  79. package/dest/types/index.d.ts +1 -1
  80. package/package.json +4 -4
  81. package/src/branded-types/block_number.ts +5 -0
  82. package/src/branded-types/index.ts +1 -0
  83. package/src/branded-types/index_within_checkpoint.ts +88 -0
  84. package/src/collection/array.ts +31 -0
  85. package/src/config/env_var.ts +9 -7
  86. package/src/config/index.ts +17 -0
  87. package/src/crypto/poseidon/index.ts +0 -10
  88. package/src/crypto/sync/poseidon/index.ts +0 -9
  89. package/src/json-rpc/client/undici.ts +21 -3
  90. package/src/json-rpc/server/safe_json_rpc_server.ts +1 -1
  91. package/src/retry/index.ts +18 -0
  92. package/src/serialize/buffer_reader.ts +21 -9
  93. package/src/trees/{balanced_merkle_tree.ts → balanced_merkle_tree_root.ts} +2 -18
  94. package/src/trees/hasher.ts +9 -0
  95. package/src/trees/index.ts +3 -3
  96. package/src/trees/membership_witness.ts +8 -0
  97. package/src/trees/merkle_tree_calculator.ts +2 -2
  98. package/src/trees/sibling_path.ts +2 -2
  99. package/src/trees/unbalanced_merkle_tree_calculator.ts +1 -2
  100. package/src/trees/{unbalanced_merkle_tree.ts → unbalanced_merkle_tree_root.ts} +8 -66
  101. package/src/trees/unbalanced_tree_store.ts +57 -2
  102. package/src/types/index.ts +1 -1
  103. package/dest/trees/balanced_merkle_tree.d.ts +0 -22
  104. package/dest/trees/balanced_merkle_tree.d.ts.map +0 -1
  105. package/dest/trees/unbalanced_merkle_tree.d.ts.map +0 -1
@@ -151,6 +151,7 @@ export type EnvVar =
151
151
  | 'PROVER_BROKER_BATCH_INTERVAL_MS'
152
152
  | 'PROVER_BROKER_BATCH_SIZE'
153
153
  | 'PROVER_BROKER_MAX_EPOCHS_TO_KEEP_RESULTS_FOR'
154
+ | 'PROVER_CANCEL_JOBS_ON_STOP'
154
155
  | 'PROVER_COORDINATION_NODE_URLS'
155
156
  | 'PROVER_FAILED_PROOF_STORE'
156
157
  | 'PROVER_NODE_FAILED_EPOCH_STORE'
@@ -175,6 +176,7 @@ export type EnvVar =
175
176
  | 'PROVER_TEST_VERIFICATION_DELAY_MS'
176
177
  | 'PXE_L2_BLOCK_BATCH_SIZE'
177
178
  | 'PXE_PROVER_ENABLED'
179
+ | 'PXE_SYNC_CHAIN_TIP'
178
180
  | 'RPC_MAX_BATCH_SIZE'
179
181
  | 'RPC_MAX_BODY_SIZE'
180
182
  | 'RPC_SIMULATE_PUBLIC_MAX_GAS_LIMIT'
@@ -246,7 +248,6 @@ export type EnvVar =
246
248
  | 'VALIDATOR_ADDRESSES'
247
249
  | 'ROLLUP_VERSION'
248
250
  | 'WS_BLOCK_CHECK_INTERVAL_MS'
249
- | 'WS_PROVEN_BLOCKS_ONLY'
250
251
  | 'WS_BLOCK_REQUEST_BATCH_SIZE'
251
252
  | 'L1_READER_VIEM_POLLING_INTERVAL_MS'
252
253
  | 'WS_DATA_DIRECTORY'
@@ -264,6 +265,7 @@ export type EnvVar =
264
265
  | 'AZTEC_LOCAL_EJECTION_THRESHOLD'
265
266
  | 'AZTEC_MANA_TARGET'
266
267
  | 'AZTEC_PROVING_COST_PER_MANA'
268
+ | 'AZTEC_INITIAL_ETH_PER_FEE_ASSET'
267
269
  | 'AZTEC_SLASHING_QUORUM'
268
270
  | 'AZTEC_SLASHING_ROUND_SIZE_IN_EPOCHS'
269
271
  | 'AZTEC_SLASHING_LIFETIME_IN_ROUNDS'
@@ -277,6 +279,7 @@ export type EnvVar =
277
279
  | 'AZTEC_SLASHER_FLAVOR'
278
280
  | 'AZTEC_GOVERNANCE_PROPOSER_QUORUM'
279
281
  | 'AZTEC_GOVERNANCE_PROPOSER_ROUND_SIZE'
282
+ | 'AZTEC_GOVERNANCE_VOTING_DURATION'
280
283
  | 'AZTEC_EXIT_DELAY_SECONDS'
281
284
  | 'L1_GAS_LIMIT_BUFFER_PERCENTAGE'
282
285
  | 'L1_GAS_PRICE_MAX'
@@ -303,7 +306,6 @@ export type EnvVar =
303
306
  | 'K8S_POD_UID'
304
307
  | 'K8S_NAMESPACE_NAME'
305
308
  | 'VALIDATOR_REEXECUTE_DEADLINE_MS'
306
- | 'ALWAYS_REEXECUTE_BLOCK_PROPOSALS'
307
309
  | 'AUTO_UPDATE'
308
310
  | 'AUTO_UPDATE_URL'
309
311
  | 'WEB3_SIGNER_URL'
@@ -313,11 +315,11 @@ export type EnvVar =
313
315
  | 'MAX_ALLOWED_ETH_CLIENT_DRIFT_SECONDS'
314
316
  | 'LEGACY_BLS_CLI'
315
317
  | 'DEBUG_FORCE_TX_PROOF_VERIFICATION'
316
- | 'SLASHING_PROTECTION_NODE_ID'
317
- | 'SLASHING_PROTECTION_POLLING_INTERVAL_MS'
318
- | 'SLASHING_PROTECTION_SIGNING_TIMEOUT_MS'
319
- | 'SLASHING_PROTECTION_ENABLED'
320
- | 'SLASHING_PROTECTION_MAX_STUCK_DUTIES_AGE_MS'
318
+ | 'VALIDATOR_HA_SIGNING_ENABLED'
319
+ | 'VALIDATOR_HA_NODE_ID'
320
+ | 'VALIDATOR_HA_POLLING_INTERVAL_MS'
321
+ | 'VALIDATOR_HA_SIGNING_TIMEOUT_MS'
322
+ | 'VALIDATOR_HA_MAX_STUCK_DUTIES_AGE_MS'
321
323
  | 'VALIDATOR_HA_DATABASE_URL'
322
324
  | 'VALIDATOR_HA_RUN_MIGRATIONS'
323
325
  | 'VALIDATOR_HA_POOL_MAX'
@@ -149,6 +149,23 @@ export function floatConfigHelper(
149
149
  };
150
150
  }
151
151
 
152
+ /**
153
+ * Parses an environment variable to a 0-1 percentage value
154
+ */
155
+ export function percentageConfigHelper(defaultVal: number): Pick<ConfigMapping, 'parseEnv' | 'defaultValue'> {
156
+ return {
157
+ parseEnv: (val: string): number => {
158
+ const parsed = safeParseFloat(val, defaultVal);
159
+ if (parsed < 0 || parsed > 1) {
160
+ throw new TypeError(`Invalid percentage value: ${parsed} should be between 0 and 1`);
161
+ }
162
+
163
+ return parsed;
164
+ },
165
+ defaultValue: defaultVal,
166
+ };
167
+ }
168
+
152
169
  /**
153
170
  * Generates parseEnv and default values for a numerical config value.
154
171
  * @param defaultVal - The default numerical value to use if the environment variable is not set or is invalid
@@ -35,16 +35,6 @@ export async function poseidon2HashWithSeparator(input: Fieldable[], separator:
35
35
  return Fr.fromBuffer(Buffer.from(response.hash));
36
36
  }
37
37
 
38
- export async function poseidon2HashAccumulate(input: Fieldable[]): Promise<Fr> {
39
- const inputFields = serializeToFields(input);
40
- await BarretenbergSync.initSingleton();
41
- const api = BarretenbergSync.getSingleton();
42
- const response = api.poseidon2HashAccumulate({
43
- inputs: inputFields.map(i => i.toBuffer()),
44
- });
45
- return Fr.fromBuffer(Buffer.from(response.hash));
46
- }
47
-
48
38
  /**
49
39
  * Runs a Poseidon2 permutation.
50
40
  * @param input the input state. Expected to be of size 4.
@@ -34,15 +34,6 @@ export function poseidon2HashWithSeparator(input: Fieldable[], separator: number
34
34
  return Fr.fromBuffer(Buffer.from(response.hash));
35
35
  }
36
36
 
37
- export function poseidon2HashAccumulate(input: Fieldable[]): Fr {
38
- const inputFields = serializeToFields(input);
39
- const api = BarretenbergSync.getSingleton();
40
- const response = api.poseidon2HashAccumulate({
41
- inputs: inputFields.map(i => i.toBuffer()),
42
- });
43
- return Fr.fromBuffer(Buffer.from(response.hash));
44
- }
45
-
46
37
  /**
47
38
  * Runs a Poseidon2 permutation.
48
39
  * @param input the input state. Expected to be of size 4.
@@ -1,3 +1,5 @@
1
+ import { promisify } from 'node:util';
2
+ import { gunzip as gunzipCb, gzip as gzipCb } from 'node:zlib';
1
3
  import { Agent, type Dispatcher } from 'undici';
2
4
 
3
5
  import { createLogger } from '../../log/pino-logger.js';
@@ -5,8 +7,14 @@ import { NoRetryError } from '../../retry/index.js';
5
7
  import { jsonStringify } from '../convert.js';
6
8
  import type { JsonRpcFetch } from './fetch.js';
7
9
 
10
+ const gzip = promisify(gzipCb);
11
+ const gunzip = promisify(gunzipCb);
12
+
8
13
  const log = createLogger('json-rpc:json_rpc_client:undici');
9
14
 
15
+ /** Minimum request size in bytes to trigger compression. */
16
+ const COMPRESSION_THRESHOLD = 1024;
17
+
10
18
  export { Agent };
11
19
 
12
20
  export function makeUndiciFetch(client = new Agent()): JsonRpcFetch {
@@ -14,14 +22,18 @@ export function makeUndiciFetch(client = new Agent()): JsonRpcFetch {
14
22
  log.trace(`JsonRpcClient.fetch: ${host}`, { host, body });
15
23
  let resp: Dispatcher.ResponseData;
16
24
  try {
25
+ const jsonBody = Buffer.from(jsonStringify(body));
26
+ const shouldCompress = jsonBody.length >= COMPRESSION_THRESHOLD;
17
27
  resp = await client.request({
18
28
  method: 'POST',
19
29
  origin: new URL(host),
20
30
  path: '/',
21
- body: jsonStringify(body),
31
+ body: shouldCompress ? await gzip(jsonBody) : jsonBody,
22
32
  headers: {
23
33
  ...extraHeaders,
24
34
  'content-type': 'application/json',
35
+ ...(shouldCompress && { 'content-encoding': 'gzip' }),
36
+ 'accept-encoding': 'gzip',
25
37
  },
26
38
  });
27
39
  } catch (err) {
@@ -31,13 +43,19 @@ export function makeUndiciFetch(client = new Agent()): JsonRpcFetch {
31
43
 
32
44
  let responseJson: any;
33
45
  const responseOk = resp.statusCode >= 200 && resp.statusCode <= 299;
46
+ const contentEncoding = resp.headers['content-encoding'];
34
47
  try {
35
- responseJson = await resp.body.json();
48
+ if (contentEncoding === 'gzip') {
49
+ const jsonBuffer = await gunzip(await resp.body.arrayBuffer());
50
+ responseJson = JSON.parse(jsonBuffer.toString('utf-8'));
51
+ } else {
52
+ responseJson = await resp.body.json();
53
+ }
36
54
  } catch {
37
55
  if (!responseOk) {
38
56
  throw new Error('HTTP ' + resp.statusCode);
39
57
  }
40
- throw new Error(`Failed to parse body as JSON: ${await resp.body.text()}`);
58
+ throw new Error(`Failed to parse body as JSON. encoding: ${contentEncoding}, body: ${await resp.body.text()}`);
41
59
  }
42
60
 
43
61
  if (!responseOk) {
@@ -35,7 +35,7 @@ export type SafeJsonRpcServerConfig = {
35
35
  const defaultServerConfig: SafeJsonRpcServerConfig = {
36
36
  http200OnError: false,
37
37
  maxBatchSize: 100,
38
- maxBodySizeBytes: '50mb',
38
+ maxBodySizeBytes: '1mb',
39
39
  };
40
40
 
41
41
  export class SafeJsonRpcServer {
@@ -103,3 +103,21 @@ export async function retryUntil<T>(
103
103
  }
104
104
  }
105
105
  }
106
+
107
+ /**
108
+ * Convenience wrapper around retryUntil with fast polling for tests.
109
+ * Uses 10s timeout and 100ms polling interval by default.
110
+ *
111
+ * @param fn - The function to retry until it returns a truthy value.
112
+ * @param name - Description of what we're waiting for (for error messages).
113
+ * @param timeout - Optional timeout in seconds. Defaults to 10s.
114
+ * @param interval - Optional interval in seconds. Defaults to 0.1s (100ms).
115
+ */
116
+ export function retryFastUntil<T>(
117
+ fn: () => (T | undefined) | Promise<T | undefined>,
118
+ name = '',
119
+ timeout = 10,
120
+ interval = 0.1,
121
+ ) {
122
+ return retryUntil(fn, name, timeout, interval);
123
+ }
@@ -224,15 +224,22 @@ export class BufferReader {
224
224
  * deserializing each one using the 'fromBuffer' method of 'itemDeserializer'.
225
225
  *
226
226
  * @param itemDeserializer - Object with 'fromBuffer' method to deserialize vector elements.
227
+ * @param maxSize - Optional maximum allowed size for the vector. If the size exceeds this, an error is thrown.
227
228
  * @returns An array of deserialized elements of type T.
228
229
  */
229
- public readVector<T>(itemDeserializer: {
230
- /**
231
- * A method to deserialize data from a buffer.
232
- */
233
- fromBuffer: (reader: BufferReader) => T;
234
- }): T[] {
230
+ public readVector<T>(
231
+ itemDeserializer: {
232
+ /**
233
+ * A method to deserialize data from a buffer.
234
+ */
235
+ fromBuffer: (reader: BufferReader) => T;
236
+ },
237
+ maxSize?: number,
238
+ ): T[] {
235
239
  const size = this.readNumber();
240
+ if (maxSize !== undefined && size > maxSize) {
241
+ throw new Error(`Vector size ${size} exceeds maximum allowed ${maxSize}`);
242
+ }
236
243
  const result = new Array<T>(size);
237
244
  for (let i = 0; i < size; i++) {
238
245
  result[i] = itemDeserializer.fromBuffer(this);
@@ -344,10 +351,11 @@ export class BufferReader {
344
351
  * The method first reads the size of the string, then reads the corresponding
345
352
  * number of bytes from the buffer and converts them to a string.
346
353
  *
354
+ * @param maxSize - Optional maximum allowed size for the string buffer. If the size exceeds this, an error is thrown.
347
355
  * @returns The read string from the buffer.
348
356
  */
349
- public readString(): string {
350
- return this.readBuffer().toString();
357
+ public readString(maxSize?: number): string {
358
+ return this.readBuffer(maxSize).toString();
351
359
  }
352
360
 
353
361
  /**
@@ -356,10 +364,14 @@ export class BufferReader {
356
364
  * a Buffer with that size containing the bytes. Useful for reading variable-length
357
365
  * binary data encoded as (size, data) format.
358
366
  *
367
+ * @param maxSize - Optional maximum allowed size for the buffer. If the size exceeds this, an error is thrown.
359
368
  * @returns A Buffer containing the read bytes.
360
369
  */
361
- public readBuffer(): Buffer {
370
+ public readBuffer(maxSize?: number): Buffer {
362
371
  const size = this.readNumber();
372
+ if (maxSize !== undefined && size > maxSize) {
373
+ throw new Error(`Buffer size ${size} exceeds maximum allowed ${maxSize}`);
374
+ }
363
375
  this.#rangeCheck(size);
364
376
  return this.readBytes(size);
365
377
  }
@@ -1,23 +1,7 @@
1
- import { pedersenHash as pedersenHashArray } from '@aztec/foundation/crypto/pedersen';
2
- import { poseidon2Hash } from '@aztec/foundation/crypto/poseidon';
3
- import { sha256Trunc } from '@aztec/foundation/crypto/sha256';
4
-
5
- import type { AsyncHasher, Hasher } from './hasher.js';
6
-
7
- export const shaMerkleHash: Hasher['hash'] = (left: Buffer, right: Buffer) =>
8
- sha256Trunc(Buffer.concat([left, right])) as Buffer<ArrayBuffer>;
9
-
10
- export const pedersenMerkleHash: AsyncHasher['hash'] = async (left: Buffer, right: Buffer) =>
11
- (await pedersenHashArray([left, right])).toBuffer() as Buffer<ArrayBuffer>;
12
-
13
- export const poseidonMerkleHash: AsyncHasher['hash'] = async (left: Buffer, right: Buffer) =>
14
- (await poseidon2Hash([left, right])).toBuffer() as Buffer<ArrayBuffer>;
1
+ import { poseidonMerkleHash, shaMerkleHash } from './hasher.js';
15
2
 
16
3
  export const computeBalancedShaRoot = (leaves: Buffer[]) => computeBalancedMerkleTreeRoot(leaves);
17
4
 
18
- export const computeBalancedPedersenRoot = async (leaves: Buffer[]) =>
19
- await computeBalancedMerkleTreeRootAsync(leaves, pedersenMerkleHash);
20
-
21
5
  export const computeBalancedPoseidonRoot = async (leaves: Buffer[]) =>
22
6
  await computeBalancedMerkleTreeRootAsync(leaves, poseidonMerkleHash);
23
7
 
@@ -46,7 +30,7 @@ export function computeBalancedMerkleTreeRoot(leaves: Buffer[], hasher = shaMerk
46
30
 
47
31
  /**
48
32
  * Computes the Merkle root with the provided leaves **asynchronously**.
49
- * This method uses an asynchronous hash function (defaults to `pedersenHash`).
33
+ * This method uses an asynchronous hash function (defaults to `poseidon2Hash`).
50
34
  *
51
35
  * @throws If the number of leaves is not a power of two.
52
36
  */
@@ -1,3 +1,6 @@
1
+ import { poseidon2Hash } from '../crypto/poseidon/index.js';
2
+ import { sha256Trunc } from '../crypto/sha256/index.js';
3
+
1
4
  /**
2
5
  * Defines hasher interface used by Merkle trees.
3
6
  */
@@ -37,3 +40,9 @@ export interface AsyncHasher {
37
40
  */
38
41
  hashInputs(inputs: Buffer[]): Promise<Buffer<ArrayBuffer>>;
39
42
  }
43
+
44
+ export const shaMerkleHash: Hasher['hash'] = (left: Buffer, right: Buffer) =>
45
+ sha256Trunc(Buffer.concat([left, right])) as Buffer<ArrayBuffer>;
46
+
47
+ export const poseidonMerkleHash: AsyncHasher['hash'] = async (left: Buffer, right: Buffer) =>
48
+ (await poseidon2Hash([left, right])).toBuffer() as Buffer<ArrayBuffer>;
@@ -1,6 +1,4 @@
1
- export * from './balanced_merkle_tree.js';
2
- export * from './unbalanced_merkle_tree.js';
3
- export * from './unbalanced_tree_store.js';
1
+ export * from './balanced_merkle_tree_root.js';
4
2
  export * from './merkle_tree_calculator.js';
5
3
  export * from './merkle_tree.js';
6
4
  export * from './indexed_merkle_tree_calculator.js';
@@ -10,3 +8,5 @@ export * from './membership_witness.js';
10
8
  export * from './hasher.js';
11
9
  export * from './indexed_tree_leaf.js';
12
10
  export * from './unbalanced_merkle_tree_calculator.js';
11
+ export * from './unbalanced_merkle_tree_root.js';
12
+ export * from './unbalanced_tree_store.js';
@@ -38,6 +38,14 @@ export class MembershipWitness<N extends number> {
38
38
  return [new Fr(this.leafIndex), ...this.siblingPath];
39
39
  }
40
40
 
41
+ /**
42
+ * Returns a representation of the membership witness as expected by intrinsic Noir deserialization.
43
+ */
44
+ public toNoirRepresentation(): (string | string[])[] {
45
+ // TODO(#12874): remove the stupid as string conversion by modifying ForeignCallOutput type in acvm.js
46
+ return [new Fr(this.leafIndex).toString() as string, this.siblingPath.map(fr => fr.toString()) as string[]];
47
+ }
48
+
41
49
  static schemaFor<N extends number>(size: N) {
42
50
  return schemas.Buffer.transform(b => MembershipWitness.fromBuffer(b, size));
43
51
  }
@@ -1,4 +1,4 @@
1
- import { pedersenHash } from '@aztec/foundation/crypto/pedersen';
1
+ import { poseidon2Hash } from '@aztec/foundation/crypto/poseidon';
2
2
 
3
3
  import type { AsyncHasher } from './hasher.js';
4
4
  import { MerkleTree } from './merkle_tree.js';
@@ -19,7 +19,7 @@ export class MerkleTreeCalculator {
19
19
  height: number,
20
20
  zeroLeaf: Buffer = Buffer.alloc(32),
21
21
  hasher = async (left: Buffer, right: Buffer) =>
22
- (await pedersenHash([left, right])).toBuffer() as Buffer<ArrayBuffer>,
22
+ (await poseidon2Hash([left, right])).toBuffer() as Buffer<ArrayBuffer>,
23
23
  ) {
24
24
  const zeroHashes = [zeroLeaf];
25
25
  for (let i = 0; i < height; i++) {
@@ -1,5 +1,5 @@
1
1
  import { makeTuple } from '../array/array.js';
2
- import { pedersenHash } from '../crypto/pedersen/index.js';
2
+ import { poseidon2Hash } from '../crypto/poseidon/index.js';
3
3
  import { Fr } from '../curves/bn254/index.js';
4
4
  import { schemas } from '../schemas/index.js';
5
5
  import {
@@ -172,7 +172,7 @@ export async function computeRootFromSiblingPath(
172
172
  leaf: Buffer,
173
173
  siblingPath: Buffer[],
174
174
  index: number,
175
- hasher = async (left: Buffer, right: Buffer) => (await pedersenHash([left, right])).toBuffer(),
175
+ hasher = async (left: Buffer, right: Buffer) => (await poseidon2Hash([left, right])).toBuffer(),
176
176
  ) {
177
177
  let result = leaf;
178
178
  for (const sibling of siblingPath) {
@@ -1,5 +1,4 @@
1
- import { shaMerkleHash } from './balanced_merkle_tree.js';
2
- import type { Hasher } from './hasher.js';
1
+ import { type Hasher, shaMerkleHash } from './hasher.js';
3
2
  import { SiblingPath } from './sibling_path.js';
4
3
  import { type TreeNodeLocation, UnbalancedTreeStore } from './unbalanced_tree_store.js';
5
4
 
@@ -1,9 +1,5 @@
1
- import {
2
- computeBalancedMerkleTreeRoot,
3
- computeBalancedMerkleTreeRootAsync,
4
- poseidonMerkleHash,
5
- shaMerkleHash,
6
- } from './balanced_merkle_tree.js';
1
+ import { computeBalancedMerkleTreeRoot, computeBalancedMerkleTreeRootAsync } from './balanced_merkle_tree_root.js';
2
+ import { poseidonMerkleHash, shaMerkleHash } from './hasher.js';
7
3
  import { UnbalancedMerkleTreeCalculator } from './unbalanced_merkle_tree_calculator.js';
8
4
 
9
5
  export const computeUnbalancedShaRoot = (leaves: Buffer[]) => computeUnbalancedMerkleTreeRoot(leaves, shaMerkleHash);
@@ -11,8 +7,7 @@ export const computeUnbalancedShaRoot = (leaves: Buffer[]) => computeUnbalancedM
11
7
  export const computeUnbalancedPoseidonRoot = async (leaves: Buffer[]) =>
12
8
  await computeUnbalancedMerkleTreeRootAsync(leaves, poseidonMerkleHash);
13
9
 
14
- export const computeCompressedUnbalancedShaRoot = (leaves: Buffer[]) =>
15
- computeCompressedUnbalancedMerkleTreeRoot(leaves);
10
+ export const computeWonkyShaRoot = (leaves: Buffer[]) => computeWonkyMerkleTreeRoot(leaves);
16
11
 
17
12
  /**
18
13
  * Computes the Merkle root of an unbalanced tree.
@@ -105,7 +100,11 @@ export async function computeUnbalancedMerkleTreeRootAsync(
105
100
  return root!;
106
101
  }
107
102
 
108
- export function computeCompressedUnbalancedMerkleTreeRoot(
103
+ // A **wonky** tree is a "compressed" unbalanced Merkle tree.
104
+ // It is constructed in the same way as an unbalanced tree: by first creating the largest possible left subtree, with
105
+ // the remaining leaves forming a right subtree that follows the same process recursively.
106
+ // During construction, leaves equal to `valueToCompress` are skipped (compressed) and do not contribute to the tree.
107
+ export function computeWonkyMerkleTreeRoot(
109
108
  leaves: Buffer[],
110
109
  valueToCompress = Buffer.alloc(32),
111
110
  emptyRoot = Buffer.alloc(32),
@@ -114,60 +113,3 @@ export function computeCompressedUnbalancedMerkleTreeRoot(
114
113
  const calculator = UnbalancedMerkleTreeCalculator.create(leaves, valueToCompress, emptyRoot, hasher);
115
114
  return calculator.getRoot();
116
115
  }
117
-
118
- /// Get the depth of the maximum balanced tree that can be created with the given number of leaves. The subtree will be
119
- /// the left most subtree of the wonky tree with a total of `numLeaves` leaves.
120
- ///
121
- /// Note: All the leaves may not be used to form the tree. For example, if there are 5 leaves, the maximum depth is 2,
122
- /// only 4 leaves are used to form a balanced tree.
123
- function getMaxBalancedSubtreeDepth(numLeaves: number) {
124
- return Math.floor(Math.log2(numLeaves));
125
- }
126
-
127
- /// Get the maximum depth of an unbalanced tree that can be created with the given number of leaves.
128
- function getMaxUnbalancedTreeDepth(numLeaves: number) {
129
- return Math.ceil(Math.log2(numLeaves));
130
- }
131
-
132
- function findPosition(
133
- rootLevel: number,
134
- leafLevel: number,
135
- numLeaves: number,
136
- indexOffset: number,
137
- targetIndex: number,
138
- ): { level: number; indexAtLevel: number } {
139
- if (numLeaves <= 1) {
140
- // Single leaf.
141
- return { level: rootLevel, indexAtLevel: indexOffset };
142
- }
143
-
144
- // The largest balanced tree that can be created with the given number of leaves.
145
- const maxBalancedTreeDepth = getMaxBalancedSubtreeDepth(numLeaves);
146
- const numBalancedLeaves = 2 ** maxBalancedTreeDepth;
147
- const numRemainingLeaves = numLeaves - numBalancedLeaves;
148
-
149
- if (targetIndex < numBalancedLeaves) {
150
- // Target is in the balanced tree.
151
-
152
- // - If numRemainingLeaves is 0: this balanced tree is grown from the current root.
153
- // - If numRemainingLeaves is not 0: the remaining leaves will form another tree, which will become the right child of the root.
154
- // And the balanced tree will be the left child of the root.
155
- // There will be an extra level between the root of the balanced tree and the current root.
156
- const extraLevel = numRemainingLeaves ? 1 : 0;
157
-
158
- return { level: rootLevel + maxBalancedTreeDepth + extraLevel, indexAtLevel: indexOffset + targetIndex };
159
- } else {
160
- // Target is in the right branch.
161
- const rightBranchMaxLevel = getMaxUnbalancedTreeDepth(numRemainingLeaves);
162
- const shiftedUp = leafLevel - rootLevel - rightBranchMaxLevel - 1;
163
- const nextLeafLevel = leafLevel - shiftedUp;
164
- const newIndexOffset = (indexOffset + numBalancedLeaves) >> shiftedUp;
165
- const shiftedTargetIndex = targetIndex - numBalancedLeaves;
166
- return findPosition(rootLevel + 1, nextLeafLevel, numRemainingLeaves, newIndexOffset, shiftedTargetIndex);
167
- }
168
- }
169
-
170
- export function findLeafLevelAndIndex(numLeaves: number, leafIndex: number) {
171
- const maxLevel = getMaxUnbalancedTreeDepth(numLeaves);
172
- return findPosition(0, maxLevel, numLeaves, 0, leafIndex);
173
- }
@@ -1,5 +1,3 @@
1
- import { findLeafLevelAndIndex } from './unbalanced_merkle_tree.js';
2
-
3
1
  export interface TreeNodeLocation {
4
2
  level: number;
5
3
  index: number;
@@ -104,3 +102,60 @@ export class UnbalancedTreeStore<T> {
104
102
  return `${location.level}-${location.index}`;
105
103
  }
106
104
  }
105
+
106
+ /// Get the depth of the maximum balanced tree that can be created with the given number of leaves. The subtree will be
107
+ /// the left most subtree of the unbalanced tree with a total of `numLeaves` leaves.
108
+ ///
109
+ /// Note: All the leaves may not be used to form the tree. For example, if there are 5 leaves, the maximum depth is 2,
110
+ /// only 4 leaves are used to form a balanced tree.
111
+ function getMaxBalancedSubtreeDepth(numLeaves: number) {
112
+ return Math.floor(Math.log2(numLeaves));
113
+ }
114
+
115
+ /// Get the maximum depth of an unbalanced tree that can be created with the given number of leaves.
116
+ function getMaxUnbalancedTreeDepth(numLeaves: number) {
117
+ return Math.ceil(Math.log2(numLeaves));
118
+ }
119
+
120
+ function findPosition(
121
+ rootLevel: number,
122
+ leafLevel: number,
123
+ numLeaves: number,
124
+ indexOffset: number,
125
+ targetIndex: number,
126
+ ): { level: number; indexAtLevel: number } {
127
+ if (numLeaves <= 1) {
128
+ // Single leaf.
129
+ return { level: rootLevel, indexAtLevel: indexOffset };
130
+ }
131
+
132
+ // The largest balanced tree that can be created with the given number of leaves.
133
+ const maxBalancedTreeDepth = getMaxBalancedSubtreeDepth(numLeaves);
134
+ const numBalancedLeaves = 2 ** maxBalancedTreeDepth;
135
+ const numRemainingLeaves = numLeaves - numBalancedLeaves;
136
+
137
+ if (targetIndex < numBalancedLeaves) {
138
+ // Target is in the balanced tree.
139
+
140
+ // - If numRemainingLeaves is 0: this balanced tree is grown from the current root.
141
+ // - If numRemainingLeaves is not 0: the remaining leaves will form another tree, which will become the right child of the root.
142
+ // And the balanced tree will be the left child of the root.
143
+ // There will be an extra level between the root of the balanced tree and the current root.
144
+ const extraLevel = numRemainingLeaves ? 1 : 0;
145
+
146
+ return { level: rootLevel + maxBalancedTreeDepth + extraLevel, indexAtLevel: indexOffset + targetIndex };
147
+ } else {
148
+ // Target is in the right branch.
149
+ const rightBranchMaxLevel = getMaxUnbalancedTreeDepth(numRemainingLeaves);
150
+ const shiftedUp = leafLevel - rootLevel - rightBranchMaxLevel - 1;
151
+ const nextLeafLevel = leafLevel - shiftedUp;
152
+ const newIndexOffset = (indexOffset + numBalancedLeaves) >> shiftedUp;
153
+ const shiftedTargetIndex = targetIndex - numBalancedLeaves;
154
+ return findPosition(rootLevel + 1, nextLeafLevel, numRemainingLeaves, newIndexOffset, shiftedTargetIndex);
155
+ }
156
+ }
157
+
158
+ export function findLeafLevelAndIndex(numLeaves: number, leafIndex: number) {
159
+ const maxLevel = getMaxUnbalancedTreeDepth(numLeaves);
160
+ return findPosition(0, maxLevel, numLeaves, 0, leafIndex);
161
+ }
@@ -33,7 +33,7 @@ export type Prettify<T> = {
33
33
  * Type-safe Event Emitter type
34
34
  * @example
35
35
  * export type ArchiverEmitter = TypedEventEmitter<{
36
- * [L2BlockSourceEvents.L2PruneDetected]: (args: L2BlockSourceEvent) => void;
36
+ * [L2BlockSourceEvents.L2PruneUnproven]: (args: L2BlockSourceEvent) => void;
37
37
  * [L2BlockSourceEvents.L2BlockProven]: (args: L2BlockSourceEvent) => void;
38
38
  * }>;
39
39
  * class Archiver extends (EventEmitter as new () => ArchiverEmitter) {
@@ -1,22 +0,0 @@
1
- import type { AsyncHasher, Hasher } from './hasher.js';
2
- export declare const shaMerkleHash: Hasher['hash'];
3
- export declare const pedersenMerkleHash: AsyncHasher['hash'];
4
- export declare const poseidonMerkleHash: AsyncHasher['hash'];
5
- export declare const computeBalancedShaRoot: (leaves: Buffer<ArrayBufferLike>[]) => Buffer<ArrayBufferLike>;
6
- export declare const computeBalancedPedersenRoot: (leaves: Buffer<ArrayBufferLike>[]) => Promise<Buffer<ArrayBufferLike>>;
7
- export declare const computeBalancedPoseidonRoot: (leaves: Buffer<ArrayBufferLike>[]) => Promise<Buffer<ArrayBufferLike>>;
8
- /**
9
- * Computes the Merkle root with the provided leaves **synchronously**.
10
- * This method uses a synchronous hash function (defaults to `sha256Trunc`).
11
- *
12
- * @throws If the number of leaves is not a power of two.
13
- */
14
- export declare function computeBalancedMerkleTreeRoot(leaves: Buffer[], hasher?: (lhs: Uint8Array<ArrayBufferLike>, rhs: Uint8Array<ArrayBufferLike>) => Buffer<ArrayBuffer>): Buffer;
15
- /**
16
- * Computes the Merkle root with the provided leaves **asynchronously**.
17
- * This method uses an asynchronous hash function (defaults to `pedersenHash`).
18
- *
19
- * @throws If the number of leaves is not a power of two.
20
- */
21
- export declare function computeBalancedMerkleTreeRootAsync(leaves: Buffer[], hasher?: (lhs: Uint8Array<ArrayBufferLike>, rhs: Uint8Array<ArrayBufferLike>) => Promise<Buffer<ArrayBuffer>>): Promise<Buffer>;
22
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFsYW5jZWRfbWVya2xlX3RyZWUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90cmVlcy9iYWxhbmNlZF9tZXJrbGVfdHJlZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFJQSxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXZELGVBQU8sTUFBTSxhQUFhLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FDeUIsQ0FBQztBQUVuRSxlQUFPLE1BQU0sa0JBQWtCLEVBQUUsV0FBVyxDQUFDLE1BQU0sQ0FDeUIsQ0FBQztBQUU3RSxlQUFPLE1BQU0sa0JBQWtCLEVBQUUsV0FBVyxDQUFDLE1BQU0sQ0FDcUIsQ0FBQztBQUV6RSxlQUFPLE1BQU0sc0JBQXNCLGdFQUE4RCxDQUFDO0FBRWxHLGVBQU8sTUFBTSwyQkFBMkIseUVBQzhCLENBQUM7QUFFdkUsZUFBTyxNQUFNLDJCQUEyQix5RUFDOEIsQ0FBQztBQUV2RTs7Ozs7R0FLRztBQUNILHdCQUFnQiw2QkFBNkIsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsTUFBTSw4RkFBZ0IsR0FBRyxNQUFNLENBZTlGO0FBRUQ7Ozs7O0dBS0c7QUFDSCx3QkFBc0Isa0NBQWtDLENBQ3RELE1BQU0sRUFBRSxNQUFNLEVBQUUsRUFDaEIsTUFBTSx1R0FBcUIsR0FDMUIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQWVqQiJ9
@@ -1 +0,0 @@
1
- {"version":3,"file":"balanced_merkle_tree.d.ts","sourceRoot":"","sources":["../../src/trees/balanced_merkle_tree.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,CACyB,CAAC;AAEnE,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CACyB,CAAC;AAE7E,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CACqB,CAAC;AAEzE,eAAO,MAAM,sBAAsB,gEAA8D,CAAC;AAElG,eAAO,MAAM,2BAA2B,yEAC8B,CAAC;AAEvE,eAAO,MAAM,2BAA2B,yEAC8B,CAAC;AAEvE;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,MAAM,8FAAgB,GAAG,MAAM,CAe9F;AAED;;;;;GAKG;AACH,wBAAsB,kCAAkC,CACtD,MAAM,EAAE,MAAM,EAAE,EAChB,MAAM,uGAAqB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAejB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"unbalanced_merkle_tree.d.ts","sourceRoot":"","sources":["../../src/trees/unbalanced_merkle_tree.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,wBAAwB,gEAA+E,CAAC;AAErH,eAAO,MAAM,6BAA6B,yEAC8B,CAAC;AAEzE,eAAO,MAAM,kCAAkC,gEACI,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,MAAM,EAAE,EAChB,MAAM,8FAAgB,EACtB,SAAS,sBAAmB,GAC3B,MAAM,CA6BR;AAED,wBAAsB,oCAAoC,CACxD,MAAM,EAAE,MAAM,EAAE,EAChB,MAAM,uGAAqB,EAC3B,SAAS,sBAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,CA6BjB;AAED,wBAAgB,yCAAyC,CACvD,MAAM,EAAE,MAAM,EAAE,EAChB,eAAe,sBAAmB,EAClC,SAAS,sBAAmB,EAC5B,MAAM,8FAAgB,GACrB,MAAM,CAGR;AAsDD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;;;EAGzE"}