@aztec-labs/simulator 6.0.0-nightly.20260829
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.
- package/README.md +57 -0
- package/dest/client.d.ts +6 -0
- package/dest/client.d.ts.map +1 -0
- package/dest/client.js +3 -0
- package/dest/common/errors.d.ts +51 -0
- package/dest/common/errors.d.ts.map +1 -0
- package/dest/common/errors.js +154 -0
- package/dest/common/index.d.ts +3 -0
- package/dest/common/index.d.ts.map +1 -0
- package/dest/common/index.js +2 -0
- package/dest/common/stats/index.d.ts +2 -0
- package/dest/common/stats/index.d.ts.map +1 -0
- package/dest/common/stats/index.js +1 -0
- package/dest/common/stats/stats.d.ts +4 -0
- package/dest/common/stats/stats.d.ts.map +1 -0
- package/dest/common/stats/stats.js +10 -0
- package/dest/private/acvm/acvm.d.ts +43 -0
- package/dest/private/acvm/acvm.d.ts.map +1 -0
- package/dest/private/acvm/acvm.js +65 -0
- package/dest/private/acvm/acvm_types.d.ts +10 -0
- package/dest/private/acvm/acvm_types.d.ts.map +1 -0
- package/dest/private/acvm/acvm_types.js +3 -0
- package/dest/private/acvm/deserialize.d.ts +35 -0
- package/dest/private/acvm/deserialize.d.ts.map +1 -0
- package/dest/private/acvm/deserialize.js +50 -0
- package/dest/private/acvm/index.d.ts +5 -0
- package/dest/private/acvm/index.d.ts.map +1 -0
- package/dest/private/acvm/index.js +4 -0
- package/dest/private/acvm/serialize.d.ts +41 -0
- package/dest/private/acvm/serialize.d.ts.map +1 -0
- package/dest/private/acvm/serialize.js +99 -0
- package/dest/private/acvm_native.d.ts +41 -0
- package/dest/private/acvm_native.d.ts.map +1 -0
- package/dest/private/acvm_native.js +147 -0
- package/dest/private/acvm_wasm.d.ts +16 -0
- package/dest/private/acvm_wasm.d.ts.map +1 -0
- package/dest/private/acvm_wasm.js +67 -0
- package/dest/private/acvm_wasm_with_blobs.d.ts +20 -0
- package/dest/private/acvm_wasm_with_blobs.d.ts.map +1 -0
- package/dest/private/acvm_wasm_with_blobs.js +35 -0
- package/dest/private/circuit_simulator.d.ts +35 -0
- package/dest/private/circuit_simulator.d.ts.map +1 -0
- package/dest/private/circuit_simulator.js +43 -0
- package/dest/private/factory.d.ts +12 -0
- package/dest/private/factory.d.ts.map +1 -0
- package/dest/private/factory.js +30 -0
- package/dest/public/avm/testing/account_proof_fetcher.d.ts +2 -0
- package/dest/public/avm/testing/account_proof_fetcher.d.ts.map +1 -0
- package/dest/public/avm/testing/account_proof_fetcher.js +152 -0
- package/dest/public/avm/testing/base_avm_simulation_tester.d.ts +39 -0
- package/dest/public/avm/testing/base_avm_simulation_tester.d.ts.map +1 -0
- package/dest/public/avm/testing/base_avm_simulation_tester.js +121 -0
- package/dest/public/avm/testing/utils.d.ts +32 -0
- package/dest/public/avm/testing/utils.d.ts.map +1 -0
- package/dest/public/avm/testing/utils.js +66 -0
- package/dest/public/avm_simulator.d.ts +28 -0
- package/dest/public/avm_simulator.d.ts.map +1 -0
- package/dest/public/avm_simulator.js +4 -0
- package/dest/public/avm_simulator_pool.d.ts +84 -0
- package/dest/public/avm_simulator_pool.d.ts.map +1 -0
- package/dest/public/avm_simulator_pool.js +311 -0
- package/dest/public/cdb_ipc_server.d.ts +40 -0
- package/dest/public/cdb_ipc_server.d.ts.map +1 -0
- package/dest/public/cdb_ipc_server.js +153 -0
- package/dest/public/contracts_db_checkpoint.d.ts +16 -0
- package/dest/public/contracts_db_checkpoint.d.ts.map +1 -0
- package/dest/public/contracts_db_checkpoint.js +30 -0
- package/dest/public/db_interfaces.d.ts +68 -0
- package/dest/public/db_interfaces.d.ts.map +1 -0
- package/dest/public/db_interfaces.js +3 -0
- package/dest/public/executor_metrics.d.ts +21 -0
- package/dest/public/executor_metrics.d.ts.map +1 -0
- package/dest/public/executor_metrics.js +64 -0
- package/dest/public/executor_metrics_interface.d.ts +10 -0
- package/dest/public/executor_metrics_interface.d.ts.map +1 -0
- package/dest/public/executor_metrics_interface.js +1 -0
- package/dest/public/fixtures/amm_test.d.ts +10 -0
- package/dest/public/fixtures/amm_test.d.ts.map +1 -0
- package/dest/public/fixtures/amm_test.js +213 -0
- package/dest/public/fixtures/bulk_test.d.ts +6 -0
- package/dest/public/fixtures/bulk_test.d.ts.map +1 -0
- package/dest/public/fixtures/bulk_test.js +289 -0
- package/dest/public/fixtures/custom_bytecode_tester.d.ts +34 -0
- package/dest/public/fixtures/custom_bytecode_tester.d.ts.map +1 -0
- package/dest/public/fixtures/custom_bytecode_tester.js +53 -0
- package/dest/public/fixtures/index.d.ts +10 -0
- package/dest/public/fixtures/index.d.ts.map +1 -0
- package/dest/public/fixtures/index.js +9 -0
- package/dest/public/fixtures/public_processor_test_env.d.ts +30 -0
- package/dest/public/fixtures/public_processor_test_env.d.ts.map +1 -0
- package/dest/public/fixtures/public_processor_test_env.js +73 -0
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +77 -0
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -0
- package/dest/public/fixtures/public_tx_simulation_tester.js +176 -0
- package/dest/public/fixtures/simple_contract_data_source.d.ts +36 -0
- package/dest/public/fixtures/simple_contract_data_source.d.ts.map +1 -0
- package/dest/public/fixtures/simple_contract_data_source.js +95 -0
- package/dest/public/fixtures/token_test.d.ts +12 -0
- package/dest/public/fixtures/token_test.d.ts.map +1 -0
- package/dest/public/fixtures/token_test.js +96 -0
- package/dest/public/fixtures/utils.d.ts +26 -0
- package/dest/public/fixtures/utils.d.ts.map +1 -0
- package/dest/public/fixtures/utils.js +170 -0
- package/dest/public/fuzzing/avm_fuzzer_simulator.d.ts +65 -0
- package/dest/public/fuzzing/avm_fuzzer_simulator.d.ts.map +1 -0
- package/dest/public/fuzzing/avm_fuzzer_simulator.js +181 -0
- package/dest/public/fuzzing/avm_simulator_bin.d.ts +2 -0
- package/dest/public/fuzzing/avm_simulator_bin.d.ts.map +1 -0
- package/dest/public/fuzzing/avm_simulator_bin.js +108 -0
- package/dest/public/index.d.ts +10 -0
- package/dest/public/index.d.ts.map +1 -0
- package/dest/public/index.js +6 -0
- package/dest/public/public_db_sources.d.ts +83 -0
- package/dest/public/public_db_sources.d.ts.map +1 -0
- package/dest/public/public_db_sources.js +297 -0
- package/dest/public/public_errors.d.ts +12 -0
- package/dest/public/public_errors.d.ts.map +1 -0
- package/dest/public/public_errors.js +13 -0
- package/dest/public/public_processor/guarded_merkle_tree.d.ts +52 -0
- package/dest/public/public_processor/guarded_merkle_tree.d.ts.map +1 -0
- package/dest/public/public_processor/guarded_merkle_tree.js +116 -0
- package/dest/public/public_processor/public_processor.d.ts +71 -0
- package/dest/public/public_processor/public_processor.d.ts.map +1 -0
- package/dest/public/public_processor/public_processor.js +858 -0
- package/dest/public/public_processor/public_processor_metrics.d.ts +30 -0
- package/dest/public/public_processor/public_processor_metrics.d.ts.map +1 -0
- package/dest/public/public_processor/public_processor_metrics.js +116 -0
- package/dest/public/public_tx_simulator/dumping_public_tx_simulator.d.ts +17 -0
- package/dest/public/public_tx_simulator/dumping_public_tx_simulator.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/dumping_public_tx_simulator.js +39 -0
- package/dest/public/public_tx_simulator/factories.d.ts +14 -0
- package/dest/public/public_tx_simulator/factories.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/factories.js +28 -0
- package/dest/public/public_tx_simulator/index.d.ts +6 -0
- package/dest/public/public_tx_simulator/index.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/index.js +3 -0
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +53 -0
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/public_tx_simulator.js +127 -0
- package/dest/public/public_tx_simulator/public_tx_simulator_base.d.ts +24 -0
- package/dest/public/public_tx_simulator/public_tx_simulator_base.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/public_tx_simulator_base.js +31 -0
- package/dest/public/public_tx_simulator/public_tx_simulator_interface.d.ts +32 -0
- package/dest/public/public_tx_simulator/public_tx_simulator_interface.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/public_tx_simulator_interface.js +1 -0
- package/dest/public/side_effect_errors.d.ts +44 -0
- package/dest/public/side_effect_errors.d.ts.map +1 -0
- package/dest/public/side_effect_errors.js +75 -0
- package/dest/public/test_executor_metrics.d.ts +56 -0
- package/dest/public/test_executor_metrics.d.ts.map +1 -0
- package/dest/public/test_executor_metrics.js +305 -0
- package/dest/public/unique_class_ids.d.ts +37 -0
- package/dest/public/unique_class_ids.d.ts.map +1 -0
- package/dest/public/unique_class_ids.js +61 -0
- package/dest/public/utils.d.ts +3 -0
- package/dest/public/utils.d.ts.map +1 -0
- package/dest/public/utils.js +18 -0
- package/dest/server.d.ts +7 -0
- package/dest/server.d.ts.map +1 -0
- package/dest/server.js +5 -0
- package/package.json +109 -0
- package/src/client.ts +5 -0
- package/src/common/errors.ts +219 -0
- package/src/common/index.ts +2 -0
- package/src/common/stats/index.ts +1 -0
- package/src/common/stats/stats.ts +20 -0
- package/src/private/acvm/acvm.ts +114 -0
- package/src/private/acvm/acvm_types.ts +11 -0
- package/src/private/acvm/deserialize.ts +58 -0
- package/src/private/acvm/index.ts +4 -0
- package/src/private/acvm/serialize.ts +123 -0
- package/src/private/acvm_native.ts +200 -0
- package/src/private/acvm_wasm.ts +80 -0
- package/src/private/acvm_wasm_with_blobs.ts +55 -0
- package/src/private/circuit_simulator.ts +91 -0
- package/src/private/factory.ts +40 -0
- package/src/public/avm/testing/account_proof.json +553 -0
- package/src/public/avm/testing/account_proof_fetcher.ts +166 -0
- package/src/public/avm/testing/base_avm_simulation_tester.ts +162 -0
- package/src/public/avm/testing/utils.ts +114 -0
- package/src/public/avm_simulator.ts +29 -0
- package/src/public/avm_simulator_pool.ts +355 -0
- package/src/public/cdb_ipc_server.ts +198 -0
- package/src/public/contracts_db_checkpoint.ts +41 -0
- package/src/public/db_interfaces.ts +76 -0
- package/src/public/executor_metrics.ts +102 -0
- package/src/public/executor_metrics_interface.ts +20 -0
- package/src/public/fixtures/amm_test.ts +331 -0
- package/src/public/fixtures/bulk_test.ts +194 -0
- package/src/public/fixtures/custom_bytecode_tester.ts +83 -0
- package/src/public/fixtures/index.ts +13 -0
- package/src/public/fixtures/public_processor_test_env.ts +88 -0
- package/src/public/fixtures/public_tx_simulation_tester.ts +315 -0
- package/src/public/fixtures/simple_contract_data_source.ts +122 -0
- package/src/public/fixtures/token_test.ts +148 -0
- package/src/public/fixtures/utils.ts +269 -0
- package/src/public/fuzzing/avm_fuzzer_simulator.ts +302 -0
- package/src/public/fuzzing/avm_simulator_bin.ts +156 -0
- package/src/public/index.ts +16 -0
- package/src/public/public_db_sources.ts +405 -0
- package/src/public/public_errors.ts +14 -0
- package/src/public/public_processor/guarded_merkle_tree.ts +161 -0
- package/src/public/public_processor/public_processor.ts +657 -0
- package/src/public/public_processor/public_processor_metrics.ts +138 -0
- package/src/public/public_tx_simulator/dumping_public_tx_simulator.ts +66 -0
- package/src/public/public_tx_simulator/factories.ts +61 -0
- package/src/public/public_tx_simulator/index.ts +8 -0
- package/src/public/public_tx_simulator/public_tx_simulator.ts +190 -0
- package/src/public/public_tx_simulator/public_tx_simulator_base.ts +37 -0
- package/src/public/public_tx_simulator/public_tx_simulator_interface.ts +33 -0
- package/src/public/side_effect_errors.ts +96 -0
- package/src/public/test_executor_metrics.ts +399 -0
- package/src/public/unique_class_ids.ts +79 -0
- package/src/public/utils.ts +16 -0
- package/src/server.ts +6 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
var _computedKey;
|
|
2
|
+
import { AvmService } from '@aztec/bb-avm-sim';
|
|
3
|
+
import { AbortError } from '@aztec-labs/foundation/error';
|
|
4
|
+
import { createLogger } from '@aztec-labs/foundation/log';
|
|
5
|
+
import { sleep } from '@aztec-labs/foundation/sleep';
|
|
6
|
+
import { CdbIpcServer } from './cdb_ipc_server.js';
|
|
7
|
+
/**
|
|
8
|
+
* The generated service flags errors caused by the death of the underlying process (rather than by the
|
|
9
|
+
* request itself) with `retry: true`. That distinction is interpreted here and goes no further: process
|
|
10
|
+
* lifecycle is invisible to the pool's callers.
|
|
11
|
+
*/ function isProcessFailure(err) {
|
|
12
|
+
return err instanceof Error && err.retry === true;
|
|
13
|
+
}
|
|
14
|
+
/** Sleep that wakes early (without throwing) when the signal aborts; callers re-check the signal. */ async function abortableSleep(ms, signal) {
|
|
15
|
+
if (!signal) {
|
|
16
|
+
return sleep(ms);
|
|
17
|
+
}
|
|
18
|
+
let onAbort;
|
|
19
|
+
const aborted = new Promise((resolve)=>{
|
|
20
|
+
onAbort = resolve;
|
|
21
|
+
signal.addEventListener('abort', onAbort, {
|
|
22
|
+
once: true
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
try {
|
|
26
|
+
await Promise.race([
|
|
27
|
+
sleep(ms),
|
|
28
|
+
aborted
|
|
29
|
+
]);
|
|
30
|
+
} finally{
|
|
31
|
+
signal.removeEventListener('abort', onAbort);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// After a cancellation is requested, how long the C++ process gets to cancel cooperatively (SIGUSR1
|
|
35
|
+
// checkpoint) before it is SIGKILLed. Killing is safe: the service respawns its process lazily, so the
|
|
36
|
+
// pool slot recovers instead of being leaked to a wedged simulation.
|
|
37
|
+
const CANCEL_KILL_GRACE_MS = 5_000;
|
|
38
|
+
_computedKey = Symbol.asyncDispose;
|
|
39
|
+
/**
|
|
40
|
+
* The public-execution AVM backend: a lazily-grown pool of bb-avm-sim services plus the CDB server that
|
|
41
|
+
* answers those processes' contract-data callbacks. Callers hold this as an {@link AvmSimulator}; the pool,
|
|
42
|
+
* the CDB server, its IPC path, and fork-id routing are all hidden behind that interface. Each `simulate`
|
|
43
|
+
* registers the call's contracts DB on the CDB server for the duration of the simulation (keyed by fork id
|
|
44
|
+
* so concurrent simulations on different forks don't collide) and unregisters it once the call returns.
|
|
45
|
+
*
|
|
46
|
+
* Process lifecycle is invisible to callers, exactly as when the simulator ran in-process: a simulation
|
|
47
|
+
* either produces a result, fails on its own merits, or runs until the caller's deadline aborts it.
|
|
48
|
+
* Environmental trouble is absorbed here — spawn failures retry indefinitely on a backoff ladder (bounded
|
|
49
|
+
* only by the caller's abort signal), and a simulation whose process dies is re-issued on the respawned
|
|
50
|
+
* process. The one deliberate exception: an input that kills the process twice is treated as a failing
|
|
51
|
+
* transaction, so a simulator-crashing tx gets evicted instead of burning a process per block forever.
|
|
52
|
+
*/ export class AvmSimulatorPool {
|
|
53
|
+
options;
|
|
54
|
+
slots;
|
|
55
|
+
available;
|
|
56
|
+
waiters;
|
|
57
|
+
createdCount;
|
|
58
|
+
destroyed;
|
|
59
|
+
log;
|
|
60
|
+
maxSize;
|
|
61
|
+
cdbServer;
|
|
62
|
+
spawnRetryIntervalMs;
|
|
63
|
+
spawnProcess;
|
|
64
|
+
constructor(options){
|
|
65
|
+
this.options = options;
|
|
66
|
+
this.slots = [];
|
|
67
|
+
this.available = [];
|
|
68
|
+
this.waiters = [];
|
|
69
|
+
this.createdCount = 0;
|
|
70
|
+
this.destroyed = false;
|
|
71
|
+
this.log = createLogger('simulator:avm-pool');
|
|
72
|
+
this.maxSize = options.maxSize ?? parseInt(process.env.AVM_MAX_CONCURRENT_SIMULATIONS ?? '4', 10);
|
|
73
|
+
this.cdbServer = new CdbIpcServer();
|
|
74
|
+
this.spawnRetryIntervalMs = options.spawnRetryIntervalMs ?? 1_000;
|
|
75
|
+
this.spawnProcess = options.spawnProcess ?? ((spawnOptions)=>AvmSimulatorProcess.spawn(spawnOptions));
|
|
76
|
+
}
|
|
77
|
+
static async spawn(options) {
|
|
78
|
+
const pool = new AvmSimulatorPool(options);
|
|
79
|
+
// Always start one process up front so the first simulate() doesn't pay process spawn/connect cost.
|
|
80
|
+
// This is also where configuration errors (missing binary) surface, fast and fatally.
|
|
81
|
+
await pool.prewarm();
|
|
82
|
+
return pool;
|
|
83
|
+
}
|
|
84
|
+
async [_computedKey]() {
|
|
85
|
+
await this.destroy();
|
|
86
|
+
}
|
|
87
|
+
async simulate(inputBuffer, context, signal) {
|
|
88
|
+
// Register the fork's contracts DB so the C++ AVM's callbacks (which carry this fork id) route to it,
|
|
89
|
+
// and unregister once the simulation returns — registration is only needed while the call is running.
|
|
90
|
+
this.cdbServer.registerFork(context.forkId, context.contractsDB, context.timestamp);
|
|
91
|
+
try {
|
|
92
|
+
return await this.runOnPool((simulator)=>simulator.simulate(inputBuffer, signal), signal);
|
|
93
|
+
} finally{
|
|
94
|
+
this.cdbServer.unregisterFork(context.forkId);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async simulateWithHints(inputBuffer) {
|
|
98
|
+
// The hinted path makes no contract-data callbacks, so no CDB registration is needed.
|
|
99
|
+
return await this.runOnPool((simulator)=>simulator.simulateWithHints(inputBuffer));
|
|
100
|
+
}
|
|
101
|
+
/** Destroy all AVM services in the pool and close the CDB server. */ async destroy() {
|
|
102
|
+
this.destroyed = true;
|
|
103
|
+
for (const waiter of this.waiters.splice(0)){
|
|
104
|
+
waiter.reject(new Error('AVM simulator pool destroyed'));
|
|
105
|
+
}
|
|
106
|
+
await Promise.all(this.slots.map((slot)=>slot.destroy()));
|
|
107
|
+
this.slots = [];
|
|
108
|
+
this.available = [];
|
|
109
|
+
this.createdCount = 0;
|
|
110
|
+
await this.cdbServer.close();
|
|
111
|
+
this.log.info('AVM simulator pool destroyed');
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Eagerly spawn up to `count` AVM processes (capped at maxSize) and leave them available, so the
|
|
115
|
+
* first simulate() doesn't pay process spawn/connect cost. Idempotent.
|
|
116
|
+
*/ async prewarm(count = 1) {
|
|
117
|
+
const target = Math.min(count, this.maxSize);
|
|
118
|
+
const created = [];
|
|
119
|
+
while(this.createdCount < target){
|
|
120
|
+
created.push(await this.checkout());
|
|
121
|
+
}
|
|
122
|
+
// Hand the checked-out processes back to the pool so checkout() reuses them.
|
|
123
|
+
for (const simulator of created){
|
|
124
|
+
this.return(simulator);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Run a call on a pooled service. A call that fails because its process died is re-issued on the
|
|
129
|
+
* respawned process; a second death for the same input is attributed to the input and surfaces as an
|
|
130
|
+
* ordinary error (the pre-IPC equivalent — a native crash — took down the whole node, so a failed tx
|
|
131
|
+
* is strictly gentler). Non-process failures surface as-is: they are the simulation's own verdict.
|
|
132
|
+
*/ async runOnPool(fn, signal) {
|
|
133
|
+
for(let attempt = 0;; attempt++){
|
|
134
|
+
const simulator = await this.checkout(signal);
|
|
135
|
+
try {
|
|
136
|
+
return await fn(simulator);
|
|
137
|
+
} catch (err) {
|
|
138
|
+
if (!isProcessFailure(err) || signal?.aborted) {
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
141
|
+
if (attempt > 0) {
|
|
142
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
143
|
+
throw new Error(`AVM simulator process died twice running this simulation; attributing the failure to the input: ${message}`, {
|
|
144
|
+
cause: err
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
this.log.warn(`AVM process died during simulation; re-issuing once on the respawned process`, {
|
|
148
|
+
err
|
|
149
|
+
});
|
|
150
|
+
} finally{
|
|
151
|
+
this.return(simulator);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/** Check out an AVM service from the pool, blocking until one is free. Caller must return() it when done. */ async checkout(signal) {
|
|
156
|
+
if (this.destroyed) {
|
|
157
|
+
throw new Error('AVM simulator pool destroyed');
|
|
158
|
+
}
|
|
159
|
+
const idx = this.available.pop();
|
|
160
|
+
if (idx !== undefined) {
|
|
161
|
+
return this.slots[idx];
|
|
162
|
+
}
|
|
163
|
+
if (this.createdCount < this.maxSize) {
|
|
164
|
+
return await this.createSlot(signal);
|
|
165
|
+
}
|
|
166
|
+
return new Promise((resolve, reject)=>{
|
|
167
|
+
const waiter = {
|
|
168
|
+
resolve,
|
|
169
|
+
reject
|
|
170
|
+
};
|
|
171
|
+
if (signal) {
|
|
172
|
+
const onAbort = ()=>{
|
|
173
|
+
const at = this.waiters.indexOf(waiter);
|
|
174
|
+
if (at >= 0) {
|
|
175
|
+
this.waiters.splice(at, 1);
|
|
176
|
+
reject(new AbortError('AVM checkout aborted'));
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
signal.addEventListener('abort', onAbort, {
|
|
180
|
+
once: true
|
|
181
|
+
});
|
|
182
|
+
waiter.resolve = (simulator)=>{
|
|
183
|
+
signal.removeEventListener('abort', onAbort);
|
|
184
|
+
resolve(simulator);
|
|
185
|
+
};
|
|
186
|
+
waiter.reject = (err)=>{
|
|
187
|
+
signal.removeEventListener('abort', onAbort);
|
|
188
|
+
reject(err);
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
this.waiters.push(waiter);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
/** Return an AVM service to the pool after use. */ return(simulator) {
|
|
195
|
+
const waiter = this.waiters.shift();
|
|
196
|
+
if (waiter) {
|
|
197
|
+
waiter.resolve(simulator);
|
|
198
|
+
} else {
|
|
199
|
+
const idx = this.slots.indexOf(simulator);
|
|
200
|
+
if (idx >= 0) {
|
|
201
|
+
this.available.push(idx);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async createSlot(signal) {
|
|
206
|
+
// Reserve the slot count synchronously, before the async spawn, so concurrent checkouts can't all
|
|
207
|
+
// observe `createdCount < maxSize` and overshoot the pool (the count is only bumped once control has
|
|
208
|
+
// yielded on the await). Roll back the reservation if the spawn is abandoned.
|
|
209
|
+
this.createdCount++;
|
|
210
|
+
try {
|
|
211
|
+
const simulator = await this.spawnUntilUp(signal);
|
|
212
|
+
this.slots.push(simulator);
|
|
213
|
+
this.log.debug(`Created AVM pool slot (${this.createdCount}/${this.maxSize})`);
|
|
214
|
+
return simulator;
|
|
215
|
+
} catch (err) {
|
|
216
|
+
this.createdCount--;
|
|
217
|
+
throw err;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Spawn a service, retrying environmental failures on a flat cadence indefinitely — the bound is
|
|
222
|
+
* the caller's own deadline (abort signal), matching the pre-IPC contract where a simulation either
|
|
223
|
+
* completed or was deadlined out. The cadence is deliberately fast and constant: an attempt is cheap,
|
|
224
|
+
* a slow one self-paces inside the backend's connect backstop, and backing off would cost a
|
|
225
|
+
* ~6s-slot sequencer whole blocks after the machine has already recovered. Configuration errors
|
|
226
|
+
* (missing binary, flagged non-retryable by the generated service) throw immediately; the boot-time
|
|
227
|
+
* prewarm is where those are meant to surface.
|
|
228
|
+
*/ async spawnUntilUp(signal) {
|
|
229
|
+
for(let failures = 0;; failures++){
|
|
230
|
+
if (this.destroyed) {
|
|
231
|
+
throw new Error('AVM simulator pool destroyed');
|
|
232
|
+
}
|
|
233
|
+
if (signal?.aborted) {
|
|
234
|
+
throw new AbortError('AVM process spawn aborted');
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
return await this.spawnProcess({
|
|
238
|
+
binaryPath: this.options.avmBinaryPath,
|
|
239
|
+
wsdbIpcPath: this.options.wsdbIpcPath,
|
|
240
|
+
cdbIpcPath: this.cdbServer.ipcPath,
|
|
241
|
+
logger: this.options.logger
|
|
242
|
+
});
|
|
243
|
+
} catch (err) {
|
|
244
|
+
if (!isProcessFailure(err)) {
|
|
245
|
+
throw err;
|
|
246
|
+
}
|
|
247
|
+
this.log.warn(`Failed to spawn AVM process (attempt ${failures + 1}); retrying in ${this.spawnRetryIntervalMs}ms`, {
|
|
248
|
+
err
|
|
249
|
+
});
|
|
250
|
+
await abortableSleep(this.spawnRetryIntervalMs, signal);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
class AvmSimulatorProcess {
|
|
256
|
+
service;
|
|
257
|
+
constructor(service){
|
|
258
|
+
this.service = service;
|
|
259
|
+
}
|
|
260
|
+
static async spawn(options) {
|
|
261
|
+
const service = await AvmService.spawn({
|
|
262
|
+
binaryPath: options.binaryPath,
|
|
263
|
+
transport: 'uds',
|
|
264
|
+
logger: options.logger,
|
|
265
|
+
extraArgs: [
|
|
266
|
+
'--wsdb',
|
|
267
|
+
options.wsdbIpcPath,
|
|
268
|
+
'--cdb',
|
|
269
|
+
options.cdbIpcPath
|
|
270
|
+
],
|
|
271
|
+
// Each simulation is self-contained (state comes from the WSDB/CDB servers, routed by fork id),
|
|
272
|
+
// so a fresh process can safely serve the next call after a death.
|
|
273
|
+
respawn: true
|
|
274
|
+
});
|
|
275
|
+
return new AvmSimulatorProcess(service);
|
|
276
|
+
}
|
|
277
|
+
async simulate(inputBuffer, signal) {
|
|
278
|
+
let killTimer;
|
|
279
|
+
// Cooperative cancellation first: SIGUSR1 makes the C++ process stop at its next cancellation
|
|
280
|
+
// checkpoint. If it doesn't respond within the grace (wedged in a slow op), SIGKILL it — the
|
|
281
|
+
// service respawns lazily, so this reclaims the pool slot rather than leaking it.
|
|
282
|
+
const onAbort = ()=>{
|
|
283
|
+
this.service.sendProcessSignal('SIGUSR1');
|
|
284
|
+
killTimer = setTimeout(()=>this.service.sendProcessSignal('SIGKILL'), CANCEL_KILL_GRACE_MS);
|
|
285
|
+
};
|
|
286
|
+
if (signal?.aborted) {
|
|
287
|
+
onAbort();
|
|
288
|
+
}
|
|
289
|
+
signal?.addEventListener('abort', onAbort, {
|
|
290
|
+
once: true
|
|
291
|
+
});
|
|
292
|
+
try {
|
|
293
|
+
return (await this.service.simulate({
|
|
294
|
+
inputs: inputBuffer
|
|
295
|
+
})).result;
|
|
296
|
+
} finally{
|
|
297
|
+
signal?.removeEventListener('abort', onAbort);
|
|
298
|
+
if (killTimer !== undefined) {
|
|
299
|
+
clearTimeout(killTimer);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
async simulateWithHints(inputBuffer) {
|
|
304
|
+
return (await this.service.simulateWithHints({
|
|
305
|
+
inputs: inputBuffer
|
|
306
|
+
})).result;
|
|
307
|
+
}
|
|
308
|
+
async destroy() {
|
|
309
|
+
await this.service.destroy();
|
|
310
|
+
}
|
|
311
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UDS server for AVM CDB requests.
|
|
3
|
+
*
|
|
4
|
+
* Transport (socket, framing, per-connection response ordering) is handled by the shared
|
|
5
|
+
* `UdsIpcServer` from `@aztec/ipc-runtime`; message dispatch comes from the generated CDB
|
|
6
|
+
* server. This class only implements the generated handler interface and routes requests to
|
|
7
|
+
* PublicContractsDB instances by fork ID.
|
|
8
|
+
*/
|
|
9
|
+
import { type CdbAddContracts, type CdbAddContractsResponse, type CdbCommitCheckpoint, type CdbCommitCheckpointResponse, type CdbCreateCheckpoint, type CdbCreateCheckpointResponse, type CdbGetBytecodeCommitment, type CdbGetBytecodeCommitmentResponse, type CdbGetContractClass, type CdbGetContractClassResponse, type CdbGetContractInstance, type CdbGetContractInstanceResponse, type CdbGetDebugFunctionName, type CdbGetDebugFunctionNameResponse, type Handler as CdbHandler, type CdbRevertCheckpoint, type CdbRevertCheckpointResponse } from '@aztec/cdb';
|
|
10
|
+
import { type ContractInstanceWithAddress } from '@aztec-labs/stdlib/contract';
|
|
11
|
+
import type { PublicContractsDB } from './public_db_sources.js';
|
|
12
|
+
/** Serializes contract instances to the AVM CDB wire shape. */
|
|
13
|
+
export declare function serializeContractInstance(instance: ContractInstanceWithAddress): Record<string, unknown>;
|
|
14
|
+
/** Routes AVM CDB IPC requests to registered PublicContractsDB forks. */
|
|
15
|
+
export declare class CdbIpcServer implements CdbHandler {
|
|
16
|
+
readonly ipcPath: string;
|
|
17
|
+
private server;
|
|
18
|
+
private log;
|
|
19
|
+
/** Maps WSDB fork IDs to contracts DB/timestamp pairs for concurrent simulations. */
|
|
20
|
+
private forks;
|
|
21
|
+
constructor();
|
|
22
|
+
/** Register a PublicContractsDB for a given WSDB fork ID. */
|
|
23
|
+
registerFork(forkId: number, contractsDB: PublicContractsDB, timestamp: bigint): void;
|
|
24
|
+
/** Unregister a fork's contracts DB (call after simulation completes). */
|
|
25
|
+
unregisterFork(forkId: number): void;
|
|
26
|
+
/** Close the server and all active connections. */
|
|
27
|
+
close(): Promise<void>;
|
|
28
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
29
|
+
/** Look up the contracts DB for a given fork ID, throwing if not registered. */
|
|
30
|
+
private getFork;
|
|
31
|
+
getContractInstance(command: CdbGetContractInstance): Promise<CdbGetContractInstanceResponse>;
|
|
32
|
+
getContractClass(command: CdbGetContractClass): Promise<CdbGetContractClassResponse>;
|
|
33
|
+
getBytecodeCommitment(command: CdbGetBytecodeCommitment): Promise<CdbGetBytecodeCommitmentResponse>;
|
|
34
|
+
getDebugFunctionName(command: CdbGetDebugFunctionName): Promise<CdbGetDebugFunctionNameResponse>;
|
|
35
|
+
addContracts(command: CdbAddContracts): Promise<CdbAddContractsResponse>;
|
|
36
|
+
createCheckpoint(command: CdbCreateCheckpoint): Promise<CdbCreateCheckpointResponse>;
|
|
37
|
+
commitCheckpoint(command: CdbCommitCheckpoint): Promise<CdbCommitCheckpointResponse>;
|
|
38
|
+
revertCheckpoint(command: CdbRevertCheckpoint): Promise<CdbRevertCheckpointResponse>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2RiX2lwY19zZXJ2ZXIuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wdWJsaWMvY2RiX2lwY19zZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRztBQUNILE9BQU8sRUFDTCxLQUFLLGVBQWUsRUFDcEIsS0FBSyx1QkFBdUIsRUFDNUIsS0FBSyxtQkFBbUIsRUFDeEIsS0FBSywyQkFBMkIsRUFDaEMsS0FBSyxtQkFBbUIsRUFDeEIsS0FBSywyQkFBMkIsRUFDaEMsS0FBSyx3QkFBd0IsRUFDN0IsS0FBSyxnQ0FBZ0MsRUFDckMsS0FBSyxtQkFBbUIsRUFDeEIsS0FBSywyQkFBMkIsRUFDaEMsS0FBSyxzQkFBc0IsRUFDM0IsS0FBSyw4QkFBOEIsRUFDbkMsS0FBSyx1QkFBdUIsRUFDNUIsS0FBSywrQkFBK0IsRUFDcEMsS0FBSyxPQUFPLElBQUksVUFBVSxFQUMxQixLQUFLLG1CQUFtQixFQUN4QixLQUFLLDJCQUEyQixFQUVqQyxNQUFNLFlBQVksQ0FBQztBQU9wQixPQUFPLEVBQTBCLEtBQUssMkJBQTJCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQU12RyxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBV2hFLCtEQUErRDtBQUMvRCx3QkFBZ0IseUJBQXlCLENBQUMsUUFBUSxFQUFFLDJCQUEyQixHQUFHLE1BQU0sQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBb0J4RztBQWlCRCx5RUFBeUU7QUFDekUscUJBQWEsWUFBYSxZQUFXLFVBQVU7SUFDN0MsU0FBZ0IsT0FBTyxFQUFFLE1BQU0sQ0FBQztJQUNoQyxPQUFPLENBQUMsTUFBTSxDQUF3QjtJQUN0QyxPQUFPLENBQUMsR0FBRyxDQUFTO0lBQ3BCLHFGQUFxRjtJQUNyRixPQUFPLENBQUMsS0FBSyxDQUFtRTtJQUVoRixjQVVDO0lBRUQsNkRBQTZEO0lBQzdELFlBQVksQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsTUFBTSxHQUFHLElBQUksQ0FFcEY7SUFFRCwwRUFBMEU7SUFDMUUsY0FBYyxDQUFDLE1BQU0sRUFBRSxNQUFNLEdBQUcsSUFBSSxDQUVuQztJQUVELG1EQUFtRDtJQUM3QyxLQUFLLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUczQjtJQUVLLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FFM0M7SUFFRCxnRkFBZ0Y7SUFDaEYsT0FBTyxDQUFDLE9BQU87SUFXVCxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsc0JBQXNCLEdBQUcsT0FBTyxDQUFDLDhCQUE4QixDQUFDLENBS2xHO0lBRUssZ0JBQWdCLENBQUMsT0FBTyxFQUFFLG1CQUFtQixHQUFHLE9BQU8sQ0FBQywyQkFBMkIsQ0FBQyxDQUt6RjtJQUVLLHFCQUFxQixDQUFDLE9BQU8sRUFBRSx3QkFBd0IsR0FBRyxPQUFPLENBQUMsZ0NBQWdDLENBQUMsQ0FLeEc7SUFFSyxvQkFBb0IsQ0FBQyxPQUFPLEVBQUUsdUJBQXVCLEdBQUcsT0FBTyxDQUFDLCtCQUErQixDQUFDLENBT3JHO0lBRUQsWUFBWSxDQUFDLE9BQU8sRUFBRSxlQUFlLEdBQUcsT0FBTyxDQUFDLHVCQUF1QixDQUFDLENBT3ZFO0lBRUQsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLG1CQUFtQixHQUFHLE9BQU8sQ0FBQywyQkFBMkIsQ0FBQyxDQUluRjtJQUVELGdCQUFnQixDQUFDLE9BQU8sRUFBRSxtQkFBbUIsR0FBRyxPQUFPLENBQUMsMkJBQTJCLENBQUMsQ0FJbkY7SUFFRCxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsbUJBQW1CLEdBQUcsT0FBTyxDQUFDLDJCQUEyQixDQUFDLENBSW5GO0NBQ0YifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdb_ipc_server.d.ts","sourceRoot":"","sources":["../../src/public/cdb_ipc_server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAChC,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,KAAK,gCAAgC,EACrC,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAChC,KAAK,sBAAsB,EAC3B,KAAK,8BAA8B,EACnC,KAAK,uBAAuB,EAC5B,KAAK,+BAA+B,EACpC,KAAK,OAAO,IAAI,UAAU,EAC1B,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAEjC,MAAM,YAAY,CAAC;AAOpB,OAAO,EAA0B,KAAK,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAMvG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAWhE,+DAA+D;AAC/D,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoBxG;AAiBD,yEAAyE;AACzE,qBAAa,YAAa,YAAW,UAAU;IAC7C,SAAgB,OAAO,EAAE,MAAM,CAAC;IAChC,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,GAAG,CAAS;IACpB,qFAAqF;IACrF,OAAO,CAAC,KAAK,CAAmE;IAEhF,cAUC;IAED,6DAA6D;IAC7D,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAEpF;IAED,0EAA0E;IAC1E,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEnC;IAED,mDAAmD;IAC7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAG3B;IAEK,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAE3C;IAED,gFAAgF;IAChF,OAAO,CAAC,OAAO;IAWT,mBAAmB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAKlG;IAEK,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAKzF;IAEK,qBAAqB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,gCAAgC,CAAC,CAKxG;IAEK,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,+BAA+B,CAAC,CAOrG;IAED,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAOvE;IAED,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAInF;IAED,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAInF;IAED,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAInF;CACF"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UDS server for AVM CDB requests.
|
|
3
|
+
*
|
|
4
|
+
* Transport (socket, framing, per-connection response ordering) is handled by the shared
|
|
5
|
+
* `UdsIpcServer` from `@aztec/ipc-runtime`; message dispatch comes from the generated CDB
|
|
6
|
+
* server. This class only implements the generated handler interface and routes requests to
|
|
7
|
+
* PublicContractsDB instances by fork ID.
|
|
8
|
+
*/ var _computedKey;
|
|
9
|
+
import { handleRequest } from '@aztec/cdb';
|
|
10
|
+
import { UdsIpcServer } from '@aztec/ipc-runtime';
|
|
11
|
+
import { Fr } from '@aztec-labs/foundation/curves/bn254';
|
|
12
|
+
import { createLogger } from '@aztec-labs/foundation/log';
|
|
13
|
+
import { FunctionSelector } from '@aztec-labs/stdlib/abi';
|
|
14
|
+
import { AztecAddress } from '@aztec-labs/stdlib/aztec-address';
|
|
15
|
+
import { ContractDeploymentData } from '@aztec-labs/stdlib/contract';
|
|
16
|
+
import { Decoder, Encoder } from 'msgpackr';
|
|
17
|
+
import * as os from 'node:os';
|
|
18
|
+
import * as path from 'node:path';
|
|
19
|
+
import { threadId } from 'node:worker_threads';
|
|
20
|
+
const encoder = new Encoder({
|
|
21
|
+
useRecords: false
|
|
22
|
+
});
|
|
23
|
+
const decoder = new Decoder({
|
|
24
|
+
useRecords: false
|
|
25
|
+
});
|
|
26
|
+
let instanceCounter = 0;
|
|
27
|
+
function toFieldBuffer(field) {
|
|
28
|
+
return field.toBuffer();
|
|
29
|
+
}
|
|
30
|
+
/** Serializes contract instances to the AVM CDB wire shape. */ export function serializeContractInstance(instance) {
|
|
31
|
+
return {
|
|
32
|
+
salt: toFieldBuffer(instance.salt),
|
|
33
|
+
deployer: toFieldBuffer(instance.deployer),
|
|
34
|
+
currentContractClassId: toFieldBuffer(instance.currentContractClassId),
|
|
35
|
+
originalContractClassId: toFieldBuffer(instance.originalContractClassId),
|
|
36
|
+
initializationHash: toFieldBuffer(instance.initializationHash),
|
|
37
|
+
immutablesHash: toFieldBuffer(instance.immutablesHash),
|
|
38
|
+
publicKeys: {
|
|
39
|
+
npkMHash: toFieldBuffer(instance.publicKeys.npkMHash),
|
|
40
|
+
ivpkM: {
|
|
41
|
+
x: toFieldBuffer(instance.publicKeys.ivpkM.x),
|
|
42
|
+
y: toFieldBuffer(instance.publicKeys.ivpkM.y)
|
|
43
|
+
},
|
|
44
|
+
ovpkMHash: toFieldBuffer(instance.publicKeys.ovpkMHash),
|
|
45
|
+
tpkMHash: toFieldBuffer(instance.publicKeys.tpkMHash),
|
|
46
|
+
mspkMHash: toFieldBuffer(instance.publicKeys.mspkMHash),
|
|
47
|
+
fbpkMHash: toFieldBuffer(instance.publicKeys.fbpkMHash)
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** Serializes contract classes to the AVM CDB wire shape. */ function serializeContractClass(contractClass) {
|
|
52
|
+
return {
|
|
53
|
+
id: toFieldBuffer(contractClass.id),
|
|
54
|
+
artifactHash: toFieldBuffer(contractClass.artifactHash),
|
|
55
|
+
privateFunctionsRoot: toFieldBuffer(contractClass.privateFunctionsRoot),
|
|
56
|
+
packedBytecode: contractClass.packedBytecode
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
_computedKey = Symbol.asyncDispose;
|
|
60
|
+
/** Routes AVM CDB IPC requests to registered PublicContractsDB forks. */ export class CdbIpcServer {
|
|
61
|
+
ipcPath;
|
|
62
|
+
server;
|
|
63
|
+
log;
|
|
64
|
+
/** Maps WSDB fork IDs to contracts DB/timestamp pairs for concurrent simulations. */ forks = new Map();
|
|
65
|
+
constructor(){
|
|
66
|
+
this.log = createLogger('cdb-ipc-server');
|
|
67
|
+
this.ipcPath = path.join(os.tmpdir(), `cdb-ts-${process.pid}-${threadId}-${instanceCounter++}.sock`);
|
|
68
|
+
// Listen asynchronously; the C++ AVM retries connecting until the socket is up.
|
|
69
|
+
this.server = UdsIpcServer.listen(this.ipcPath, (_clientId, request)=>handleRequest(this, request));
|
|
70
|
+
this.server.then(()=>this.log.debug(`CDB IPC server listening on ${this.ipcPath}`), (err)=>this.log.error(`CDB IPC server failed to listen on ${this.ipcPath}`, {
|
|
71
|
+
err
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
/** Register a PublicContractsDB for a given WSDB fork ID. */ registerFork(forkId, contractsDB, timestamp) {
|
|
75
|
+
this.forks.set(forkId, {
|
|
76
|
+
db: contractsDB,
|
|
77
|
+
timestamp
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/** Unregister a fork's contracts DB (call after simulation completes). */ unregisterFork(forkId) {
|
|
81
|
+
this.forks.delete(forkId);
|
|
82
|
+
}
|
|
83
|
+
/** Close the server and all active connections. */ async close() {
|
|
84
|
+
const server = await this.server.catch(()=>undefined);
|
|
85
|
+
await server?.close();
|
|
86
|
+
}
|
|
87
|
+
async [_computedKey]() {
|
|
88
|
+
await this.close();
|
|
89
|
+
}
|
|
90
|
+
/** Look up the contracts DB for a given fork ID, throwing if not registered. */ getFork(forkId) {
|
|
91
|
+
const fork = this.forks.get(forkId);
|
|
92
|
+
if (!fork) {
|
|
93
|
+
const registered = Array.from(this.forks.keys()).sort((a, b)=>a - b);
|
|
94
|
+
throw new Error(`CDB server: no contracts DB registered for forkId ${forkId} (registered=[${registered.join(',')}])`);
|
|
95
|
+
}
|
|
96
|
+
return fork;
|
|
97
|
+
}
|
|
98
|
+
async getContractInstance(command) {
|
|
99
|
+
const { db, timestamp } = this.getFork(command.forkId);
|
|
100
|
+
const address = AztecAddress.fromBuffer(Buffer.from(command.address));
|
|
101
|
+
const instance = await db.getContractInstance(address, timestamp);
|
|
102
|
+
return {
|
|
103
|
+
instance: instance ? encoder.encode(serializeContractInstance(instance)) : null
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async getContractClass(command) {
|
|
107
|
+
const { db } = this.getFork(command.forkId);
|
|
108
|
+
const classId = Fr.fromBuffer(Buffer.from(command.classId));
|
|
109
|
+
const contractClass = await db.getContractClass(classId);
|
|
110
|
+
return {
|
|
111
|
+
contractClass: contractClass ? encoder.encode(serializeContractClass(contractClass)) : null
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
async getBytecodeCommitment(command) {
|
|
115
|
+
const { db } = this.getFork(command.forkId);
|
|
116
|
+
const classId = Fr.fromBuffer(Buffer.from(command.classId));
|
|
117
|
+
const commitment = await db.getBytecodeCommitment(classId);
|
|
118
|
+
return {
|
|
119
|
+
commitment: commitment ? toFieldBuffer(commitment) : null
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async getDebugFunctionName(command) {
|
|
123
|
+
const { db } = this.getFork(command.forkId);
|
|
124
|
+
const address = AztecAddress.fromBuffer(Buffer.from(command.address));
|
|
125
|
+
const selectorField = Fr.fromBuffer(Buffer.from(command.selector));
|
|
126
|
+
const selector = FunctionSelector.fromFieldOrUndefined(selectorField);
|
|
127
|
+
const name = selector ? await db.getDebugFunctionName(address, selector) : undefined;
|
|
128
|
+
return {
|
|
129
|
+
name: name ?? null
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
addContracts(command) {
|
|
133
|
+
const { db } = this.getFork(command.forkId);
|
|
134
|
+
const contractDeploymentData = ContractDeploymentData.fromPlainObject(decoder.decode(command.contractDeploymentData));
|
|
135
|
+
db.addContractsFromLogs(contractDeploymentData);
|
|
136
|
+
return Promise.resolve({});
|
|
137
|
+
}
|
|
138
|
+
createCheckpoint(command) {
|
|
139
|
+
const { db } = this.getFork(command.forkId);
|
|
140
|
+
db.createCheckpoint();
|
|
141
|
+
return Promise.resolve({});
|
|
142
|
+
}
|
|
143
|
+
commitCheckpoint(command) {
|
|
144
|
+
const { db } = this.getFork(command.forkId);
|
|
145
|
+
db.commitCheckpoint();
|
|
146
|
+
return Promise.resolve({});
|
|
147
|
+
}
|
|
148
|
+
revertCheckpoint(command) {
|
|
149
|
+
const { db } = this.getFork(command.forkId);
|
|
150
|
+
db.revertCheckpoint();
|
|
151
|
+
return Promise.resolve({});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Fr } from '@aztec-labs/foundation/curves/bn254';
|
|
2
|
+
import type { AztecAddress } from '@aztec-labs/stdlib/aztec-address';
|
|
3
|
+
import type { ContractClassPublic, ContractInstanceWithAddress } from '@aztec-labs/stdlib/contract';
|
|
4
|
+
export declare class ContractsDbCheckpoint {
|
|
5
|
+
private instances;
|
|
6
|
+
private classes;
|
|
7
|
+
private bytecodeCommitments;
|
|
8
|
+
addInstance(address: AztecAddress, instance: ContractInstanceWithAddress): void;
|
|
9
|
+
addClass(classId: Fr, contractClass: ContractClassPublic): void;
|
|
10
|
+
addBytecodeCommitment(classId: Fr, commitment: Fr): void;
|
|
11
|
+
getInstance(address: AztecAddress): ContractInstanceWithAddress | undefined;
|
|
12
|
+
getClass(classId: Fr): ContractClassPublic | undefined;
|
|
13
|
+
getBytecodeCommitment(classId: Fr): Fr | undefined;
|
|
14
|
+
fork(): ContractsDbCheckpoint;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhY3RzX2RiX2NoZWNrcG9pbnQuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wdWJsaWMvY29udHJhY3RzX2RiX2NoZWNrcG9pbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsRUFBRSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDOUQsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDckUsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUVwRyxxQkFBYSxxQkFBcUI7SUFDaEMsT0FBTyxDQUFDLFNBQVMsQ0FBdUQ7SUFDeEUsT0FBTyxDQUFDLE9BQU8sQ0FBK0M7SUFDOUQsT0FBTyxDQUFDLG1CQUFtQixDQUE4QjtJQUVsRCxXQUFXLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsMkJBQTJCLEdBQUcsSUFBSSxDQUVyRjtJQUVNLFFBQVEsQ0FBQyxPQUFPLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxtQkFBbUIsR0FBRyxJQUFJLENBRXJFO0lBRU0scUJBQXFCLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxVQUFVLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FFOUQ7SUFFTSxXQUFXLENBQUMsT0FBTyxFQUFFLFlBQVksR0FBRywyQkFBMkIsR0FBRyxTQUFTLENBRWpGO0lBRU0sUUFBUSxDQUFDLE9BQU8sRUFBRSxFQUFFLEdBQUcsbUJBQW1CLEdBQUcsU0FBUyxDQUU1RDtJQUVNLHFCQUFxQixDQUFDLE9BQU8sRUFBRSxFQUFFLEdBQUcsRUFBRSxHQUFHLFNBQVMsQ0FFeEQ7SUFFTSxJQUFJLElBQUkscUJBQXFCLENBTW5DO0NBQ0YifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts_db_checkpoint.d.ts","sourceRoot":"","sources":["../../src/public/contracts_db_checkpoint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,qCAAqC,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAEpG,qBAAa,qBAAqB;IAChC,OAAO,CAAC,SAAS,CAAuD;IACxE,OAAO,CAAC,OAAO,CAA+C;IAC9D,OAAO,CAAC,mBAAmB,CAA8B;IAElD,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,2BAA2B,GAAG,IAAI,CAErF;IAEM,QAAQ,CAAC,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,mBAAmB,GAAG,IAAI,CAErE;IAEM,qBAAqB,CAAC,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,GAAG,IAAI,CAE9D;IAEM,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,2BAA2B,GAAG,SAAS,CAEjF;IAEM,QAAQ,CAAC,OAAO,EAAE,EAAE,GAAG,mBAAmB,GAAG,SAAS,CAE5D;IAEM,qBAAqB,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,GAAG,SAAS,CAExD;IAEM,IAAI,IAAI,qBAAqB,CAMnC;CACF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export class ContractsDbCheckpoint {
|
|
2
|
+
instances = new Map();
|
|
3
|
+
classes = new Map();
|
|
4
|
+
bytecodeCommitments = new Map();
|
|
5
|
+
addInstance(address, instance) {
|
|
6
|
+
this.instances.set(address.toString(), instance);
|
|
7
|
+
}
|
|
8
|
+
addClass(classId, contractClass) {
|
|
9
|
+
this.classes.set(classId.toString(), contractClass);
|
|
10
|
+
}
|
|
11
|
+
addBytecodeCommitment(classId, commitment) {
|
|
12
|
+
this.bytecodeCommitments.set(classId.toString(), commitment);
|
|
13
|
+
}
|
|
14
|
+
getInstance(address) {
|
|
15
|
+
return this.instances.get(address.toString());
|
|
16
|
+
}
|
|
17
|
+
getClass(classId) {
|
|
18
|
+
return this.classes.get(classId.toString());
|
|
19
|
+
}
|
|
20
|
+
getBytecodeCommitment(classId) {
|
|
21
|
+
return this.bytecodeCommitments.get(classId.toString());
|
|
22
|
+
}
|
|
23
|
+
fork() {
|
|
24
|
+
const copy = new ContractsDbCheckpoint();
|
|
25
|
+
this.instances.forEach((value, key)=>copy.instances.set(key, value));
|
|
26
|
+
this.classes.forEach((value, key)=>copy.classes.set(key, value));
|
|
27
|
+
this.bytecodeCommitments.forEach((value, key)=>copy.bytecodeCommitments.set(key, value));
|
|
28
|
+
return copy;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { Fr } from '@aztec-labs/foundation/curves/bn254';
|
|
2
|
+
import type { FunctionSelector } from '@aztec-labs/stdlib/abi';
|
|
3
|
+
import type { AztecAddress } from '@aztec-labs/stdlib/aztec-address';
|
|
4
|
+
import type { ContractClassPublic, ContractInstanceWithAddress } from '@aztec-labs/stdlib/contract';
|
|
5
|
+
import type { UInt64 } from '@aztec-labs/stdlib/types';
|
|
6
|
+
/**
|
|
7
|
+
* Database interface for providing access to public state.
|
|
8
|
+
*/
|
|
9
|
+
export interface PublicStateDBInterface {
|
|
10
|
+
/**
|
|
11
|
+
* Reads a value from public storage, returning zero if none.
|
|
12
|
+
* @param contract - Owner of the storage.
|
|
13
|
+
* @param slot - Slot to read in the contract storage.
|
|
14
|
+
* @returns The current value in the storage slot.
|
|
15
|
+
*/
|
|
16
|
+
storageRead(contract: AztecAddress, slot: Fr): Promise<Fr>;
|
|
17
|
+
/**
|
|
18
|
+
* Records a write to public storage.
|
|
19
|
+
* @param contract - Owner of the storage.
|
|
20
|
+
* @param slot - Slot to read in the contract storage.
|
|
21
|
+
* @param newValue - The new value to store.
|
|
22
|
+
*/
|
|
23
|
+
storageWrite(contract: AztecAddress, slot: Fr, newValue: Fr): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Database interface for providing access to public contract data.
|
|
27
|
+
*/
|
|
28
|
+
export interface PublicContractsDBInterface {
|
|
29
|
+
/**
|
|
30
|
+
* Returns a contract instance given its address and the given timestamp, or undefined if not exists.
|
|
31
|
+
* @param address - Address of the contract.
|
|
32
|
+
* @param timestamp - Timestamp to get the contract instance at. Contract updates might change the instance.
|
|
33
|
+
* @returns The contract instance or undefined if not found.
|
|
34
|
+
*/
|
|
35
|
+
getContractInstance(address: AztecAddress, timestamp: UInt64): Promise<ContractInstanceWithAddress | undefined>;
|
|
36
|
+
/**
|
|
37
|
+
* Returns a publicly deployed contract class.
|
|
38
|
+
* @param contractClassId - ID of the contract class.
|
|
39
|
+
* @returns The contract class or undefined if not found
|
|
40
|
+
*/
|
|
41
|
+
getContractClass(contractClassId: Fr): Promise<ContractClassPublic | undefined>;
|
|
42
|
+
/**
|
|
43
|
+
* Returns the commitment to the bytecode of a contract class.
|
|
44
|
+
* @param contractClassId - ID of the contract class.
|
|
45
|
+
* @returns The commitment to the bytecode or undefined if not found.
|
|
46
|
+
*/
|
|
47
|
+
getBytecodeCommitment(contractClassId: Fr): Promise<Fr | undefined>;
|
|
48
|
+
/**
|
|
49
|
+
* Returns the function name of a contract's function given its selector.
|
|
50
|
+
* @param contractAddress - Address of the contract.
|
|
51
|
+
* @param selector - Selector of the function.
|
|
52
|
+
* @returns The name of the function or undefined if not found.
|
|
53
|
+
*/
|
|
54
|
+
getDebugFunctionName(contractAddress: AztecAddress, selector: FunctionSelector): Promise<string | undefined>;
|
|
55
|
+
/**
|
|
56
|
+
* Creates a checkpoint of the current contract state.
|
|
57
|
+
*/
|
|
58
|
+
createCheckpoint(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Commits the current checkpoint, merging its state with the parent.
|
|
61
|
+
*/
|
|
62
|
+
commitCheckpoint(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Reverts the current checkpoint, discarding its state.
|
|
65
|
+
*/
|
|
66
|
+
revertCheckpoint(): void;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGJfaW50ZXJmYWNlcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3B1YmxpYy9kYl9pbnRlcmZhY2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQzlELE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDL0QsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDckUsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNwRyxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUV2RDs7R0FFRztBQUNILE1BQU0sV0FBVyxzQkFBc0I7SUFDckM7Ozs7O09BS0c7SUFDSCxXQUFXLENBQUMsUUFBUSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUUzRDs7Ozs7T0FLRztJQUNILFlBQVksQ0FBQyxRQUFRLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLEVBQUUsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7Q0FDN0U7QUFFRDs7R0FFRztBQUNILE1BQU0sV0FBVywwQkFBMEI7SUFDekM7Ozs7O09BS0c7SUFDSCxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLDJCQUEyQixHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBRWhIOzs7O09BSUc7SUFDSCxnQkFBZ0IsQ0FBQyxlQUFlLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsR0FBRyxTQUFTLENBQUMsQ0FBQztJQUVoRjs7OztPQUlHO0lBQ0gscUJBQXFCLENBQUMsZUFBZSxFQUFFLEVBQUUsR0FBRyxPQUFPLENBQUMsRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBRXBFOzs7OztPQUtHO0lBQ0gsb0JBQW9CLENBQUMsZUFBZSxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsZ0JBQWdCLEdBQUcsT0FBTyxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUMsQ0FBQztJQUU3Rzs7T0FFRztJQUNILGdCQUFnQixJQUFJLElBQUksQ0FBQztJQUV6Qjs7T0FFRztJQUNILGdCQUFnQixJQUFJLElBQUksQ0FBQztJQUV6Qjs7T0FFRztJQUNILGdCQUFnQixJQUFJLElBQUksQ0FBQztDQUMxQiJ9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db_interfaces.d.ts","sourceRoot":"","sources":["../../src/public/db_interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,qCAAqC,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AACpG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,WAAW,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;IAE3D;;;;;OAKG;IACH,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7E;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAAC;IAEhH;;;;OAIG;IACH,gBAAgB,CAAC,eAAe,EAAE,EAAE,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAAC;IAEhF;;;;OAIG;IACH,qBAAqB,CAAC,eAAe,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC;IAEpE;;;;;OAKG;IACH,oBAAoB,CAAC,eAAe,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE7G;;OAEG;IACH,gBAAgB,IAAI,IAAI,CAAC;IAEzB;;OAEG;IACH,gBAAgB,IAAI,IAAI,CAAC;IAEzB;;OAEG;IACH,gBAAgB,IAAI,IAAI,CAAC;CAC1B"}
|