@aztec/prover-client 0.65.2 → 0.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/block_builder/index.d.ts +6 -0
- package/dest/block_builder/index.d.ts.map +1 -0
- package/dest/block_builder/index.js +2 -0
- package/dest/block_builder/light.d.ts +32 -0
- package/dest/block_builder/light.d.ts.map +1 -0
- package/dest/block_builder/light.js +71 -0
- package/dest/index.d.ts +1 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +2 -3
- package/dest/mocks/fixtures.d.ts +1 -2
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +3 -7
- package/dest/mocks/test_context.d.ts +28 -10
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +58 -21
- package/dest/orchestrator/epoch-proving-state.d.ts +5 -6
- package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/epoch-proving-state.js +10 -12
- package/dest/orchestrator/orchestrator.d.ts +8 -6
- package/dest/orchestrator/orchestrator.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator.js +83 -72
- package/dest/orchestrator/tx-proving-state.d.ts +0 -1
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/tx-proving-state.js +2 -34
- package/dest/prover-client/factory.d.ts +6 -0
- package/dest/prover-client/factory.d.ts.map +1 -0
- package/dest/prover-client/factory.js +6 -0
- package/dest/prover-client/index.d.ts +3 -0
- package/dest/prover-client/index.d.ts.map +1 -0
- package/dest/prover-client/index.js +3 -0
- package/dest/{tx-prover/tx-prover.d.ts → prover-client/prover-client.d.ts} +8 -11
- package/dest/prover-client/prover-client.d.ts.map +1 -0
- package/dest/prover-client/prover-client.js +107 -0
- package/dest/proving_broker/factory.d.ts +2 -1
- package/dest/proving_broker/factory.d.ts.map +1 -1
- package/dest/proving_broker/factory.js +4 -4
- package/dest/proving_broker/proving_agent.d.ts +5 -0
- package/dest/proving_broker/proving_agent.d.ts.map +1 -1
- package/dest/proving_broker/proving_agent.js +13 -2
- package/dest/proving_broker/proving_agent_instrumentation.d.ts +8 -0
- package/dest/proving_broker/proving_agent_instrumentation.d.ts.map +1 -0
- package/dest/proving_broker/proving_agent_instrumentation.js +16 -0
- package/dest/proving_broker/proving_broker.d.ts +6 -1
- package/dest/proving_broker/proving_broker.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker.js +37 -4
- package/dest/proving_broker/proving_broker_database/persisted.d.ts +3 -1
- package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_database/persisted.js +10 -2
- package/dest/proving_broker/proving_broker_instrumentation.d.ts +25 -0
- package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -0
- package/dest/proving_broker/proving_broker_instrumentation.js +91 -0
- package/dest/test/mock_prover.d.ts +1 -1
- package/dest/test/mock_prover.d.ts.map +1 -1
- package/dest/test/mock_prover.js +4 -3
- package/package.json +14 -13
- package/src/block_builder/index.ts +6 -0
- package/src/block_builder/light.ts +117 -0
- package/src/index.ts +1 -2
- package/src/mocks/fixtures.ts +2 -14
- package/src/mocks/test_context.ts +80 -24
- package/src/orchestrator/epoch-proving-state.ts +10 -13
- package/src/orchestrator/orchestrator.ts +97 -77
- package/src/orchestrator/tx-proving-state.ts +1 -56
- package/src/{tx-prover → prover-client}/factory.ts +4 -3
- package/src/prover-client/index.ts +2 -0
- package/src/{tx-prover/tx-prover.ts → prover-client/prover-client.ts} +23 -13
- package/src/proving_broker/factory.ts +7 -3
- package/src/proving_broker/proving_agent.ts +16 -1
- package/src/proving_broker/proving_agent_instrumentation.ts +21 -0
- package/src/proving_broker/proving_broker.ts +46 -3
- package/src/proving_broker/proving_broker_database/persisted.ts +17 -2
- package/src/proving_broker/proving_broker_instrumentation.ts +130 -0
- package/src/test/mock_prover.ts +3 -2
- package/dest/tx-prover/factory.d.ts +0 -6
- package/dest/tx-prover/factory.d.ts.map +0 -1
- package/dest/tx-prover/factory.js +0 -6
- package/dest/tx-prover/tx-prover.d.ts.map +0 -1
- package/dest/tx-prover/tx-prover.js +0 -110
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
EncryptedNoteTxL2Logs,
|
|
3
|
-
EncryptedTxL2Logs,
|
|
4
|
-
type MerkleTreeId,
|
|
5
|
-
type ProcessedTx,
|
|
6
|
-
type ProofAndVerificationKey,
|
|
7
|
-
UnencryptedTxL2Logs,
|
|
8
|
-
} from '@aztec/circuit-types';
|
|
1
|
+
import { type MerkleTreeId, type ProcessedTx, type ProofAndVerificationKey } from '@aztec/circuit-types';
|
|
9
2
|
import {
|
|
10
3
|
type AVM_PROOF_LENGTH_IN_FIELDS,
|
|
11
4
|
AVM_VK_INDEX,
|
|
12
5
|
type AppendOnlyTreeSnapshot,
|
|
13
6
|
AvmProofData,
|
|
14
7
|
type BaseRollupHints,
|
|
15
|
-
Fr,
|
|
16
8
|
PrivateBaseRollupHints,
|
|
17
9
|
PrivateBaseRollupInputs,
|
|
18
10
|
PrivateTubeData,
|
|
@@ -112,53 +104,6 @@ export class TxProvingState {
|
|
|
112
104
|
this.avm = avmProofAndVk;
|
|
113
105
|
}
|
|
114
106
|
|
|
115
|
-
public verifyStateOrReject(): string | undefined {
|
|
116
|
-
const txEffect = this.processedTx.txEffect;
|
|
117
|
-
const fromPrivate = this.processedTx.data;
|
|
118
|
-
|
|
119
|
-
const noteEncryptedLogsHashes = [
|
|
120
|
-
fromPrivate.forRollup?.end.noteEncryptedLogsHashes || [],
|
|
121
|
-
fromPrivate.forPublic?.nonRevertibleAccumulatedData.noteEncryptedLogsHashes || [],
|
|
122
|
-
fromPrivate.forPublic?.revertibleAccumulatedData.noteEncryptedLogsHashes || [],
|
|
123
|
-
].flat();
|
|
124
|
-
const txNoteEncryptedLogsHash = EncryptedNoteTxL2Logs.hashNoteLogs(
|
|
125
|
-
noteEncryptedLogsHashes.filter(log => !log.isEmpty()).map(log => log.value.toBuffer()),
|
|
126
|
-
);
|
|
127
|
-
if (!txNoteEncryptedLogsHash.equals(txEffect.noteEncryptedLogs.hash())) {
|
|
128
|
-
return `Note encrypted logs hash mismatch: ${Fr.fromBuffer(txNoteEncryptedLogsHash)} === ${Fr.fromBuffer(
|
|
129
|
-
txEffect.noteEncryptedLogs.hash(),
|
|
130
|
-
)}`;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const encryptedLogsHashes = [
|
|
134
|
-
fromPrivate.forRollup?.end.encryptedLogsHashes || [],
|
|
135
|
-
fromPrivate.forPublic?.nonRevertibleAccumulatedData.encryptedLogsHashes || [],
|
|
136
|
-
fromPrivate.forPublic?.revertibleAccumulatedData.encryptedLogsHashes || [],
|
|
137
|
-
].flat();
|
|
138
|
-
const txEncryptedLogsHash = EncryptedTxL2Logs.hashSiloedLogs(
|
|
139
|
-
encryptedLogsHashes.filter(log => !log.isEmpty()).map(log => log.getSiloedHash()),
|
|
140
|
-
);
|
|
141
|
-
if (!txEncryptedLogsHash.equals(txEffect.encryptedLogs.hash())) {
|
|
142
|
-
// @todo This rejection messages is never seen. Never making it out to the logs
|
|
143
|
-
return `Encrypted logs hash mismatch: ${Fr.fromBuffer(txEncryptedLogsHash)} === ${Fr.fromBuffer(
|
|
144
|
-
txEffect.encryptedLogs.hash(),
|
|
145
|
-
)}`;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const avmOutput = this.processedTx.avmProvingRequest?.inputs.output;
|
|
149
|
-
const unencryptedLogsHashes = avmOutput
|
|
150
|
-
? avmOutput.accumulatedData.unencryptedLogsHashes
|
|
151
|
-
: fromPrivate.forRollup!.end.unencryptedLogsHashes;
|
|
152
|
-
const txUnencryptedLogsHash = UnencryptedTxL2Logs.hashSiloedLogs(
|
|
153
|
-
unencryptedLogsHashes.filter(log => !log.isEmpty()).map(log => log.getSiloedHash()),
|
|
154
|
-
);
|
|
155
|
-
if (!txUnencryptedLogsHash.equals(txEffect.unencryptedLogs.hash())) {
|
|
156
|
-
return `Unencrypted logs hash mismatch: ${Fr.fromBuffer(txUnencryptedLogsHash)} === ${Fr.fromBuffer(
|
|
157
|
-
txEffect.unencryptedLogs.hash(),
|
|
158
|
-
)}`;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
107
|
private getTubeVkData() {
|
|
163
108
|
let vkIndex = TUBE_VK_INDEX;
|
|
164
109
|
try {
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { type ProvingJobBroker } from '@aztec/circuit-types';
|
|
1
|
+
import { type ForkMerkleTreeOperations, type ProvingJobBroker } from '@aztec/circuit-types';
|
|
2
2
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
3
3
|
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
|
|
4
4
|
|
|
5
5
|
import { type ProverClientConfig } from '../config.js';
|
|
6
|
-
import {
|
|
6
|
+
import { ProverClient } from './prover-client.js';
|
|
7
7
|
|
|
8
8
|
export function createProverClient(
|
|
9
9
|
config: ProverClientConfig,
|
|
10
|
+
worldState: ForkMerkleTreeOperations,
|
|
10
11
|
broker: ProvingJobBroker,
|
|
11
12
|
telemetry: TelemetryClient = new NoopTelemetryClient(),
|
|
12
13
|
) {
|
|
13
|
-
return
|
|
14
|
+
return ProverClient.new(config, worldState, broker, telemetry);
|
|
14
15
|
}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
type ActualProverConfig,
|
|
4
4
|
type EpochProver,
|
|
5
5
|
type EpochProverManager,
|
|
6
|
-
type
|
|
6
|
+
type ForkMerkleTreeOperations,
|
|
7
7
|
type ProverCache,
|
|
8
8
|
type ProvingJobBroker,
|
|
9
9
|
type ProvingJobConsumer,
|
|
@@ -25,11 +25,8 @@ import { InlineProofStore } from '../proving_broker/proof_store.js';
|
|
|
25
25
|
import { InMemoryProverCache } from '../proving_broker/prover_cache/memory.js';
|
|
26
26
|
import { ProvingAgent } from '../proving_broker/proving_agent.js';
|
|
27
27
|
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
* TODO(palla/prover-node): Rename this class
|
|
31
|
-
*/
|
|
32
|
-
export class TxProver implements EpochProverManager {
|
|
28
|
+
/** Manages proving of epochs by orchestrating the proving of individual blocks relying on a pool of prover agents. */
|
|
29
|
+
export class ProverClient implements EpochProverManager {
|
|
33
30
|
private running = false;
|
|
34
31
|
private agents: ProvingAgent[] = [];
|
|
35
32
|
|
|
@@ -37,6 +34,7 @@ export class TxProver implements EpochProverManager {
|
|
|
37
34
|
|
|
38
35
|
private constructor(
|
|
39
36
|
private config: ProverClientConfig,
|
|
37
|
+
private worldState: ForkMerkleTreeOperations,
|
|
40
38
|
private telemetry: TelemetryClient,
|
|
41
39
|
private orchestratorClient: ProvingJobProducer,
|
|
42
40
|
private agentClient?: ProvingJobConsumer,
|
|
@@ -47,9 +45,9 @@ export class TxProver implements EpochProverManager {
|
|
|
47
45
|
this.cacheDir = this.config.cacheDir ? join(this.config.cacheDir, `tx_prover_${this.config.proverId}`) : undefined;
|
|
48
46
|
}
|
|
49
47
|
|
|
50
|
-
public createEpochProver(
|
|
48
|
+
public createEpochProver(cache: ProverCache = new InMemoryProverCache()): EpochProver {
|
|
51
49
|
return new ProvingOrchestrator(
|
|
52
|
-
|
|
50
|
+
this.worldState,
|
|
53
51
|
new CachingBrokerFacade(this.orchestratorClient, cache),
|
|
54
52
|
this.telemetry,
|
|
55
53
|
this.config.proverId,
|
|
@@ -104,12 +102,16 @@ export class TxProver implements EpochProverManager {
|
|
|
104
102
|
/**
|
|
105
103
|
* Creates a new prover client and starts it
|
|
106
104
|
* @param config - The prover configuration.
|
|
107
|
-
* @param
|
|
108
|
-
* @param worldStateSynchronizer - An instance of the world state
|
|
105
|
+
* @param worldState - An instance of the world state
|
|
109
106
|
* @returns An instance of the prover, constructed and started.
|
|
110
107
|
*/
|
|
111
|
-
public static async new(
|
|
112
|
-
|
|
108
|
+
public static async new(
|
|
109
|
+
config: ProverClientConfig,
|
|
110
|
+
worldState: ForkMerkleTreeOperations,
|
|
111
|
+
broker: ProvingJobBroker,
|
|
112
|
+
telemetry: TelemetryClient,
|
|
113
|
+
) {
|
|
114
|
+
const prover = new ProverClient(config, worldState, telemetry, broker, broker);
|
|
113
115
|
await prover.start();
|
|
114
116
|
return prover;
|
|
115
117
|
}
|
|
@@ -135,7 +137,15 @@ export class TxProver implements EpochProverManager {
|
|
|
135
137
|
const prover = await buildServerCircuitProver(this.config, this.telemetry);
|
|
136
138
|
this.agents = times(
|
|
137
139
|
this.config.proverAgentCount,
|
|
138
|
-
() =>
|
|
140
|
+
() =>
|
|
141
|
+
new ProvingAgent(
|
|
142
|
+
this.agentClient!,
|
|
143
|
+
proofStore,
|
|
144
|
+
prover,
|
|
145
|
+
this.telemetry,
|
|
146
|
+
[],
|
|
147
|
+
this.config.proverAgentPollIntervalMs,
|
|
148
|
+
),
|
|
139
149
|
);
|
|
140
150
|
|
|
141
151
|
await Promise.all(this.agents.map(agent => agent.start()));
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { type ProverBrokerConfig } from '@aztec/circuit-types';
|
|
2
2
|
import { AztecLmdbStore } from '@aztec/kv-store/lmdb';
|
|
3
|
+
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
3
4
|
|
|
4
5
|
import { ProvingBroker } from './proving_broker.js';
|
|
5
6
|
import { InMemoryBrokerDatabase } from './proving_broker_database/memory.js';
|
|
6
7
|
import { KVBrokerDatabase } from './proving_broker_database/persisted.js';
|
|
7
8
|
|
|
8
|
-
export async function createAndStartProvingBroker(
|
|
9
|
+
export async function createAndStartProvingBroker(
|
|
10
|
+
config: ProverBrokerConfig,
|
|
11
|
+
client: TelemetryClient,
|
|
12
|
+
): Promise<ProvingBroker> {
|
|
9
13
|
const database = config.proverBrokerDataDirectory
|
|
10
|
-
? new KVBrokerDatabase(AztecLmdbStore.open(config.proverBrokerDataDirectory))
|
|
14
|
+
? new KVBrokerDatabase(AztecLmdbStore.open(config.proverBrokerDataDirectory), client)
|
|
11
15
|
: new InMemoryBrokerDatabase();
|
|
12
16
|
|
|
13
|
-
const broker = new ProvingBroker(database, {
|
|
17
|
+
const broker = new ProvingBroker(database, client, {
|
|
14
18
|
jobTimeoutMs: config.proverBrokerJobTimeoutMs,
|
|
15
19
|
maxRetries: config.proverBrokerJobMaxRetries,
|
|
16
20
|
timeoutIntervalMs: config.proverBrokerPollIntervalMs,
|
|
@@ -10,8 +10,11 @@ import {
|
|
|
10
10
|
} from '@aztec/circuit-types';
|
|
11
11
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
12
12
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
13
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
14
|
+
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
13
15
|
|
|
14
16
|
import { type ProofStore } from './proof_store.js';
|
|
17
|
+
import { ProvingAgentInstrumentation } from './proving_agent_instrumentation.js';
|
|
15
18
|
import { ProvingJobController, ProvingJobControllerStatus } from './proving_job_controller.js';
|
|
16
19
|
|
|
17
20
|
/**
|
|
@@ -20,6 +23,8 @@ import { ProvingJobController, ProvingJobControllerStatus } from './proving_job_
|
|
|
20
23
|
export class ProvingAgent {
|
|
21
24
|
private currentJobController?: ProvingJobController;
|
|
22
25
|
private runningPromise: RunningPromise;
|
|
26
|
+
private instrumentation: ProvingAgentInstrumentation;
|
|
27
|
+
private idleTimer: Timer | undefined;
|
|
23
28
|
|
|
24
29
|
constructor(
|
|
25
30
|
/** The source of proving jobs */
|
|
@@ -28,12 +33,15 @@ export class ProvingAgent {
|
|
|
28
33
|
private proofStore: ProofStore,
|
|
29
34
|
/** The prover implementation to defer jobs to */
|
|
30
35
|
private circuitProver: ServerCircuitProver,
|
|
36
|
+
/** A telemetry client through which to emit metrics */
|
|
37
|
+
client: TelemetryClient,
|
|
31
38
|
/** Optional list of allowed proof types to build */
|
|
32
39
|
private proofAllowList: Array<ProvingRequestType> = [],
|
|
33
40
|
/** How long to wait between jobs */
|
|
34
41
|
private pollIntervalMs = 1000,
|
|
35
42
|
private log = createDebugLogger('aztec:prover-client:proving-agent'),
|
|
36
43
|
) {
|
|
44
|
+
this.instrumentation = new ProvingAgentInstrumentation(client);
|
|
37
45
|
this.runningPromise = new RunningPromise(this.safeWork, this.pollIntervalMs);
|
|
38
46
|
}
|
|
39
47
|
|
|
@@ -46,6 +54,7 @@ export class ProvingAgent {
|
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
public start(): void {
|
|
57
|
+
this.idleTimer = new Timer();
|
|
49
58
|
this.runningPromise.start();
|
|
50
59
|
}
|
|
51
60
|
|
|
@@ -114,6 +123,11 @@ export class ProvingAgent {
|
|
|
114
123
|
);
|
|
115
124
|
}
|
|
116
125
|
|
|
126
|
+
if (this.idleTimer) {
|
|
127
|
+
this.instrumentation.recordIdleTime(this.idleTimer);
|
|
128
|
+
}
|
|
129
|
+
this.idleTimer = undefined;
|
|
130
|
+
|
|
117
131
|
this.currentJobController.start();
|
|
118
132
|
} catch (err) {
|
|
119
133
|
this.log.error(`Error in ProvingAgent: ${String(err)}`);
|
|
@@ -126,9 +140,10 @@ export class ProvingAgent {
|
|
|
126
140
|
err: Error | undefined,
|
|
127
141
|
result: ProvingJobResultsMap[T] | undefined,
|
|
128
142
|
) => {
|
|
143
|
+
this.idleTimer = new Timer();
|
|
129
144
|
if (err) {
|
|
130
145
|
const retry = err.name === ProvingError.NAME ? (err as ProvingError).retry : false;
|
|
131
|
-
this.log.
|
|
146
|
+
this.log.error(`Job id=${jobId} type=${ProvingRequestType[type]} failed err=${err.message} retry=${retry}`, err);
|
|
132
147
|
return this.broker.reportProvingJobError(jobId, err.message, retry);
|
|
133
148
|
} else if (result) {
|
|
134
149
|
const outputUri = await this.proofStore.saveProofOutput(jobId, type, result);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Timer } from '@aztec/foundation/timer';
|
|
2
|
+
import { type Histogram, Metrics, type TelemetryClient, ValueType } from '@aztec/telemetry-client';
|
|
3
|
+
|
|
4
|
+
export class ProvingAgentInstrumentation {
|
|
5
|
+
private idleTime: Histogram;
|
|
6
|
+
|
|
7
|
+
constructor(client: TelemetryClient, name = 'ProvingAgent') {
|
|
8
|
+
const meter = client.getMeter(name);
|
|
9
|
+
|
|
10
|
+
this.idleTime = meter.createHistogram(Metrics.PROVING_AGENT_IDLE, {
|
|
11
|
+
description: 'Records how long an agent was idle',
|
|
12
|
+
unit: 'ms',
|
|
13
|
+
valueType: ValueType.INT,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
recordIdleTime(msOrTimer: Timer | number) {
|
|
18
|
+
const duration = typeof msOrTimer === 'number' ? msOrTimer : Math.floor(msOrTimer.ms());
|
|
19
|
+
this.idleTime.record(duration);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -12,10 +12,13 @@ import {
|
|
|
12
12
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
13
13
|
import { type PromiseWithResolvers, RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
|
|
14
14
|
import { PriorityMemoryQueue } from '@aztec/foundation/queue';
|
|
15
|
+
import { Timer } from '@aztec/foundation/timer';
|
|
16
|
+
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
15
17
|
|
|
16
18
|
import assert from 'assert';
|
|
17
19
|
|
|
18
20
|
import { type ProvingBrokerDatabase } from './proving_broker_database.js';
|
|
21
|
+
import { type MonitorCallback, ProvingBrokerInstrumentation } from './proving_broker_instrumentation.js';
|
|
19
22
|
|
|
20
23
|
type InProgressMetadata = {
|
|
21
24
|
id: ProvingJobId;
|
|
@@ -58,6 +61,9 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
|
|
|
58
61
|
// as above, but for results
|
|
59
62
|
private resultsCache = new Map<ProvingJobId, ProvingJobSettledResult>();
|
|
60
63
|
|
|
64
|
+
// tracks when each job was enqueued
|
|
65
|
+
private enqueuedAt = new Map<ProvingJobId, Timer>();
|
|
66
|
+
|
|
61
67
|
// keeps track of which jobs are currently being processed
|
|
62
68
|
// in the event of a crash this information is lost, but that's ok
|
|
63
69
|
// the next time the broker starts it will recreate jobsCache and still
|
|
@@ -75,18 +81,37 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
|
|
|
75
81
|
private jobTimeoutMs: number;
|
|
76
82
|
private maxRetries: number;
|
|
77
83
|
|
|
84
|
+
private instrumentation: ProvingBrokerInstrumentation;
|
|
85
|
+
|
|
78
86
|
public constructor(
|
|
79
87
|
private database: ProvingBrokerDatabase,
|
|
80
|
-
|
|
88
|
+
client: TelemetryClient,
|
|
89
|
+
{ jobTimeoutMs = 30_000, timeoutIntervalMs = 10_000, maxRetries = 3 }: ProofRequestBrokerConfig = {},
|
|
81
90
|
private logger = createDebugLogger('aztec:prover-client:proving-broker'),
|
|
82
91
|
) {
|
|
92
|
+
this.instrumentation = new ProvingBrokerInstrumentation(client);
|
|
83
93
|
this.timeoutPromise = new RunningPromise(this.timeoutCheck, timeoutIntervalMs);
|
|
84
94
|
this.jobTimeoutMs = jobTimeoutMs;
|
|
85
95
|
this.maxRetries = maxRetries;
|
|
86
96
|
}
|
|
87
97
|
|
|
88
|
-
|
|
89
|
-
|
|
98
|
+
private measureQueueDepth: MonitorCallback = (type: ProvingRequestType) => {
|
|
99
|
+
return this.queues[type].length();
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
private countActiveJobs: MonitorCallback = (type: ProvingRequestType) => {
|
|
103
|
+
let count = 0;
|
|
104
|
+
for (const { id } of this.inProgress.values()) {
|
|
105
|
+
const job = this.jobsCache.get(id);
|
|
106
|
+
if (job?.type === type) {
|
|
107
|
+
count++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return count;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
public start(): Promise<void> {
|
|
90
115
|
for (const [item, result] of this.database.allProvingJobs()) {
|
|
91
116
|
this.logger.info(`Restoring proving job id=${item.id} settled=${!!result}`);
|
|
92
117
|
|
|
@@ -103,6 +128,11 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
|
|
|
103
128
|
}
|
|
104
129
|
|
|
105
130
|
this.timeoutPromise.start();
|
|
131
|
+
|
|
132
|
+
this.instrumentation.monitorQueueDepth(this.measureQueueDepth);
|
|
133
|
+
this.instrumentation.monitorActiveJobs(this.countActiveJobs);
|
|
134
|
+
|
|
135
|
+
return Promise.resolve();
|
|
106
136
|
}
|
|
107
137
|
|
|
108
138
|
public stop(): Promise<void> {
|
|
@@ -187,6 +217,10 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
|
|
|
187
217
|
startedAt: time,
|
|
188
218
|
lastUpdatedAt: time,
|
|
189
219
|
});
|
|
220
|
+
const enqueuedAt = this.enqueuedAt.get(job.id);
|
|
221
|
+
if (enqueuedAt) {
|
|
222
|
+
this.instrumentation.recordJobWait(job.type, enqueuedAt);
|
|
223
|
+
}
|
|
190
224
|
|
|
191
225
|
return { job, time };
|
|
192
226
|
}
|
|
@@ -216,6 +250,7 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
|
|
|
216
250
|
this.logger.info(`Retrying proving job id=${id} type=${ProvingRequestType[item.type]} retry=${retries + 1}`);
|
|
217
251
|
this.retries.set(id, retries + 1);
|
|
218
252
|
this.enqueueJobInternal(item);
|
|
253
|
+
this.instrumentation.incRetriedJobs(item.type);
|
|
219
254
|
return;
|
|
220
255
|
}
|
|
221
256
|
|
|
@@ -228,6 +263,11 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
|
|
|
228
263
|
const result: ProvingJobSettledResult = { status: 'rejected', reason: String(err) };
|
|
229
264
|
this.resultsCache.set(id, result);
|
|
230
265
|
this.promises.get(id)!.resolve(result);
|
|
266
|
+
this.instrumentation.incRejectedJobs(item.type);
|
|
267
|
+
if (info) {
|
|
268
|
+
const duration = this.timeSource() - info.startedAt;
|
|
269
|
+
this.instrumentation.recordJobDuration(item.type, duration * 1000);
|
|
270
|
+
}
|
|
231
271
|
}
|
|
232
272
|
|
|
233
273
|
reportProvingJobProgress(
|
|
@@ -303,6 +343,7 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
|
|
|
303
343
|
const result: ProvingJobSettledResult = { status: 'fulfilled', value };
|
|
304
344
|
this.resultsCache.set(id, result);
|
|
305
345
|
this.promises.get(id)!.resolve(result);
|
|
346
|
+
this.instrumentation.incResolvedJobs(item.type);
|
|
306
347
|
}
|
|
307
348
|
|
|
308
349
|
private timeoutCheck = () => {
|
|
@@ -320,6 +361,7 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
|
|
|
320
361
|
this.logger.warn(`Proving job id=${id} timed out. Adding it back to the queue.`);
|
|
321
362
|
this.inProgress.delete(id);
|
|
322
363
|
this.enqueueJobInternal(item);
|
|
364
|
+
this.instrumentation.incTimedOutJobs(item.type);
|
|
323
365
|
}
|
|
324
366
|
}
|
|
325
367
|
};
|
|
@@ -329,6 +371,7 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer {
|
|
|
329
371
|
this.promises.set(job.id, promiseWithResolvers());
|
|
330
372
|
}
|
|
331
373
|
this.queues[job.type].put(job);
|
|
374
|
+
this.enqueuedAt.set(job.id, new Timer());
|
|
332
375
|
this.logger.debug(`Enqueued new proving job id=${job.id}`);
|
|
333
376
|
}
|
|
334
377
|
}
|
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
import { type ProofUri, ProvingJob, type ProvingJobId, ProvingJobSettledResult } from '@aztec/circuit-types';
|
|
2
2
|
import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc';
|
|
3
3
|
import { type AztecKVStore, type AztecMap } from '@aztec/kv-store';
|
|
4
|
+
import { LmdbMetrics, Metrics, type TelemetryClient } from '@aztec/telemetry-client';
|
|
4
5
|
|
|
5
6
|
import { type ProvingBrokerDatabase } from '../proving_broker_database.js';
|
|
6
7
|
|
|
7
8
|
export class KVBrokerDatabase implements ProvingBrokerDatabase {
|
|
8
9
|
private jobs: AztecMap<ProvingJobId, string>;
|
|
9
10
|
private jobResults: AztecMap<ProvingJobId, string>;
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
private metrics: LmdbMetrics;
|
|
12
|
+
|
|
13
|
+
constructor(private store: AztecKVStore, client: TelemetryClient) {
|
|
14
|
+
this.metrics = new LmdbMetrics(
|
|
15
|
+
client.getMeter('KVBrokerDatabase'),
|
|
16
|
+
{
|
|
17
|
+
name: Metrics.PROVING_QUEUE_DB_MAP_SIZE,
|
|
18
|
+
description: 'Database map size for the proving broker',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: Metrics.PROVING_QUEUE_DB_USED_SIZE,
|
|
22
|
+
description: 'Database used size for the proving broker',
|
|
23
|
+
},
|
|
24
|
+
{ name: Metrics.PROVING_QUEUE_DB_NUM_ITEMS, description: 'Number of items in the broker database' },
|
|
25
|
+
() => store.estimateSize(),
|
|
26
|
+
);
|
|
12
27
|
this.jobs = store.openMap('proving_jobs');
|
|
13
28
|
this.jobResults = store.openMap('proving_job_results');
|
|
14
29
|
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { ProvingRequestType } from '@aztec/circuit-types';
|
|
2
|
+
import { type Timer } from '@aztec/foundation/timer';
|
|
3
|
+
import {
|
|
4
|
+
Attributes,
|
|
5
|
+
type Histogram,
|
|
6
|
+
Metrics,
|
|
7
|
+
type ObservableGauge,
|
|
8
|
+
type ObservableResult,
|
|
9
|
+
type TelemetryClient,
|
|
10
|
+
type UpDownCounter,
|
|
11
|
+
ValueType,
|
|
12
|
+
millisecondBuckets,
|
|
13
|
+
} from '@aztec/telemetry-client';
|
|
14
|
+
|
|
15
|
+
export type MonitorCallback = (proofType: ProvingRequestType) => number;
|
|
16
|
+
|
|
17
|
+
export class ProvingBrokerInstrumentation {
|
|
18
|
+
private queueSize: ObservableGauge;
|
|
19
|
+
private activeJobs: ObservableGauge;
|
|
20
|
+
private resolvedJobs: UpDownCounter;
|
|
21
|
+
private rejectedJobs: UpDownCounter;
|
|
22
|
+
private timedOutJobs: UpDownCounter;
|
|
23
|
+
private jobWait: Histogram;
|
|
24
|
+
private jobDuration: Histogram;
|
|
25
|
+
private retriedJobs: UpDownCounter;
|
|
26
|
+
|
|
27
|
+
constructor(client: TelemetryClient, name = 'ProvingBroker') {
|
|
28
|
+
const meter = client.getMeter(name);
|
|
29
|
+
|
|
30
|
+
this.queueSize = meter.createObservableGauge(Metrics.PROVING_QUEUE_SIZE, {
|
|
31
|
+
valueType: ValueType.INT,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
this.activeJobs = meter.createObservableGauge(Metrics.PROVING_QUEUE_ACTIVE_JOBS, {
|
|
35
|
+
valueType: ValueType.INT,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
this.resolvedJobs = meter.createUpDownCounter(Metrics.PROVING_QUEUE_RESOLVED_JOBS, {
|
|
39
|
+
valueType: ValueType.INT,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
this.rejectedJobs = meter.createUpDownCounter(Metrics.PROVING_QUEUE_REJECTED_JOBS, {
|
|
43
|
+
valueType: ValueType.INT,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this.retriedJobs = meter.createUpDownCounter(Metrics.PROVING_QUEUE_RETRIED_JOBS, {
|
|
47
|
+
valueType: ValueType.INT,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
this.timedOutJobs = meter.createUpDownCounter(Metrics.PROVING_QUEUE_TIMED_OUT_JOBS, {
|
|
51
|
+
valueType: ValueType.INT,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
this.jobWait = meter.createHistogram(Metrics.PROVING_QUEUE_JOB_WAIT, {
|
|
55
|
+
description: 'Records how long a job sits in the queue',
|
|
56
|
+
unit: 'ms',
|
|
57
|
+
valueType: ValueType.INT,
|
|
58
|
+
advice: {
|
|
59
|
+
explicitBucketBoundaries: millisecondBuckets(1), // 10ms -> ~327s
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
this.jobDuration = meter.createHistogram(Metrics.PROVING_QUEUE_JOB_DURATION, {
|
|
64
|
+
description: 'Records how long a job takes to complete',
|
|
65
|
+
unit: 'ms',
|
|
66
|
+
valueType: ValueType.INT,
|
|
67
|
+
advice: {
|
|
68
|
+
explicitBucketBoundaries: millisecondBuckets(1), // 10ms -> ~327s
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
monitorQueueDepth(fn: MonitorCallback) {
|
|
74
|
+
this.queueSize.addCallback(obs => this.observe(obs, fn));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
monitorActiveJobs(fn: MonitorCallback) {
|
|
78
|
+
this.activeJobs.addCallback(obs => this.observe(obs, fn));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
incResolvedJobs(proofType: ProvingRequestType) {
|
|
82
|
+
this.resolvedJobs.add(1, {
|
|
83
|
+
[Attributes.PROVING_JOB_TYPE]: ProvingRequestType[proofType],
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
incRejectedJobs(proofType: ProvingRequestType) {
|
|
88
|
+
this.rejectedJobs.add(1, {
|
|
89
|
+
[Attributes.PROVING_JOB_TYPE]: ProvingRequestType[proofType],
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
incRetriedJobs(proofType: ProvingRequestType) {
|
|
94
|
+
this.retriedJobs.add(1, {
|
|
95
|
+
[Attributes.PROVING_JOB_TYPE]: ProvingRequestType[proofType],
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
incTimedOutJobs(proofType: ProvingRequestType) {
|
|
100
|
+
this.timedOutJobs.add(1, {
|
|
101
|
+
[Attributes.PROVING_JOB_TYPE]: ProvingRequestType[proofType],
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
recordJobWait(proofType: ProvingRequestType, msOrTimer: Timer | number) {
|
|
106
|
+
const duration = typeof msOrTimer === 'number' ? msOrTimer : Math.floor(msOrTimer.ms());
|
|
107
|
+
this.jobWait.record(duration, {
|
|
108
|
+
[Attributes.PROVING_JOB_TYPE]: ProvingRequestType[proofType],
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
recordJobDuration(proofType: ProvingRequestType, msOrTimer: Timer | number) {
|
|
113
|
+
const duration = typeof msOrTimer === 'number' ? msOrTimer : Math.floor(msOrTimer.ms());
|
|
114
|
+
this.jobDuration.record(duration, {
|
|
115
|
+
[Attributes.PROVING_JOB_TYPE]: ProvingRequestType[proofType],
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private observe(obs: ObservableResult, fn: MonitorCallback) {
|
|
120
|
+
for (const proofType of Object.values(ProvingRequestType)) {
|
|
121
|
+
// a type predicate for TypeScript to recognize that we're only iterating over enum values
|
|
122
|
+
if (typeof proofType !== 'number') {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
obs.observe(fn(proofType), {
|
|
126
|
+
[Attributes.PROVING_JOB_TYPE]: ProvingRequestType[proofType],
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
package/src/test/mock_prover.ts
CHANGED
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
makeRootRollupPublicInputs,
|
|
44
44
|
} from '@aztec/circuits.js/testing';
|
|
45
45
|
import { times } from '@aztec/foundation/collection';
|
|
46
|
+
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
|
|
46
47
|
|
|
47
48
|
import { InlineProofStore, type ProofStore } from '../proving_broker/proof_store.js';
|
|
48
49
|
import { ProvingAgent } from '../proving_broker/proving_agent.js';
|
|
@@ -50,7 +51,7 @@ import { ProvingBroker } from '../proving_broker/proving_broker.js';
|
|
|
50
51
|
import { InMemoryBrokerDatabase } from '../proving_broker/proving_broker_database/memory.js';
|
|
51
52
|
|
|
52
53
|
export class TestBroker implements ProvingJobProducer {
|
|
53
|
-
private broker = new ProvingBroker(new InMemoryBrokerDatabase());
|
|
54
|
+
private broker = new ProvingBroker(new InMemoryBrokerDatabase(), new NoopTelemetryClient());
|
|
54
55
|
private agents: ProvingAgent[];
|
|
55
56
|
|
|
56
57
|
constructor(
|
|
@@ -58,7 +59,7 @@ export class TestBroker implements ProvingJobProducer {
|
|
|
58
59
|
prover: ServerCircuitProver,
|
|
59
60
|
private proofStore: ProofStore = new InlineProofStore(),
|
|
60
61
|
) {
|
|
61
|
-
this.agents = times(agentCount, () => new ProvingAgent(this.broker, proofStore, prover));
|
|
62
|
+
this.agents = times(agentCount, () => new ProvingAgent(this.broker, proofStore, prover, new NoopTelemetryClient()));
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
public async start() {
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { type ProvingJobBroker } from '@aztec/circuit-types';
|
|
2
|
-
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
3
|
-
import { type ProverClientConfig } from '../config.js';
|
|
4
|
-
import { TxProver } from './tx-prover.js';
|
|
5
|
-
export declare function createProverClient(config: ProverClientConfig, broker: ProvingJobBroker, telemetry?: TelemetryClient): Promise<TxProver>;
|
|
6
|
-
//# sourceMappingURL=factory.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/tx-prover/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG/D,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,gBAAgB,EACxB,SAAS,GAAE,eAA2C,qBAGvD"}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { NoopTelemetryClient } from '@aztec/telemetry-client/noop';
|
|
2
|
-
import { TxProver } from './tx-prover.js';
|
|
3
|
-
export function createProverClient(config, broker, telemetry = new NoopTelemetryClient()) {
|
|
4
|
-
return TxProver.new(config, broker, telemetry);
|
|
5
|
-
}
|
|
6
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eC1wcm92ZXIvZmFjdG9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUduRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFMUMsTUFBTSxVQUFVLGtCQUFrQixDQUNoQyxNQUEwQixFQUMxQixNQUF3QixFQUN4QixZQUE2QixJQUFJLG1CQUFtQixFQUFFO0lBRXRELE9BQU8sUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBQ2pELENBQUMifQ==
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tx-prover.d.ts","sourceRoot":"","sources":["../../src/tx-prover/tx-prover.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,QAAQ,EAA2C,MAAM,kBAAkB,CAAC;AAC3G,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EAEvB,KAAK,mBAAmB,EACzB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAIxC,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI/D,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAOvD;;;GAGG;AACH,qBAAa,QAAS,YAAW,kBAAkB;IAO/C,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,WAAW,CAAC;IACpB,OAAO,CAAC,GAAG;IAVb,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAsB;IAEpC,OAAO,CAAC,QAAQ,CAAC,CAAS;IAE1B,OAAO;IAYA,iBAAiB,CAAC,EAAE,EAAE,yBAAyB,EAAE,KAAK,GAAE,WAAuC,GAAG,WAAW;IAS7G,WAAW,IAAI,EAAE;IAIlB,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB5E;;OAEG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IASnC;;OAEG;IACU,IAAI;IAQjB;;;;;;OAMG;WACiB,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,eAAe;IAMjG,mBAAmB,IAAI,kBAAkB;YAQlC,oBAAoB;YAmBpB,UAAU;CAGzB;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,kBAAkB,GAAG,UAAU,GAAG,QAAQ,EAClD,SAAS,EAAE,eAAe,GACzB,OAAO,CAAC,mBAAmB,CAAC,CAU9B"}
|