@aztec/foundation 0.72.1 → 0.74.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 (123) hide show
  1. package/dest/abi/abi.d.ts +3 -2
  2. package/dest/abi/abi.d.ts.map +1 -1
  3. package/dest/abi/abi.js +22 -5
  4. package/dest/abi/encoder.js +2 -2
  5. package/dest/abi/event_selector.d.ts +1 -1
  6. package/dest/abi/event_selector.d.ts.map +1 -1
  7. package/dest/abi/event_selector.js +3 -3
  8. package/dest/abi/function_selector.d.ts +3 -13
  9. package/dest/abi/function_selector.d.ts.map +1 -1
  10. package/dest/abi/function_selector.js +5 -16
  11. package/dest/abi/u128.js +1 -1
  12. package/dest/blob/blob.d.ts +154 -0
  13. package/dest/blob/blob.d.ts.map +1 -0
  14. package/dest/blob/blob.js +264 -0
  15. package/dest/blob/encoding.d.ts +53 -0
  16. package/dest/blob/encoding.d.ts.map +1 -0
  17. package/dest/blob/encoding.js +87 -0
  18. package/dest/blob/errors.d.ts +4 -0
  19. package/dest/blob/errors.d.ts.map +1 -0
  20. package/dest/blob/errors.js +7 -0
  21. package/dest/blob/index.d.ts +5 -58
  22. package/dest/blob/index.d.ts.map +1 -1
  23. package/dest/blob/index.js +7 -142
  24. package/dest/blob/interface.d.ts +10 -0
  25. package/dest/blob/interface.d.ts.map +1 -0
  26. package/dest/blob/interface.js +2 -0
  27. package/dest/blob/mocks.d.ts +20 -0
  28. package/dest/blob/mocks.d.ts.map +1 -0
  29. package/dest/blob/mocks.js +42 -0
  30. package/dest/config/env_var.d.ts +1 -1
  31. package/dest/config/env_var.d.ts.map +1 -1
  32. package/dest/config/index.d.ts +1 -0
  33. package/dest/config/index.d.ts.map +1 -1
  34. package/dest/config/index.js +11 -14
  35. package/dest/crypto/index.d.ts +0 -7
  36. package/dest/crypto/index.d.ts.map +1 -1
  37. package/dest/crypto/index.js +1 -11
  38. package/dest/crypto/keys/index.d.ts +1 -1
  39. package/dest/crypto/keys/index.d.ts.map +1 -1
  40. package/dest/crypto/keys/index.js +5 -5
  41. package/dest/crypto/pedersen/pedersen.wasm.d.ts +3 -3
  42. package/dest/crypto/pedersen/pedersen.wasm.d.ts.map +1 -1
  43. package/dest/crypto/pedersen/pedersen.wasm.js +13 -10
  44. package/dest/crypto/poseidon/index.d.ts +5 -5
  45. package/dest/crypto/poseidon/index.d.ts.map +1 -1
  46. package/dest/crypto/poseidon/index.js +20 -19
  47. package/dest/crypto/sync/index.d.ts +3 -0
  48. package/dest/crypto/sync/index.d.ts.map +1 -0
  49. package/dest/crypto/sync/index.js +5 -0
  50. package/dest/crypto/sync/pedersen/index.d.ts +21 -0
  51. package/dest/crypto/sync/pedersen/index.d.ts.map +1 -0
  52. package/dest/crypto/sync/pedersen/index.js +37 -0
  53. package/dest/crypto/sync/poseidon/index.d.ts +26 -0
  54. package/dest/crypto/sync/poseidon/index.d.ts.map +1 -0
  55. package/dest/crypto/sync/poseidon/index.js +57 -0
  56. package/dest/fields/fields.js +4 -4
  57. package/dest/fields/point.d.ts +1 -1
  58. package/dest/iterable/toArray.d.ts +1 -1
  59. package/dest/iterable/toArray.d.ts.map +1 -1
  60. package/dest/iterable/toArray.js +1 -1
  61. package/dest/json-rpc/client/safe_json_rpc_client.js +2 -2
  62. package/dest/json-rpc/convert.d.ts +1 -1
  63. package/dest/json-rpc/convert.d.ts.map +1 -1
  64. package/dest/json-rpc/convert.js +2 -2
  65. package/dest/json-rpc/server/safe_json_rpc_server.d.ts.map +1 -1
  66. package/dest/json-rpc/server/safe_json_rpc_server.js +4 -2
  67. package/dest/message/index.d.ts +32 -0
  68. package/dest/message/index.d.ts.map +1 -0
  69. package/dest/message/index.js +23 -0
  70. package/dest/mutex/index.d.ts.map +1 -1
  71. package/dest/mutex/index.js +6 -4
  72. package/dest/promise/running-promise.d.ts +2 -1
  73. package/dest/promise/running-promise.d.ts.map +1 -1
  74. package/dest/promise/running-promise.js +6 -3
  75. package/dest/schemas/parse.d.ts +1 -1
  76. package/dest/schemas/parse.d.ts.map +1 -1
  77. package/dest/schemas/parse.js +2 -2
  78. package/dest/serialize/field_reader.d.ts +18 -0
  79. package/dest/serialize/field_reader.d.ts.map +1 -1
  80. package/dest/serialize/field_reader.js +32 -2
  81. package/dest/worker/browser/start_web_module.d.ts.map +1 -1
  82. package/dest/worker/browser/start_web_module.js +2 -1
  83. package/dest/worker/browser/web_worker.d.ts.map +1 -1
  84. package/dest/worker/browser/web_worker.js +2 -1
  85. package/dest/worker/node/node_worker.d.ts.map +1 -1
  86. package/dest/worker/node/node_worker.js +2 -1
  87. package/dest/worker/node/start_node_module.d.ts.map +1 -1
  88. package/dest/worker/node/start_node_module.js +2 -1
  89. package/package.json +5 -3
  90. package/src/abi/abi.ts +28 -8
  91. package/src/abi/encoder.ts +1 -1
  92. package/src/abi/event_selector.ts +2 -2
  93. package/src/abi/function_selector.ts +7 -27
  94. package/src/abi/u128.ts +1 -1
  95. package/src/blob/blob.ts +311 -0
  96. package/src/blob/encoding.ts +98 -0
  97. package/src/blob/errors.ts +6 -0
  98. package/src/blob/index.ts +6 -183
  99. package/src/blob/interface.ts +11 -0
  100. package/src/blob/mocks.ts +48 -0
  101. package/src/config/env_var.ts +7 -4
  102. package/src/config/index.ts +10 -12
  103. package/src/crypto/index.ts +0 -12
  104. package/src/crypto/keys/index.ts +5 -4
  105. package/src/crypto/pedersen/pedersen.wasm.ts +13 -14
  106. package/src/crypto/poseidon/index.ts +24 -39
  107. package/src/crypto/sync/index.ts +6 -0
  108. package/src/crypto/sync/pedersen/index.ts +45 -0
  109. package/src/crypto/sync/poseidon/index.ts +76 -0
  110. package/src/fields/fields.ts +3 -3
  111. package/src/iterable/toArray.ts +3 -1
  112. package/src/json-rpc/client/safe_json_rpc_client.ts +1 -1
  113. package/src/json-rpc/convert.ts +2 -2
  114. package/src/json-rpc/server/safe_json_rpc_server.ts +3 -1
  115. package/src/message/index.ts +43 -0
  116. package/src/mutex/index.ts +5 -4
  117. package/src/promise/running-promise.ts +4 -1
  118. package/src/schemas/parse.ts +2 -2
  119. package/src/serialize/field_reader.ts +34 -1
  120. package/src/worker/browser/start_web_module.ts +1 -0
  121. package/src/worker/browser/web_worker.ts +1 -0
  122. package/src/worker/node/node_worker.ts +1 -0
  123. package/src/worker/node/start_node_module.ts +1 -0
@@ -16,6 +16,8 @@ export type EnvVar =
16
16
  | 'BB_SKIP_CLEANUP'
17
17
  | 'BB_WORKING_DIRECTORY'
18
18
  | 'BOOTSTRAP_NODES'
19
+ | 'BLOB_SINK_PORT'
20
+ | 'BLOB_SINK_URL'
19
21
  | 'BOT_DA_GAS_LIMIT'
20
22
  | 'BOT_FEE_PAYMENT_METHOD'
21
23
  | 'BOT_FLUSH_SETUP_TRANSACTIONS'
@@ -51,7 +53,9 @@ export type EnvVar =
51
53
  | 'GOVERNANCE_PROPOSER_PAYLOAD_ADDRESS'
52
54
  | 'INBOX_CONTRACT_ADDRESS'
53
55
  | 'L1_CHAIN_ID'
54
- | 'L1_CONSENSUS_CLIENT_URL'
56
+ | 'L1_CONSENSUS_HOST_URL'
57
+ | 'L1_CONSENSUS_HOST_API_KEY'
58
+ | 'L1_CONSENSUS_HOST_API_KEY_HEADER'
55
59
  | 'L1_PRIVATE_KEY'
56
60
  | 'L2_QUEUE_SIZE'
57
61
  | 'LOG_ELAPSED_TIME'
@@ -102,7 +106,6 @@ export type EnvVar =
102
106
  | 'P2P_UDP_LISTEN_ADDR'
103
107
  | 'P2P_ARCHIVED_TX_LIMIT'
104
108
  | 'PEER_ID_PRIVATE_KEY'
105
- | 'PROVER_BLOB_SINK_URL'
106
109
  | 'PROOF_VERIFIER_L1_START_BLOCK'
107
110
  | 'PROOF_VERIFIER_POLL_INTERVAL_MS'
108
111
  | 'PROVER_AGENT_ENABLED'
@@ -142,7 +145,6 @@ export type EnvVar =
142
145
  | 'REGISTRY_CONTRACT_ADDRESS'
143
146
  | 'ROLLUP_CONTRACT_ADDRESS'
144
147
  | 'SEQ_ALLOWED_SETUP_FN'
145
- | 'SEQ_BLOB_SINK_URL'
146
148
  | 'SEQ_MAX_BLOCK_SIZE_IN_BYTES'
147
149
  | 'SEQ_MAX_TX_PER_BLOCK'
148
150
  | 'SEQ_MIN_TX_PER_BLOCK'
@@ -205,4 +207,5 @@ export type EnvVar =
205
207
  | 'FAUCET_L1_ASSETS'
206
208
  | 'K8S_POD_NAME'
207
209
  | 'K8S_POD_UID'
208
- | 'K8S_NAMESPACE_NAME';
210
+ | 'K8S_NAMESPACE_NAME'
211
+ | 'CUSTOM_FORWARDER_CONTRACT_ADDRESS';
@@ -9,6 +9,7 @@ export interface ConfigMapping {
9
9
  printDefault?: (val: any) => string;
10
10
  description: string;
11
11
  isBoolean?: boolean;
12
+ nested?: Record<string, ConfigMapping>;
12
13
  }
13
14
 
14
15
  export function isBooleanConfigValue<T>(obj: T, key: keyof T): boolean {
@@ -21,18 +22,15 @@ export function getConfigFromMappings<T>(configMappings: ConfigMappingsType<T>):
21
22
  const config = {} as T;
22
23
 
23
24
  for (const key in configMappings) {
24
- if (configMappings[key]) {
25
- const { env, parseEnv, defaultValue: def } = configMappings[key];
26
- // Special case for L1 contract addresses which is an object of config values
27
- if (key === 'l1Contracts' && def) {
28
- (config as any)[key] = getConfigFromMappings(def);
29
- } else {
30
- const val = env ? process.env[env] : undefined;
31
- if (val !== undefined) {
32
- (config as any)[key] = parseEnv ? parseEnv(val) : val;
33
- } else if (def !== undefined) {
34
- (config as any)[key] = def;
35
- }
25
+ const { env, parseEnv, defaultValue: def, nested } = configMappings[key];
26
+ if (nested) {
27
+ (config as any)[key] = getConfigFromMappings(nested);
28
+ } else {
29
+ const val = env ? process.env[env] : undefined;
30
+ if (val !== undefined) {
31
+ (config as any)[key] = parseEnv ? parseEnv(val) : val;
32
+ } else if (def !== undefined) {
33
+ (config as any)[key] = def;
36
34
  }
37
35
  }
38
36
  }
@@ -1,5 +1,3 @@
1
- import { BarretenbergSync } from '@aztec/bb.js';
2
-
3
1
  export * from './keccak/index.js';
4
2
  export * from './random/index.js';
5
3
  export * from './sha256/index.js';
@@ -8,13 +6,3 @@ export * from './pedersen/index.js';
8
6
  export * from './poseidon/index.js';
9
7
  export * from './secp256k1-signer/index.js';
10
8
  export * from './keys/index.js';
11
-
12
- /**
13
- * Init the bb singleton. This constructs (if not already) the barretenberg sync api within bb.js itself.
14
- * It takes about 100-200ms to initialize. It may not seem like much, but when in conjunction with many other things
15
- * initializing, developers may want to pick precisely when to incur this cost.
16
- * If in a test environment, we'll just do it on module load.
17
- */
18
- export async function init() {
19
- await BarretenbergSync.initSingleton();
20
- }
@@ -2,8 +2,9 @@ import { BarretenbergSync, RawBuffer } from '@aztec/bb.js';
2
2
 
3
3
  import { Fr } from '../../fields/fields.js';
4
4
 
5
- export function vkAsFieldsMegaHonk(input: Buffer): Fr[] {
6
- return BarretenbergSync.getSingleton()
7
- .acirVkAsFieldsMegaHonk(new RawBuffer(input))
8
- .map(bbFr => Fr.fromBuffer(Buffer.from(bbFr.toBuffer()))); // TODO(#4189): remove this conversion
5
+ export async function vkAsFieldsMegaHonk(input: Buffer): Promise<Fr[]> {
6
+ const api = await BarretenbergSync.initSingleton();
7
+ const result = api.acirVkAsFieldsMegaHonk(new RawBuffer(input));
8
+
9
+ return result.map(bbFr => Fr.fromBuffer(Buffer.from(bbFr.toBuffer()))); // TODO(#4189): remove this conversion
9
10
  }
@@ -7,12 +7,13 @@ import { type Fieldable, serializeToFields } from '../../serialize/serialize.js'
7
7
  * Create a pedersen commitment (point) from an array of input fields.
8
8
  * Left pads any inputs less than 32 bytes.
9
9
  */
10
- export function pedersenCommit(input: Buffer[], offset = 0) {
10
+ export async function pedersenCommit(input: Buffer[], offset = 0) {
11
11
  if (!input.every(i => i.length <= 32)) {
12
12
  throw new Error('All Pedersen Commit input buffers must be <= 32 bytes.');
13
13
  }
14
14
  input = input.map(i => (i.length < 32 ? Buffer.concat([Buffer.alloc(32 - i.length, 0), i]) : i));
15
- const point = BarretenbergSync.getSingleton().pedersenCommit(
15
+ const api = await BarretenbergSync.initSingleton();
16
+ const point = api.pedersenCommit(
16
17
  input.map(i => new FrBarretenberg(i)),
17
18
  offset,
18
19
  );
@@ -27,23 +28,21 @@ export function pedersenCommit(input: Buffer[], offset = 0) {
27
28
  * @param index - The separator index to use for the hash.
28
29
  * @returns The pedersen hash.
29
30
  */
30
- export function pedersenHash(input: Fieldable[], index = 0): Fr {
31
+ export async function pedersenHash(input: Fieldable[], index = 0): Promise<Fr> {
31
32
  const inputFields = serializeToFields(input);
32
- return Fr.fromBuffer(
33
- Buffer.from(
34
- BarretenbergSync.getSingleton()
35
- .pedersenHash(
36
- inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
37
- index,
38
- )
39
- .toBuffer(),
40
- ),
33
+ const api = await BarretenbergSync.initSingleton();
34
+ const hash = api.pedersenHash(
35
+ inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
36
+ index,
41
37
  );
38
+ return Fr.fromBuffer(Buffer.from(hash.toBuffer()));
42
39
  }
43
40
 
44
41
  /**
45
42
  * Create a pedersen hash from an arbitrary length buffer.
46
43
  */
47
- export function pedersenHashBuffer(input: Buffer, index = 0) {
48
- return Buffer.from(BarretenbergSync.getSingleton().pedersenHashBuffer(input, index).toBuffer());
44
+ export async function pedersenHashBuffer(input: Buffer, index = 0) {
45
+ const api = await BarretenbergSync.initSingleton();
46
+ const result = api.pedersenHashBuffer(input, index);
47
+ return Buffer.from(result.toBuffer());
49
48
  }
@@ -8,17 +8,13 @@ import { type Fieldable, serializeToFields } from '../../serialize/serialize.js'
8
8
  * @param input - The input fields to hash.
9
9
  * @returns The poseidon hash.
10
10
  */
11
- export function poseidon2Hash(input: Fieldable[]): Fr {
11
+ export async function poseidon2Hash(input: Fieldable[]): Promise<Fr> {
12
12
  const inputFields = serializeToFields(input);
13
- return Fr.fromBuffer(
14
- Buffer.from(
15
- BarretenbergSync.getSingleton()
16
- .poseidon2Hash(
17
- inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
18
- )
19
- .toBuffer(),
20
- ),
13
+ const api = await BarretenbergSync.initSingleton();
14
+ const hash = api.poseidon2Hash(
15
+ inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
21
16
  );
17
+ return Fr.fromBuffer(Buffer.from(hash.toBuffer()));
22
18
  }
23
19
 
24
20
  /**
@@ -27,29 +23,22 @@ export function poseidon2Hash(input: Fieldable[]): Fr {
27
23
  * @param separator - The domain separator.
28
24
  * @returns The poseidon hash.
29
25
  */
30
- export function poseidon2HashWithSeparator(input: Fieldable[], separator: number): Fr {
26
+ export async function poseidon2HashWithSeparator(input: Fieldable[], separator: number): Promise<Fr> {
31
27
  const inputFields = serializeToFields(input);
32
28
  inputFields.unshift(new Fr(separator));
33
- return Fr.fromBuffer(
34
- Buffer.from(
35
- BarretenbergSync.getSingleton()
36
- .poseidon2Hash(
37
- inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
38
- )
39
- .toBuffer(),
40
- ),
29
+ const api = await BarretenbergSync.initSingleton();
30
+
31
+ const hash = api.poseidon2Hash(
32
+ inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
41
33
  );
34
+ return Fr.fromBuffer(Buffer.from(hash.toBuffer()));
42
35
  }
43
36
 
44
- export function poseidon2HashAccumulate(input: Fieldable[]): Fr {
37
+ export async function poseidon2HashAccumulate(input: Fieldable[]): Promise<Fr> {
45
38
  const inputFields = serializeToFields(input);
46
- return Fr.fromBuffer(
47
- Buffer.from(
48
- BarretenbergSync.getSingleton()
49
- .poseidon2HashAccumulate(inputFields.map(i => new FrBarretenberg(i.toBuffer())))
50
- .toBuffer(),
51
- ),
52
- );
39
+ const api = await BarretenbergSync.initSingleton();
40
+ const result = api.poseidon2HashAccumulate(inputFields.map(i => new FrBarretenberg(i.toBuffer())));
41
+ return Fr.fromBuffer(Buffer.from(result.toBuffer()));
53
42
  }
54
43
 
55
44
  /**
@@ -57,19 +46,18 @@ export function poseidon2HashAccumulate(input: Fieldable[]): Fr {
57
46
  * @param input the input state. Expected to be of size 4.
58
47
  * @returns the output state, size 4.
59
48
  */
60
- export function poseidon2Permutation(input: Fieldable[]): Fr[] {
49
+ export async function poseidon2Permutation(input: Fieldable[]): Promise<Fr[]> {
61
50
  const inputFields = serializeToFields(input);
62
51
  // We'd like this assertion but it's not possible to use it in the browser.
63
52
  // assert(input.length === 4, 'Input state must be of size 4');
64
- const res = BarretenbergSync.getSingleton().poseidon2Permutation(
65
- inputFields.map(i => new FrBarretenberg(i.toBuffer())),
66
- );
53
+ const api = await BarretenbergSync.initSingleton();
54
+ const res = api.poseidon2Permutation(inputFields.map(i => new FrBarretenberg(i.toBuffer())));
67
55
  // We'd like this assertion but it's not possible to use it in the browser.
68
56
  // assert(res.length === 4, 'Output state must be of size 4');
69
57
  return res.map(o => Fr.fromBuffer(Buffer.from(o.toBuffer())));
70
58
  }
71
59
 
72
- export function poseidon2HashBytes(input: Buffer): Fr {
60
+ export async function poseidon2HashBytes(input: Buffer): Promise<Fr> {
73
61
  const inputFields = [];
74
62
  for (let i = 0; i < input.length; i += 31) {
75
63
  const fieldBytes = Buffer.alloc(32, 0);
@@ -80,13 +68,10 @@ export function poseidon2HashBytes(input: Buffer): Fr {
80
68
  inputFields.push(Fr.fromBuffer(fieldBytes));
81
69
  }
82
70
 
83
- return Fr.fromBuffer(
84
- Buffer.from(
85
- BarretenbergSync.getSingleton()
86
- .poseidon2Hash(
87
- inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
88
- )
89
- .toBuffer(),
90
- ),
71
+ const api = await BarretenbergSync.initSingleton();
72
+ const res = api.poseidon2Hash(
73
+ inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
91
74
  );
75
+
76
+ return Fr.fromBuffer(Buffer.from(res.toBuffer()));
92
77
  }
@@ -0,0 +1,6 @@
1
+ import { BarretenbergSync } from '@aztec/bb.js';
2
+
3
+ export * from './poseidon/index.js';
4
+ export * from './pedersen/index.js';
5
+
6
+ await BarretenbergSync.initSingleton();
@@ -0,0 +1,45 @@
1
+ import { BarretenbergSync, Fr as FrBarretenberg } from '@aztec/bb.js';
2
+
3
+ import { Fr } from '../../../fields/fields.js';
4
+ import { type Fieldable, serializeToFields } from '../../../serialize/serialize.js';
5
+
6
+ /**
7
+ * Create a pedersen commitment (point) from an array of input fields.
8
+ * Left pads any inputs less than 32 bytes.
9
+ */
10
+ export function pedersenCommit(input: Buffer[], offset = 0) {
11
+ if (!input.every(i => i.length <= 32)) {
12
+ throw new Error('All Pedersen Commit input buffers must be <= 32 bytes.');
13
+ }
14
+ input = input.map(i => (i.length < 32 ? Buffer.concat([Buffer.alloc(32 - i.length, 0), i]) : i));
15
+ const point = BarretenbergSync.getSingleton().pedersenCommit(
16
+ input.map(i => new FrBarretenberg(i)),
17
+ offset,
18
+ );
19
+ // toBuffer returns Uint8Arrays (browser/worker-boundary friendly).
20
+ // TODO: rename toTypedArray()?
21
+ return [Buffer.from(point.x.toBuffer()), Buffer.from(point.y.toBuffer())];
22
+ }
23
+
24
+ /**
25
+ * Create a pedersen hash (field) from an array of input fields.
26
+ * @param input - The input fieldables to hash.
27
+ * @param index - The separator index to use for the hash.
28
+ * @returns The pedersen hash.
29
+ */
30
+ export function pedersenHash(input: Fieldable[], index = 0): Fr {
31
+ const inputFields = serializeToFields(input);
32
+ const hash = BarretenbergSync.getSingleton().pedersenHash(
33
+ inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
34
+ index,
35
+ );
36
+ return Fr.fromBuffer(Buffer.from(hash.toBuffer()));
37
+ }
38
+
39
+ /**
40
+ * Create a pedersen hash from an arbitrary length buffer.
41
+ */
42
+ export function pedersenHashBuffer(input: Buffer, index = 0) {
43
+ const result = BarretenbergSync.getSingleton().pedersenHashBuffer(input, index);
44
+ return Buffer.from(result.toBuffer());
45
+ }
@@ -0,0 +1,76 @@
1
+ import { BarretenbergSync, Fr as FrBarretenberg } from '@aztec/bb.js';
2
+
3
+ import { Fr } from '../../../fields/fields.js';
4
+ import { type Fieldable, serializeToFields } from '../../../serialize/serialize.js';
5
+
6
+ /**
7
+ * Create a poseidon hash (field) from an array of input fields.
8
+ * @param input - The input fields to hash.
9
+ * @returns The poseidon hash.
10
+ */
11
+ export function poseidon2Hash(input: Fieldable[]): Fr {
12
+ const inputFields = serializeToFields(input);
13
+ const hash = BarretenbergSync.getSingleton().poseidon2Hash(
14
+ inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
15
+ );
16
+ return Fr.fromBuffer(Buffer.from(hash.toBuffer()));
17
+ }
18
+
19
+ /**
20
+ * Create a poseidon hash (field) from an array of input fields and a domain separator.
21
+ * @param input - The input fields to hash.
22
+ * @param separator - The domain separator.
23
+ * @returns The poseidon hash.
24
+ */
25
+ export function poseidon2HashWithSeparator(input: Fieldable[], separator: number): Fr {
26
+ const inputFields = serializeToFields(input);
27
+ inputFields.unshift(new Fr(separator));
28
+
29
+ const hash = BarretenbergSync.getSingleton().poseidon2Hash(
30
+ inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
31
+ );
32
+ return Fr.fromBuffer(Buffer.from(hash.toBuffer()));
33
+ }
34
+
35
+ export function poseidon2HashAccumulate(input: Fieldable[]): Fr {
36
+ const inputFields = serializeToFields(input);
37
+ const result = BarretenbergSync.getSingleton().poseidon2HashAccumulate(
38
+ inputFields.map(i => new FrBarretenberg(i.toBuffer())),
39
+ );
40
+ return Fr.fromBuffer(Buffer.from(result.toBuffer()));
41
+ }
42
+
43
+ /**
44
+ * Runs a Poseidon2 permutation.
45
+ * @param input the input state. Expected to be of size 4.
46
+ * @returns the output state, size 4.
47
+ */
48
+ export function poseidon2Permutation(input: Fieldable[]): Fr[] {
49
+ const inputFields = serializeToFields(input);
50
+ // We'd like this assertion but it's not possible to use it in the browser.
51
+ // assert(input.length === 4, 'Input state must be of size 4');
52
+ const res = BarretenbergSync.getSingleton().poseidon2Permutation(
53
+ inputFields.map(i => new FrBarretenberg(i.toBuffer())),
54
+ );
55
+ // We'd like this assertion but it's not possible to use it in the browser.
56
+ // assert(res.length === 4, 'Output state must be of size 4');
57
+ return res.map(o => Fr.fromBuffer(Buffer.from(o.toBuffer())));
58
+ }
59
+
60
+ export function poseidon2HashBytes(input: Buffer): Fr {
61
+ const inputFields = [];
62
+ for (let i = 0; i < input.length; i += 31) {
63
+ const fieldBytes = Buffer.alloc(32, 0);
64
+ input.slice(i, i + 31).copy(fieldBytes);
65
+
66
+ // Noir builds the bytes as little-endian, so we need to reverse them.
67
+ fieldBytes.reverse();
68
+ inputFields.push(Fr.fromBuffer(fieldBytes));
69
+ }
70
+
71
+ const res = BarretenbergSync.getSingleton().poseidon2Hash(
72
+ inputFields.map(i => new FrBarretenberg(i.toBuffer())), // TODO(#4189): remove this stupid conversion
73
+ );
74
+
75
+ return Fr.fromBuffer(Buffer.from(res.toBuffer()));
76
+ }
@@ -1,4 +1,4 @@
1
- import { BarretenbergLazy } from '@aztec/bb.js';
1
+ import { BarretenbergSync } from '@aztec/bb.js';
2
2
 
3
3
  import { inspect } from 'util';
4
4
 
@@ -319,8 +319,8 @@ export class Fr extends BaseField {
319
319
  * @returns A square root of the field element (null if it does not exist).
320
320
  */
321
321
  async sqrt(): Promise<Fr | null> {
322
- const wasm = (await BarretenbergLazy.getSingleton()).getWasm();
323
- const [buf] = await wasm.callWasmExport('bn254_fr_sqrt', [this.toBuffer()], [Fr.SIZE_IN_BYTES + 1]);
322
+ const wasm = (await BarretenbergSync.initSingleton()).getWasm();
323
+ const [buf] = wasm.callWasmExport('bn254_fr_sqrt', [this.toBuffer()], [Fr.SIZE_IN_BYTES + 1]);
324
324
  const isSqrt = buf[0] === 1;
325
325
  if (!isSqrt) {
326
326
  // Field element is not a quadratic residue mod p so it has no square root.
@@ -1,4 +1,6 @@
1
- export async function toArray<T>(iterator: AsyncIterableIterator<T> | IterableIterator<T>): Promise<T[]> {
1
+ export async function toArray<T>(
2
+ iterator: Iterable<T> | AsyncIterableIterator<T> | AsyncIterable<T> | IterableIterator<T>,
3
+ ): Promise<T[]> {
2
4
  const arr = [];
3
5
  for await (const i of iterator) {
4
6
  arr.push(i);
@@ -40,7 +40,7 @@ export function createSafeJsonRpcClient<T extends object>(
40
40
  if ([null, undefined, 'null', 'undefined'].includes(res.result)) {
41
41
  return;
42
42
  }
43
- return (schema as ApiSchema)[methodName].returnType().parse(res.result);
43
+ return (schema as ApiSchema)[methodName].returnType().parseAsync(res.result);
44
44
  };
45
45
 
46
46
  const proxy: any = {};
@@ -8,8 +8,8 @@ import { type ZodFor } from '../schemas/types.js';
8
8
  * @param schema - Zod schema.
9
9
  * @returns Result of parsing json with schema.
10
10
  */
11
- export function jsonParseWithSchema<T>(json: string, schema: ZodFor<T>): T {
12
- return schema.parse(JSON.parse(json));
11
+ export function jsonParseWithSchema<T>(json: string, schema: ZodFor<T>): Promise<T> {
12
+ return schema.parseAsync(JSON.parse(json));
13
13
  }
14
14
 
15
15
  /**
@@ -151,6 +151,7 @@ export class SafeJsonRpcServer {
151
151
  throw new Error('Server is already listening');
152
152
  }
153
153
 
154
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
154
155
  this.httpServer = http.createServer(this.getApp(prefix).callback());
155
156
  this.httpServer.listen(port);
156
157
  }
@@ -217,7 +218,7 @@ export class SafeJsonProxy<T extends object = any> implements Proxy {
217
218
  assert(schemaHasMethod(this.schema, methodName), `Method ${methodName} not found in schema`);
218
219
  const method = this.handler[methodName as keyof T];
219
220
  assert(typeof method === 'function', `Method ${methodName} is not a function`);
220
- const args = parseWithOptionals(jsonParams, this.schema[methodName].parameters());
221
+ const args = await parseWithOptionals(jsonParams, this.schema[methodName].parameters());
221
222
  const ret = await method.apply(this.handler, args);
222
223
  this.log.debug(format('response', methodName, ret));
223
224
  return ret;
@@ -355,6 +356,7 @@ export async function startHttpRpcServer(
355
356
  const statusRouter = createStatusRouter(rpcServer.isHealthy.bind(rpcServer), options.apiPrefix);
356
357
  app.use(statusRouter.routes()).use(statusRouter.allowedMethods());
357
358
 
359
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
358
360
  const httpServer = http.createServer(app.callback());
359
361
  if (options.timeoutMs) {
360
362
  httpServer.timeout = options.timeoutMs;
@@ -0,0 +1,43 @@
1
+ export type MessageHeaderInit = {
2
+ /** The message ID. Optional, if not set defaults to 0 */
3
+ messageId?: number;
4
+ /** Identifies the original request. Optional */
5
+ requestId?: number;
6
+ };
7
+
8
+ export class MessageHeader {
9
+ /** An number to identify this message */
10
+ public readonly messageId: number;
11
+ /** If this message is a response to a request, the messageId of the request */
12
+ public readonly requestId: number;
13
+
14
+ constructor({ messageId, requestId }: MessageHeaderInit) {
15
+ this.messageId = messageId ?? 0;
16
+ this.requestId = requestId ?? 0;
17
+ }
18
+
19
+ static fromMessagePack(data: object): MessageHeader {
20
+ return new MessageHeader(data as MessageHeaderInit);
21
+ }
22
+ }
23
+
24
+ interface TypedMessageLike {
25
+ msgType: number;
26
+ header: {
27
+ messageId?: number;
28
+ requestId?: number;
29
+ };
30
+ value: any;
31
+ }
32
+
33
+ export class TypedMessage<T, B> {
34
+ public constructor(public readonly msgType: T, public readonly header: MessageHeader, public readonly value: B) {}
35
+
36
+ static fromMessagePack<T, B>(data: TypedMessageLike): TypedMessage<T, B> {
37
+ return new TypedMessage<T, B>(data['msgType'] as T, MessageHeader.fromMessagePack(data['header']), data['value']);
38
+ }
39
+
40
+ static isTypedMessageLike(obj: any): obj is TypedMessageLike {
41
+ return typeof obj === 'object' && obj !== null && 'msgType' in obj && 'header' in obj && 'value' in obj;
42
+ }
43
+ }
@@ -72,12 +72,13 @@ export class Mutex {
72
72
  *
73
73
  * @param id - The id of the current lock instance.
74
74
  */
75
- private async ping(id: number) {
75
+ private ping(id: number) {
76
76
  if (id !== this.id) {
77
77
  return;
78
78
  }
79
-
80
- await this.db.extendLock(this.name, this.timeout);
81
- this.pingTimeout = setTimeout(() => this.ping(id), this.pingInterval);
79
+ void (async () => {
80
+ await this.db.extendLock(this.name, this.timeout);
81
+ this.pingTimeout = setTimeout(() => this.ping(id), this.pingInterval);
82
+ })();
82
83
  }
83
84
  }
@@ -17,6 +17,7 @@ export class RunningPromise {
17
17
  private fn: () => void | Promise<void>,
18
18
  private logger = createLogger('running-promise'),
19
19
  private pollingIntervalMS = 10000,
20
+ private ignoredErrors: (new (...args: any[]) => Error)[] = [],
20
21
  ) {}
21
22
 
22
23
  /**
@@ -35,7 +36,9 @@ export class RunningPromise {
35
36
  try {
36
37
  await this.fn();
37
38
  } catch (err) {
38
- this.logger.error('Error in running promise', err);
39
+ if (err instanceof Error && !this.ignoredErrors.some(ErrorType => err instanceof ErrorType)) {
40
+ this.logger.error('Error in running promise', err);
41
+ }
39
42
  }
40
43
 
41
44
  // If an immediate run had been requested *before* the function started running, resolve the request.
@@ -11,12 +11,12 @@ export function parse<T extends [] | [z.ZodTypeAny, ...z.ZodTypeAny[]]>(args: IA
11
11
  * Parses the given arguments against a tuple, allowing empty for optional items.
12
12
  * @dev Zod doesn't like tuplues with optional items. See https://github.com/colinhacks/zod/discussions/949.
13
13
  */
14
- export function parseWithOptionals<T extends z.AnyZodTuple>(args: any[], schema: T): T['_output'] {
14
+ export function parseWithOptionals<T extends z.AnyZodTuple>(args: any[], schema: T): Promise<T['_output']> {
15
15
  const missingCount = schema.items.length - args.length;
16
16
  const optionalCount = schema.items.filter(isOptional).length;
17
17
  const toParse =
18
18
  missingCount > 0 && missingCount <= optionalCount ? args.concat(times(missingCount, () => undefined)) : args;
19
- return schema.parse(toParse);
19
+ return schema.parseAsync(toParse);
20
20
  }
21
21
 
22
22
  function isOptional(schema: z.ZodTypeAny) {
@@ -34,6 +34,27 @@ export class FieldReader {
34
34
  return new FieldReader(fields);
35
35
  }
36
36
 
37
+ /**
38
+ * Skips the next n fields.
39
+ *
40
+ * @param n - The number of fields to skip.
41
+ */
42
+ public skip(n: number) {
43
+ if (this.index + n > this.length) {
44
+ throw new Error('Not enough fields to be consumed.');
45
+ }
46
+ this.index += n;
47
+ }
48
+
49
+ /**
50
+ * Returns the current cursor position.
51
+ *
52
+ * @returns The current cursor position.
53
+ */
54
+ public get cursor() {
55
+ return this.index;
56
+ }
57
+
37
58
  /**
38
59
  * Reads a single field from the array.
39
60
  *
@@ -46,6 +67,18 @@ export class FieldReader {
46
67
  return this.fields[this.index++];
47
68
  }
48
69
 
70
+ /**
71
+ * Peeks at the next field without advancing the cursor.
72
+ *
73
+ * @returns A field.
74
+ */
75
+ public peekField(): Fr {
76
+ if (this.index === this.length) {
77
+ throw new Error('Not enough fields to be consumed.');
78
+ }
79
+ return this.fields[this.index];
80
+ }
81
+
49
82
  /**
50
83
  * Reads a Fq from the array.
51
84
  *
@@ -146,6 +179,6 @@ export class FieldReader {
146
179
  * @returns A bool.
147
180
  */
148
181
  public isFinished(): boolean {
149
- return this.index === this.length;
182
+ return this.index >= this.length;
150
183
  }
151
184
  }
@@ -18,6 +18,7 @@ export function startWebModule(module: WasmModule) {
18
18
  };
19
19
  const transportListener = new WorkerListener(self);
20
20
  const transportServer = new TransportServer<DispatchMsg>(transportListener, dispatch);
21
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
21
22
  module.addLogger((...args: any[]) => transportServer.broadcast({ fn: 'emit', args: ['log', ...args] }));
22
23
  transportServer.start();
23
24
  }
@@ -15,6 +15,7 @@ export async function createWebWorker(url: string, initialMem?: number, maxMem?:
15
15
  const transportClient = new TransportClient<DispatchMsg>(transportConnect);
16
16
  await transportClient.open();
17
17
  const remoteModule = createDispatchProxy(WasmModule, transportClient) as WasmWorker;
18
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
18
19
  remoteModule.destroyWorker = async () => {
19
20
  await transportClient.request({ fn: '__destroyWorker__', args: [] });
20
21
  transportClient.close();
@@ -13,6 +13,7 @@ export async function createNodeWorker(filepath: string, initialMem?: number, ma
13
13
  const transportClient = new TransportClient<DispatchMsg>(transportConnect);
14
14
  await transportClient.open();
15
15
  const remoteModule = createDispatchProxy(WasmModule, transportClient) as WasmWorker;
16
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
16
17
  remoteModule.destroyWorker = async () => {
17
18
  await transportClient.request({ fn: '__destroyWorker__', args: [] });
18
19
  transportClient.close();