@aztec/native 0.0.1-commit.9b94fc1 → 0.0.1-commit.c7c42ec

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.
@@ -1,4 +1,4 @@
1
- import { Fr } from '@aztec/foundation/fields';
1
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
2
  import { MessageHeader, TypedMessage } from '@aztec/foundation/message';
3
3
  import { Encoder, addExtension } from 'msgpackr';
4
4
  import { isAnyArrayBuffer } from 'util/types';
@@ -1,3 +1,4 @@
1
+ import { type LogLevel } from '@aztec/foundation/log';
1
2
  import type { MessageReceiver } from './msgpack_channel.js';
2
3
  interface NativeClassCtor {
3
4
  new (...args: unknown[]): MessageReceiver;
@@ -57,23 +58,43 @@ export interface ContractProvider {
57
58
  */
58
59
  revertCheckpoint(): Promise<void>;
59
60
  }
61
+ /**
62
+ * Cancellation token handle used to cancel C++ AVM simulation.
63
+ * The token is created via createCancellationToken() and can be cancelled via cancelSimulation().
64
+ * Pass it to avmSimulate to enable cancellation support.
65
+ */
66
+ export type CancellationToken = any;
67
+ /**
68
+ * Create a new cancellation token for C++ simulation.
69
+ * This token can be passed to avmSimulate and later cancelled via cancelSimulation().
70
+ * @returns A handle to a cancellation token
71
+ */
72
+ export declare function createCancellationToken(): CancellationToken;
73
+ /**
74
+ * Signal cancellation to a C++ simulation.
75
+ * The simulation will stop at the next opcode or before the next WorldState write.
76
+ * @param token - The cancellation token previously passed to avmSimulate
77
+ */
78
+ export declare function cancelSimulation(token: CancellationToken): void;
60
79
  /**
61
80
  * AVM simulation function that takes serialized inputs and a contract provider.
62
81
  * The contract provider enables C++ to callback to TypeScript for contract data during simulation.
63
82
  * @param inputs - Msgpack-serialized AvmFastSimulationInputs buffer
64
83
  * @param contractProvider - Object with callbacks for fetching contract instances and classes
65
84
  * @param worldStateHandle - Native handle to WorldState instance
66
- * TODO(MW): include generate_hints bool
85
+ * @param logLevel - Log level to control C++ verbosity
86
+ * @param cancellationToken - Optional token to enable cancellation support
67
87
  * @returns Promise resolving to msgpack-serialized AvmCircuitPublicInputs buffer
68
88
  */
69
- export declare const avmSimulate: (inputs: Buffer, contractProvider: ContractProvider, worldStateHandle: any) => Promise<Buffer>;
89
+ export declare function avmSimulate(inputs: Buffer, contractProvider: ContractProvider, worldStateHandle: any, logLevel?: LogLevel, cancellationToken?: CancellationToken): Promise<Buffer>;
70
90
  /**
71
91
  * AVM simulation function that uses pre-collected hints from TypeScript simulation.
72
92
  * All contract data and merkle tree hints are included in the AvmCircuitInputs, so no runtime
73
93
  * callbacks to TS or WS pointer are needed.
74
94
  * @param inputs - Msgpack-serialized AvmCircuitInputs (AvmProvingInputs in C++) buffer
95
+ * @param logLevel - Log level to control C++ verbosity
75
96
  * @returns Promise resolving to msgpack-serialized simulation results buffer
76
97
  */
77
- export declare const avmSimulateWithHintedDbs: (inputs: Buffer) => Promise<Buffer>;
98
+ export declare function avmSimulateWithHintedDbs(inputs: Buffer, logLevel?: LogLevel): Promise<Buffer>;
78
99
  export {};
79
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF0aXZlX21vZHVsZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL25hdGl2ZV9tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBSUEsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFNUQsVUFBVSxlQUFlO0lBQ3ZCLEtBQUssR0FBRyxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsZUFBZSxDQUFDO0NBQzNDO0FBYUQsZUFBTyxNQUFNLGdCQUFnQixFQUFFLGVBQTRELENBQUM7QUFDNUYsZUFBTyxNQUFNLGVBQWUsRUFBRSxlQUEyRCxDQUFDO0FBRTFGOzs7R0FHRztBQUNILE1BQU0sV0FBVyxnQkFBZ0I7SUFDL0I7Ozs7T0FJRztJQUNILG1CQUFtQixDQUFDLE9BQU8sRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUMsQ0FBQztJQUNsRTs7OztPQUlHO0lBQ0gsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBRS9EOzs7O09BSUc7SUFDSCxZQUFZLENBQUMsc0JBQXNCLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUU1RDs7OztPQUlHO0lBQ0gscUJBQXFCLENBQUMsT0FBTyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBRXBFOzs7OztPQUtHO0lBQ0gsb0JBQW9CLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLENBQUM7SUFFckY7Ozs7T0FJRztJQUNILGdCQUFnQixJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVsQzs7O09BR0c7SUFDSCxnQkFBZ0IsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFbEM7OztPQUdHO0lBQ0gsZ0JBQWdCLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0NBQ25DO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxlQUFPLE1BQU0sV0FBVyxFQUFFLENBQ3hCLE1BQU0sRUFBRSxNQUFNLEVBQ2QsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQ2xDLGdCQUFnQixFQUFFLEdBQUcsS0FDbEIsT0FBTyxDQUFDLE1BQU0sQ0FJQyxDQUFDO0FBQ3JCOzs7Ozs7R0FNRztBQUNILGVBQU8sTUFBTSx3QkFBd0IsRUFBRSxDQUFDLE1BQU0sRUFBRSxNQUFNLEtBQUssT0FBTyxDQUFDLE1BQU0sQ0FFckQsQ0FBQyJ9
100
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF0aXZlX21vZHVsZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL25hdGl2ZV9tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLEtBQUssUUFBUSxFQUFhLE1BQU0sdUJBQXVCLENBQUM7QUFLakUsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFNUQsVUFBVSxlQUFlO0lBQ3ZCLEtBQUssR0FBRyxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsZUFBZSxDQUFDO0NBQzNDO0FBYUQsZUFBTyxNQUFNLGdCQUFnQixFQUFFLGVBQTRELENBQUM7QUFDNUYsZUFBTyxNQUFNLGVBQWUsRUFBRSxlQUEyRCxDQUFDO0FBRTFGOzs7R0FHRztBQUNILE1BQU0sV0FBVyxnQkFBZ0I7SUFDL0I7Ozs7T0FJRztJQUNILG1CQUFtQixDQUFDLE9BQU8sRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUMsQ0FBQztJQUNsRTs7OztPQUlHO0lBQ0gsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBRS9EOzs7O09BSUc7SUFDSCxZQUFZLENBQUMsc0JBQXNCLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUU1RDs7OztPQUlHO0lBQ0gscUJBQXFCLENBQUMsT0FBTyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBRXBFOzs7OztPQUtHO0lBQ0gsb0JBQW9CLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLENBQUM7SUFFckY7Ozs7T0FJRztJQUNILGdCQUFnQixJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVsQzs7O09BR0c7SUFDSCxnQkFBZ0IsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFbEM7OztPQUdHO0lBQ0gsZ0JBQWdCLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0NBQ25DO0FBbUJEOzs7O0dBSUc7QUFDSCxNQUFNLE1BQU0saUJBQWlCLEdBQUcsR0FBRyxDQUFDO0FBRXBDOzs7O0dBSUc7QUFDSCx3QkFBZ0IsdUJBQXVCLElBQUksaUJBQWlCLENBRTNEO0FBRUQ7Ozs7R0FJRztBQUNILHdCQUFnQixnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsaUJBQWlCLEdBQUcsSUFBSSxDQUUvRDtBQWlCRDs7Ozs7Ozs7O0dBU0c7QUFDSCx3QkFBc0IsV0FBVyxDQUMvQixNQUFNLEVBQUUsTUFBTSxFQUNkLGdCQUFnQixFQUFFLGdCQUFnQixFQUNsQyxnQkFBZ0IsRUFBRSxHQUFHLEVBQ3JCLFFBQVEsR0FBRSxRQUFpQixFQUMzQixpQkFBaUIsQ0FBQyxFQUFFLGlCQUFpQixHQUNwQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBYWpCO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILHdCQUFzQix3QkFBd0IsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFFBQVEsR0FBRSxRQUFpQixHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FPM0cifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"native_module.d.ts","sourceRoot":"","sources":["../src/native_module.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,UAAU,eAAe;IACvB,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC;CAC3C;AAaD,eAAO,MAAM,gBAAgB,EAAE,eAA4D,CAAC;AAC5F,eAAO,MAAM,eAAe,EAAE,eAA2D,CAAC;AAE1F;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAClE;;;;OAIG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE/D;;;;OAIG;IACH,YAAY,CAAC,sBAAsB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5D;;;;OAIG;IACH,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAEpE;;;;;OAKG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAErF;;;;OAIG;IACH,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,EAAE,CACxB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,gBAAgB,EAClC,gBAAgB,EAAE,GAAG,KAClB,OAAO,CAAC,MAAM,CAIC,CAAC;AACrB;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAErD,CAAC"}
1
+ {"version":3,"file":"native_module.d.ts","sourceRoot":"","sources":["../src/native_module.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAa,MAAM,uBAAuB,CAAC;AAKjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,UAAU,eAAe;IACvB,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,eAAe,CAAC;CAC3C;AAaD,eAAO,MAAM,gBAAgB,EAAE,eAA4D,CAAC;AAC5F,eAAO,MAAM,eAAe,EAAE,eAA2D,CAAC;AAE1F;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAClE;;;;OAIG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE/D;;;;OAIG;IACH,YAAY,CAAC,sBAAsB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5D;;;;OAIG;IACH,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAEpE;;;;;OAKG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAErF;;;;OAIG;IACH,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAmBD;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAEpC;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,iBAAiB,CAE3D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAE/D;AAiBD;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,gBAAgB,EAClC,gBAAgB,EAAE,GAAG,EACrB,QAAQ,GAAE,QAAiB,EAC3B,iBAAiB,CAAC,EAAE,iBAAiB,GACpC,OAAO,CAAC,MAAM,CAAC,CAajB;AAED;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,QAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAO3G"}
@@ -1,4 +1,6 @@
1
1
  import { findNapiBinary } from '@aztec/bb.js';
2
+ import { LogLevels } from '@aztec/foundation/log';
3
+ import { Semaphore } from '@aztec/foundation/queue';
2
4
  import { createRequire } from 'module';
3
5
  function loadNativeModule() {
4
6
  const require = createRequire(import.meta.url);
@@ -11,19 +13,67 @@ function loadNativeModule() {
11
13
  const nativeModule = loadNativeModule();
12
14
  export const NativeWorldState = nativeModule.WorldState;
13
15
  export const NativeLMDBStore = nativeModule.LMDBStore;
16
+ // Internal native functions with numeric log level
17
+ const nativeAvmSimulate = nativeModule.avmSimulate;
18
+ const nativeAvmSimulateWithHintedDbs = nativeModule.avmSimulateWithHintedDbs;
19
+ const nativeCreateCancellationToken = nativeModule.createCancellationToken;
20
+ const nativeCancelSimulation = nativeModule.cancelSimulation;
21
+ /**
22
+ * Create a new cancellation token for C++ simulation.
23
+ * This token can be passed to avmSimulate and later cancelled via cancelSimulation().
24
+ * @returns A handle to a cancellation token
25
+ */ export function createCancellationToken() {
26
+ return nativeCreateCancellationToken();
27
+ }
28
+ /**
29
+ * Signal cancellation to a C++ simulation.
30
+ * The simulation will stop at the next opcode or before the next WorldState write.
31
+ * @param token - The cancellation token previously passed to avmSimulate
32
+ */ export function cancelSimulation(token) {
33
+ nativeCancelSimulation(token);
34
+ }
35
+ /**
36
+ * Concurrency limiting for C++ AVM simulation to prevent libuv thread pool exhaustion.
37
+ *
38
+ * The C++ simulator uses NAPI BlockingCall to callback to TypeScript for contract data.
39
+ * This blocks the libuv thread while waiting for the callback to complete. If all libuv
40
+ * threads are blocked waiting for callbacks, no threads remain to service those callbacks,
41
+ * causing deadlock.
42
+ *
43
+ * We limit concurrent simulations to UV_THREADPOOL_SIZE / 2 to ensure threads remain
44
+ * available for callback processing.
45
+ */ const UV_THREADPOOL_SIZE = parseInt(process.env.UV_THREADPOOL_SIZE ?? '4', 10);
46
+ const MAX_CONCURRENT_AVM_SIMULATIONS = Math.max(1, Math.floor(UV_THREADPOOL_SIZE / 2));
47
+ const avmSimulationSemaphore = new Semaphore(MAX_CONCURRENT_AVM_SIMULATIONS);
14
48
  /**
15
49
  * AVM simulation function that takes serialized inputs and a contract provider.
16
50
  * The contract provider enables C++ to callback to TypeScript for contract data during simulation.
17
51
  * @param inputs - Msgpack-serialized AvmFastSimulationInputs buffer
18
52
  * @param contractProvider - Object with callbacks for fetching contract instances and classes
19
53
  * @param worldStateHandle - Native handle to WorldState instance
20
- * TODO(MW): include generate_hints bool
54
+ * @param logLevel - Log level to control C++ verbosity
55
+ * @param cancellationToken - Optional token to enable cancellation support
21
56
  * @returns Promise resolving to msgpack-serialized AvmCircuitPublicInputs buffer
22
- */ export const avmSimulate = nativeModule.avmSimulate;
57
+ */ export async function avmSimulate(inputs, contractProvider, worldStateHandle, logLevel = 'info', cancellationToken) {
58
+ await avmSimulationSemaphore.acquire();
59
+ try {
60
+ return await nativeAvmSimulate(inputs, contractProvider, worldStateHandle, LogLevels.indexOf(logLevel), cancellationToken);
61
+ } finally{
62
+ avmSimulationSemaphore.release();
63
+ }
64
+ }
23
65
  /**
24
66
  * AVM simulation function that uses pre-collected hints from TypeScript simulation.
25
67
  * All contract data and merkle tree hints are included in the AvmCircuitInputs, so no runtime
26
68
  * callbacks to TS or WS pointer are needed.
27
69
  * @param inputs - Msgpack-serialized AvmCircuitInputs (AvmProvingInputs in C++) buffer
70
+ * @param logLevel - Log level to control C++ verbosity
28
71
  * @returns Promise resolving to msgpack-serialized simulation results buffer
29
- */ export const avmSimulateWithHintedDbs = nativeModule.avmSimulateWithHintedDbs;
72
+ */ export async function avmSimulateWithHintedDbs(inputs, logLevel = 'info') {
73
+ await avmSimulationSemaphore.acquire();
74
+ try {
75
+ return await nativeAvmSimulateWithHintedDbs(inputs, LogLevels.indexOf(logLevel));
76
+ } finally{
77
+ avmSimulationSemaphore.release();
78
+ }
79
+ }
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@aztec/native",
3
- "version": "0.0.1-commit.9b94fc1",
3
+ "version": "0.0.1-commit.c7c42ec",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js"
7
7
  },
8
8
  "scripts": {
9
- "build": "yarn clean && tsgo -b",
10
- "build:dev": "tsgo -b --watch",
9
+ "build": "yarn clean && ../scripts/tsc.sh",
10
+ "build:dev": "../scripts/tsc.sh --watch",
11
11
  "clean": "rm -rf ./dest .tsbuildinfo",
12
12
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
13
13
  },
@@ -15,8 +15,8 @@
15
15
  "../package.common.json"
16
16
  ],
17
17
  "dependencies": {
18
- "@aztec/bb.js": "0.0.1-commit.9b94fc1",
19
- "@aztec/foundation": "0.0.1-commit.9b94fc1",
18
+ "@aztec/bb.js": "0.0.1-commit.c7c42ec",
19
+ "@aztec/foundation": "0.0.1-commit.c7c42ec",
20
20
  "msgpackr": "^1.11.2"
21
21
  },
22
22
  "devDependencies": {
@@ -1,4 +1,4 @@
1
- import { Fr } from '@aztec/foundation/fields';
1
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
2
  import { MessageHeader, TypedMessage } from '@aztec/foundation/message';
3
3
 
4
4
  import { Encoder, addExtension } from 'msgpackr';
@@ -1,4 +1,6 @@
1
1
  import { findNapiBinary } from '@aztec/bb.js';
2
+ import { type LogLevel, LogLevels } from '@aztec/foundation/log';
3
+ import { Semaphore } from '@aztec/foundation/queue';
2
4
 
3
5
  import { createRequire } from 'module';
4
6
 
@@ -82,31 +84,107 @@ export interface ContractProvider {
82
84
  revertCheckpoint(): Promise<void>;
83
85
  }
84
86
 
87
+ // Internal native functions with numeric log level
88
+ const nativeAvmSimulate = nativeModule.avmSimulate as (
89
+ inputs: Buffer,
90
+ contractProvider: ContractProvider,
91
+ worldStateHandle: any,
92
+ logLevel: number,
93
+ cancellationToken?: any,
94
+ ) => Promise<Buffer>;
95
+
96
+ const nativeAvmSimulateWithHintedDbs = nativeModule.avmSimulateWithHintedDbs as (
97
+ inputs: Buffer,
98
+ logLevel: number,
99
+ ) => Promise<Buffer>;
100
+
101
+ const nativeCreateCancellationToken = nativeModule.createCancellationToken as () => any;
102
+ const nativeCancelSimulation = nativeModule.cancelSimulation as (token: any) => void;
103
+
104
+ /**
105
+ * Cancellation token handle used to cancel C++ AVM simulation.
106
+ * The token is created via createCancellationToken() and can be cancelled via cancelSimulation().
107
+ * Pass it to avmSimulate to enable cancellation support.
108
+ */
109
+ export type CancellationToken = any;
110
+
111
+ /**
112
+ * Create a new cancellation token for C++ simulation.
113
+ * This token can be passed to avmSimulate and later cancelled via cancelSimulation().
114
+ * @returns A handle to a cancellation token
115
+ */
116
+ export function createCancellationToken(): CancellationToken {
117
+ return nativeCreateCancellationToken();
118
+ }
119
+
120
+ /**
121
+ * Signal cancellation to a C++ simulation.
122
+ * The simulation will stop at the next opcode or before the next WorldState write.
123
+ * @param token - The cancellation token previously passed to avmSimulate
124
+ */
125
+ export function cancelSimulation(token: CancellationToken): void {
126
+ nativeCancelSimulation(token);
127
+ }
128
+
129
+ /**
130
+ * Concurrency limiting for C++ AVM simulation to prevent libuv thread pool exhaustion.
131
+ *
132
+ * The C++ simulator uses NAPI BlockingCall to callback to TypeScript for contract data.
133
+ * This blocks the libuv thread while waiting for the callback to complete. If all libuv
134
+ * threads are blocked waiting for callbacks, no threads remain to service those callbacks,
135
+ * causing deadlock.
136
+ *
137
+ * We limit concurrent simulations to UV_THREADPOOL_SIZE / 2 to ensure threads remain
138
+ * available for callback processing.
139
+ */
140
+ const UV_THREADPOOL_SIZE = parseInt(process.env.UV_THREADPOOL_SIZE ?? '4', 10);
141
+ const MAX_CONCURRENT_AVM_SIMULATIONS = Math.max(1, Math.floor(UV_THREADPOOL_SIZE / 2));
142
+ const avmSimulationSemaphore = new Semaphore(MAX_CONCURRENT_AVM_SIMULATIONS);
143
+
85
144
  /**
86
145
  * AVM simulation function that takes serialized inputs and a contract provider.
87
146
  * The contract provider enables C++ to callback to TypeScript for contract data during simulation.
88
147
  * @param inputs - Msgpack-serialized AvmFastSimulationInputs buffer
89
148
  * @param contractProvider - Object with callbacks for fetching contract instances and classes
90
149
  * @param worldStateHandle - Native handle to WorldState instance
91
- * TODO(MW): include generate_hints bool
150
+ * @param logLevel - Log level to control C++ verbosity
151
+ * @param cancellationToken - Optional token to enable cancellation support
92
152
  * @returns Promise resolving to msgpack-serialized AvmCircuitPublicInputs buffer
93
153
  */
94
- export const avmSimulate: (
95
- inputs: Buffer,
96
- contractProvider: ContractProvider,
97
- worldStateHandle: any,
98
- ) => Promise<Buffer> = nativeModule.avmSimulate as (
154
+ export async function avmSimulate(
99
155
  inputs: Buffer,
100
156
  contractProvider: ContractProvider,
101
157
  worldStateHandle: any,
102
- ) => Promise<Buffer>;
158
+ logLevel: LogLevel = 'info',
159
+ cancellationToken?: CancellationToken,
160
+ ): Promise<Buffer> {
161
+ await avmSimulationSemaphore.acquire();
162
+ try {
163
+ return await nativeAvmSimulate(
164
+ inputs,
165
+ contractProvider,
166
+ worldStateHandle,
167
+ LogLevels.indexOf(logLevel),
168
+ cancellationToken,
169
+ );
170
+ } finally {
171
+ avmSimulationSemaphore.release();
172
+ }
173
+ }
174
+
103
175
  /**
104
176
  * AVM simulation function that uses pre-collected hints from TypeScript simulation.
105
177
  * All contract data and merkle tree hints are included in the AvmCircuitInputs, so no runtime
106
178
  * callbacks to TS or WS pointer are needed.
107
179
  * @param inputs - Msgpack-serialized AvmCircuitInputs (AvmProvingInputs in C++) buffer
180
+ * @param logLevel - Log level to control C++ verbosity
108
181
  * @returns Promise resolving to msgpack-serialized simulation results buffer
109
182
  */
110
- export const avmSimulateWithHintedDbs: (inputs: Buffer) => Promise<Buffer> = nativeModule.avmSimulateWithHintedDbs as (
111
- inputs: Buffer,
112
- ) => Promise<Buffer>;
183
+ export async function avmSimulateWithHintedDbs(inputs: Buffer, logLevel: LogLevel = 'info'): Promise<Buffer> {
184
+ await avmSimulationSemaphore.acquire();
185
+ try {
186
+ return await nativeAvmSimulateWithHintedDbs(inputs, LogLevels.indexOf(logLevel));
187
+ } finally {
188
+ avmSimulationSemaphore.release();
189
+ }
190
+ }