@aztec/native 4.1.0-rc.2 → 4.1.0-rc.4

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.
@@ -76,14 +76,10 @@ export declare function createCancellationToken(): CancellationToken;
76
76
  * @param token - The cancellation token previously passed to avmSimulate
77
77
  */
78
78
  export declare function cancelSimulation(token: CancellationToken): void;
79
+ export declare const AVM_MAX_CONCURRENT_SIMULATIONS: number;
79
80
  /**
80
81
  * AVM simulation function that takes serialized inputs and a contract provider.
81
82
  * The contract provider enables C++ to callback to TypeScript for contract data during simulation.
82
- *
83
- * Simulations run on dedicated std::threads (not the libuv thread pool), so there is no risk
84
- * of libuv thread pool exhaustion or deadlock from C++ BlockingCall callbacks.
85
- * Concurrency is limited by AVM_MAX_CONCURRENT_SIMULATIONS (default 4, 0 = unlimited).
86
- *
87
83
  * @param inputs - Msgpack-serialized AvmFastSimulationInputs buffer
88
84
  * @param contractProvider - Object with callbacks for fetching contract instances and classes
89
85
  * @param worldStateHandle - Native handle to WorldState instance
@@ -97,14 +93,10 @@ export declare function avmSimulate(inputs: Buffer, contractProvider: ContractPr
97
93
  * AVM simulation function that uses pre-collected hints from TypeScript simulation.
98
94
  * All contract data and merkle tree hints are included in the AvmCircuitInputs, so no runtime
99
95
  * callbacks to TS or WS pointer are needed.
100
- *
101
- * Simulations run on dedicated std::threads (not the libuv thread pool).
102
- * Concurrency is limited by AVM_MAX_CONCURRENT_SIMULATIONS (default 4, 0 = unlimited).
103
- *
104
96
  * @param inputs - Msgpack-serialized AvmCircuitInputs (AvmProvingInputs in C++) buffer
105
97
  * @param logLevel - Log level to control C++ verbosity
106
98
  * @returns Promise resolving to msgpack-serialized simulation results buffer
107
99
  */
108
100
  export declare function avmSimulateWithHintedDbs(inputs: Buffer, logLevel?: LogLevel): Promise<Buffer>;
109
101
  export {};
110
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF0aXZlX21vZHVsZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL25hdGl2ZV9tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLEtBQUssUUFBUSxFQUFhLEtBQUssTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFLOUUsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFNUQsVUFBVSxlQUFlO0lBQ3ZCLEtBQUssR0FBRyxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsZUFBZSxDQUFDO0NBQzNDO0FBYUQsZUFBTyxNQUFNLGdCQUFnQixFQUFFLGVBQTRELENBQUM7QUFDNUYsZUFBTyxNQUFNLGVBQWUsRUFBRSxlQUEyRCxDQUFDO0FBRTFGOzs7R0FHRztBQUNILE1BQU0sV0FBVyxnQkFBZ0I7SUFDL0I7Ozs7T0FJRztJQUNILG1CQUFtQixDQUFDLE9BQU8sRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUMsQ0FBQztJQUNsRTs7OztPQUlHO0lBQ0gsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBRS9EOzs7O09BSUc7SUFDSCxZQUFZLENBQUMsc0JBQXNCLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUU1RDs7OztPQUlHO0lBQ0gscUJBQXFCLENBQUMsT0FBTyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBRXBFOzs7OztPQUtHO0lBQ0gsb0JBQW9CLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLENBQUM7SUFFckY7Ozs7T0FJRztJQUNILGdCQUFnQixJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVsQzs7O09BR0c7SUFDSCxnQkFBZ0IsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFbEM7OztPQUdHO0lBQ0gsZ0JBQWdCLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0NBQ25DO0FBb0JEOzs7O0dBSUc7QUFDSCxNQUFNLE1BQU0saUJBQWlCLEdBQUcsR0FBRyxDQUFDO0FBRXBDOzs7O0dBSUc7QUFDSCx3QkFBZ0IsdUJBQXVCLElBQUksaUJBQWlCLENBRTNEO0FBRUQ7Ozs7R0FJRztBQUNILHdCQUFnQixnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsaUJBQWlCLEdBQUcsSUFBSSxDQUUvRDtBQXNCRDs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCx3QkFBZ0IsV0FBVyxDQUN6QixNQUFNLEVBQUUsTUFBTSxFQUNkLGdCQUFnQixFQUFFLGdCQUFnQixFQUNsQyxnQkFBZ0IsRUFBRSxHQUFHLEVBQ3JCLFFBQVEsR0FBRSxRQUFpQixFQUMzQixNQUFNLENBQUMsRUFBRSxNQUFNLEVBQ2YsaUJBQWlCLENBQUMsRUFBRSxpQkFBaUIsR0FDcEMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQVdqQjtBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsd0JBQWdCLHdCQUF3QixDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxHQUFFLFFBQWlCLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUVyRyJ9
102
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmF0aXZlX21vZHVsZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL25hdGl2ZV9tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLEtBQUssUUFBUSxFQUFhLEtBQUssTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFLOUUsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFNUQsVUFBVSxlQUFlO0lBQ3ZCLEtBQUssR0FBRyxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsZUFBZSxDQUFDO0NBQzNDO0FBYUQsZUFBTyxNQUFNLGdCQUFnQixFQUFFLGVBQTRELENBQUM7QUFDNUYsZUFBTyxNQUFNLGVBQWUsRUFBRSxlQUEyRCxDQUFDO0FBRTFGOzs7R0FHRztBQUNILE1BQU0sV0FBVyxnQkFBZ0I7SUFDL0I7Ozs7T0FJRztJQUNILG1CQUFtQixDQUFDLE9BQU8sRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUMsQ0FBQztJQUNsRTs7OztPQUlHO0lBQ0gsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBRS9EOzs7O09BSUc7SUFDSCxZQUFZLENBQUMsc0JBQXNCLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUU1RDs7OztPQUlHO0lBQ0gscUJBQXFCLENBQUMsT0FBTyxFQUFFLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBRXBFOzs7OztPQUtHO0lBQ0gsb0JBQW9CLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLENBQUM7SUFFckY7Ozs7T0FJRztJQUNILGdCQUFnQixJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUVsQzs7O09BR0c7SUFDSCxnQkFBZ0IsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFFbEM7OztPQUdHO0lBQ0gsZ0JBQWdCLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0NBQ25DO0FBb0JEOzs7O0dBSUc7QUFDSCxNQUFNLE1BQU0saUJBQWlCLEdBQUcsR0FBRyxDQUFDO0FBRXBDOzs7O0dBSUc7QUFDSCx3QkFBZ0IsdUJBQXVCLElBQUksaUJBQWlCLENBRTNEO0FBRUQ7Ozs7R0FJRztBQUNILHdCQUFnQixnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsaUJBQWlCLEdBQUcsSUFBSSxDQUUvRDtBQWNELGVBQU8sTUFBTSw4QkFBOEIsUUFBa0QsQ0FBQztBQUc5Rjs7Ozs7Ozs7OztHQVVHO0FBQ0gsd0JBQXNCLFdBQVcsQ0FDL0IsTUFBTSxFQUFFLE1BQU0sRUFDZCxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFDbEMsZ0JBQWdCLEVBQUUsR0FBRyxFQUNyQixRQUFRLEdBQUUsUUFBaUIsRUFDM0IsTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUNmLGlCQUFpQixDQUFDLEVBQUUsaUJBQWlCLEdBQ3BDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FlakI7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsd0JBQXNCLHdCQUF3QixDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxHQUFFLFFBQWlCLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQU8zRyJ9
@@ -1 +1 @@
1
- {"version":3,"file":"native_module.d.ts","sourceRoot":"","sources":["../src/native_module.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAa,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAK9E,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;AAoBD;;;;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;AAsBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,gBAAgB,EAClC,gBAAgB,EAAE,GAAG,EACrB,QAAQ,GAAE,QAAiB,EAC3B,MAAM,CAAC,EAAE,MAAM,EACf,iBAAiB,CAAC,EAAE,iBAAiB,GACpC,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,QAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAErG"}
1
+ {"version":3,"file":"native_module.d.ts","sourceRoot":"","sources":["../src/native_module.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAa,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAK9E,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;AAoBD;;;;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;AAcD,eAAO,MAAM,8BAA8B,QAAkD,CAAC;AAG9F;;;;;;;;;;GAUG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,gBAAgB,EAClC,gBAAgB,EAAE,GAAG,EACrB,QAAQ,GAAE,QAAiB,EAC3B,MAAM,CAAC,EAAE,MAAM,EACf,iBAAiB,CAAC,EAAE,iBAAiB,GACpC,OAAO,CAAC,MAAM,CAAC,CAejB;AAED;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,QAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAO3G"}
@@ -33,29 +33,21 @@ const nativeCancelSimulation = nativeModule.cancelSimulation;
33
33
  nativeCancelSimulation(token);
34
34
  }
35
35
  /**
36
- * Maximum number of concurrent AVM simulations. Each simulation spawns a dedicated OS thread,
37
- * so this controls resource usage. Defaults to 4. Set to 0 for unlimited.
38
- */ const AVM_MAX_CONCURRENT_SIMULATIONS = parseInt(process.env.AVM_MAX_CONCURRENT_SIMULATIONS ?? '4', 10);
39
- const avmSimulationSemaphore = AVM_MAX_CONCURRENT_SIMULATIONS > 0 ? new Semaphore(AVM_MAX_CONCURRENT_SIMULATIONS) : null;
40
- async function withAvmConcurrencyLimit(fn) {
41
- if (!avmSimulationSemaphore) {
42
- return fn();
43
- }
44
- await avmSimulationSemaphore.acquire();
45
- try {
46
- return await fn();
47
- } finally{
48
- avmSimulationSemaphore.release();
49
- }
50
- }
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
+ export const AVM_MAX_CONCURRENT_SIMULATIONS = Math.max(1, Math.floor(UV_THREADPOOL_SIZE / 2));
47
+ const avmSimulationSemaphore = new Semaphore(AVM_MAX_CONCURRENT_SIMULATIONS);
51
48
  /**
52
49
  * AVM simulation function that takes serialized inputs and a contract provider.
53
50
  * The contract provider enables C++ to callback to TypeScript for contract data during simulation.
54
- *
55
- * Simulations run on dedicated std::threads (not the libuv thread pool), so there is no risk
56
- * of libuv thread pool exhaustion or deadlock from C++ BlockingCall callbacks.
57
- * Concurrency is limited by AVM_MAX_CONCURRENT_SIMULATIONS (default 4, 0 = unlimited).
58
- *
59
51
  * @param inputs - Msgpack-serialized AvmFastSimulationInputs buffer
60
52
  * @param contractProvider - Object with callbacks for fetching contract instances and classes
61
53
  * @param worldStateHandle - Native handle to WorldState instance
@@ -63,20 +55,26 @@ async function withAvmConcurrencyLimit(fn) {
63
55
  * @param logger - Optional logger object for C++ logging callbacks
64
56
  * @param cancellationToken - Optional token to enable cancellation support
65
57
  * @returns Promise resolving to msgpack-serialized AvmCircuitPublicInputs buffer
66
- */ export function avmSimulate(inputs, contractProvider, worldStateHandle, logLevel = 'info', logger, cancellationToken) {
67
- return withAvmConcurrencyLimit(()=>nativeAvmSimulate(inputs, contractProvider, worldStateHandle, LogLevels.indexOf(logLevel), logger ? (level, msg)=>logger[level](msg) : null, cancellationToken));
58
+ */ export async function avmSimulate(inputs, contractProvider, worldStateHandle, logLevel = 'info', logger, cancellationToken) {
59
+ await avmSimulationSemaphore.acquire();
60
+ try {
61
+ return await nativeAvmSimulate(inputs, contractProvider, worldStateHandle, LogLevels.indexOf(logLevel), logger ? (level, msg)=>logger[level](msg) : null, cancellationToken);
62
+ } finally{
63
+ avmSimulationSemaphore.release();
64
+ }
68
65
  }
69
66
  /**
70
67
  * AVM simulation function that uses pre-collected hints from TypeScript simulation.
71
68
  * All contract data and merkle tree hints are included in the AvmCircuitInputs, so no runtime
72
69
  * callbacks to TS or WS pointer are needed.
73
- *
74
- * Simulations run on dedicated std::threads (not the libuv thread pool).
75
- * Concurrency is limited by AVM_MAX_CONCURRENT_SIMULATIONS (default 4, 0 = unlimited).
76
- *
77
70
  * @param inputs - Msgpack-serialized AvmCircuitInputs (AvmProvingInputs in C++) buffer
78
71
  * @param logLevel - Log level to control C++ verbosity
79
72
  * @returns Promise resolving to msgpack-serialized simulation results buffer
80
- */ export function avmSimulateWithHintedDbs(inputs, logLevel = 'info') {
81
- return withAvmConcurrencyLimit(()=>nativeAvmSimulateWithHintedDbs(inputs, LogLevels.indexOf(logLevel)));
73
+ */ export async function avmSimulateWithHintedDbs(inputs, logLevel = 'info') {
74
+ await avmSimulationSemaphore.acquire();
75
+ try {
76
+ return await nativeAvmSimulateWithHintedDbs(inputs, LogLevels.indexOf(logLevel));
77
+ } finally{
78
+ avmSimulationSemaphore.release();
79
+ }
82
80
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/native",
3
- "version": "4.1.0-rc.2",
3
+ "version": "4.1.0-rc.4",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js"
@@ -15,8 +15,8 @@
15
15
  "../package.common.json"
16
16
  ],
17
17
  "dependencies": {
18
- "@aztec/bb.js": "4.1.0-rc.2",
19
- "@aztec/foundation": "4.1.0-rc.2",
18
+ "@aztec/bb.js": "4.1.0-rc.4",
19
+ "@aztec/foundation": "4.1.0-rc.4",
20
20
  "msgpackr": "^1.11.2"
21
21
  },
22
22
  "devDependencies": {
@@ -128,33 +128,23 @@ export function cancelSimulation(token: CancellationToken): void {
128
128
  }
129
129
 
130
130
  /**
131
- * Maximum number of concurrent AVM simulations. Each simulation spawns a dedicated OS thread,
132
- * so this controls resource usage. Defaults to 4. Set to 0 for unlimited.
131
+ * Concurrency limiting for C++ AVM simulation to prevent libuv thread pool exhaustion.
132
+ *
133
+ * The C++ simulator uses NAPI BlockingCall to callback to TypeScript for contract data.
134
+ * This blocks the libuv thread while waiting for the callback to complete. If all libuv
135
+ * threads are blocked waiting for callbacks, no threads remain to service those callbacks,
136
+ * causing deadlock.
137
+ *
138
+ * We limit concurrent simulations to UV_THREADPOOL_SIZE / 2 to ensure threads remain
139
+ * available for callback processing.
133
140
  */
134
- const AVM_MAX_CONCURRENT_SIMULATIONS = parseInt(process.env.AVM_MAX_CONCURRENT_SIMULATIONS ?? '4', 10);
135
- const avmSimulationSemaphore =
136
- AVM_MAX_CONCURRENT_SIMULATIONS > 0 ? new Semaphore(AVM_MAX_CONCURRENT_SIMULATIONS) : null;
137
-
138
- async function withAvmConcurrencyLimit<T>(fn: () => Promise<T>): Promise<T> {
139
- if (!avmSimulationSemaphore) {
140
- return fn();
141
- }
142
- await avmSimulationSemaphore.acquire();
143
- try {
144
- return await fn();
145
- } finally {
146
- avmSimulationSemaphore.release();
147
- }
148
- }
141
+ const UV_THREADPOOL_SIZE = parseInt(process.env.UV_THREADPOOL_SIZE ?? '4', 10);
142
+ export const AVM_MAX_CONCURRENT_SIMULATIONS = Math.max(1, Math.floor(UV_THREADPOOL_SIZE / 2));
143
+ const avmSimulationSemaphore = new Semaphore(AVM_MAX_CONCURRENT_SIMULATIONS);
149
144
 
150
145
  /**
151
146
  * AVM simulation function that takes serialized inputs and a contract provider.
152
147
  * The contract provider enables C++ to callback to TypeScript for contract data during simulation.
153
- *
154
- * Simulations run on dedicated std::threads (not the libuv thread pool), so there is no risk
155
- * of libuv thread pool exhaustion or deadlock from C++ BlockingCall callbacks.
156
- * Concurrency is limited by AVM_MAX_CONCURRENT_SIMULATIONS (default 4, 0 = unlimited).
157
- *
158
148
  * @param inputs - Msgpack-serialized AvmFastSimulationInputs buffer
159
149
  * @param contractProvider - Object with callbacks for fetching contract instances and classes
160
150
  * @param worldStateHandle - Native handle to WorldState instance
@@ -163,7 +153,7 @@ async function withAvmConcurrencyLimit<T>(fn: () => Promise<T>): Promise<T> {
163
153
  * @param cancellationToken - Optional token to enable cancellation support
164
154
  * @returns Promise resolving to msgpack-serialized AvmCircuitPublicInputs buffer
165
155
  */
166
- export function avmSimulate(
156
+ export async function avmSimulate(
167
157
  inputs: Buffer,
168
158
  contractProvider: ContractProvider,
169
159
  worldStateHandle: any,
@@ -171,30 +161,35 @@ export function avmSimulate(
171
161
  logger?: Logger,
172
162
  cancellationToken?: CancellationToken,
173
163
  ): Promise<Buffer> {
174
- return withAvmConcurrencyLimit(() =>
175
- nativeAvmSimulate(
164
+ await avmSimulationSemaphore.acquire();
165
+
166
+ try {
167
+ return await nativeAvmSimulate(
176
168
  inputs,
177
169
  contractProvider,
178
170
  worldStateHandle,
179
171
  LogLevels.indexOf(logLevel),
180
172
  logger ? (level: LogLevel, msg: string) => logger[level](msg) : null,
181
173
  cancellationToken,
182
- ),
183
- );
174
+ );
175
+ } finally {
176
+ avmSimulationSemaphore.release();
177
+ }
184
178
  }
185
179
 
186
180
  /**
187
181
  * AVM simulation function that uses pre-collected hints from TypeScript simulation.
188
182
  * All contract data and merkle tree hints are included in the AvmCircuitInputs, so no runtime
189
183
  * callbacks to TS or WS pointer are needed.
190
- *
191
- * Simulations run on dedicated std::threads (not the libuv thread pool).
192
- * Concurrency is limited by AVM_MAX_CONCURRENT_SIMULATIONS (default 4, 0 = unlimited).
193
- *
194
184
  * @param inputs - Msgpack-serialized AvmCircuitInputs (AvmProvingInputs in C++) buffer
195
185
  * @param logLevel - Log level to control C++ verbosity
196
186
  * @returns Promise resolving to msgpack-serialized simulation results buffer
197
187
  */
198
- export function avmSimulateWithHintedDbs(inputs: Buffer, logLevel: LogLevel = 'info'): Promise<Buffer> {
199
- return withAvmConcurrencyLimit(() => nativeAvmSimulateWithHintedDbs(inputs, LogLevels.indexOf(logLevel)));
188
+ export async function avmSimulateWithHintedDbs(inputs: Buffer, logLevel: LogLevel = 'info'): Promise<Buffer> {
189
+ await avmSimulationSemaphore.acquire();
190
+ try {
191
+ return await nativeAvmSimulateWithHintedDbs(inputs, LogLevels.indexOf(logLevel));
192
+ } finally {
193
+ avmSimulationSemaphore.release();
194
+ }
200
195
  }