@aztec/prover-client 0.0.0-test.1 → 0.0.1-commit.017a351

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/dest/config.d.ts +8 -8
  2. package/dest/config.d.ts.map +1 -1
  3. package/dest/config.js +26 -2
  4. package/dest/index.d.ts +1 -1
  5. package/dest/light/index.d.ts +2 -0
  6. package/dest/light/index.d.ts.map +1 -0
  7. package/dest/light/index.js +1 -0
  8. package/dest/light/lightweight_checkpoint_builder.d.ts +52 -0
  9. package/dest/light/lightweight_checkpoint_builder.d.ts.map +1 -0
  10. package/dest/light/lightweight_checkpoint_builder.js +231 -0
  11. package/dest/mocks/fixtures.d.ts +8 -8
  12. package/dest/mocks/fixtures.d.ts.map +1 -1
  13. package/dest/mocks/fixtures.js +36 -17
  14. package/dest/mocks/test_context.d.ts +45 -32
  15. package/dest/mocks/test_context.d.ts.map +1 -1
  16. package/dest/mocks/test_context.js +162 -90
  17. package/dest/orchestrator/block-building-helpers.d.ts +36 -29
  18. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
  19. package/dest/orchestrator/block-building-helpers.js +170 -189
  20. package/dest/orchestrator/block-proving-state.d.ts +73 -48
  21. package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
  22. package/dest/orchestrator/block-proving-state.js +289 -177
  23. package/dest/orchestrator/checkpoint-proving-state.d.ts +83 -0
  24. package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -0
  25. package/dest/orchestrator/checkpoint-proving-state.js +252 -0
  26. package/dest/orchestrator/checkpoint-sub-tree-orchestrator.d.ts +107 -0
  27. package/dest/orchestrator/checkpoint-sub-tree-orchestrator.d.ts.map +1 -0
  28. package/dest/orchestrator/checkpoint-sub-tree-orchestrator.js +151 -0
  29. package/dest/orchestrator/epoch-proving-context.d.ts +51 -0
  30. package/dest/orchestrator/epoch-proving-context.d.ts.map +1 -0
  31. package/dest/orchestrator/epoch-proving-context.js +81 -0
  32. package/dest/orchestrator/epoch-proving-state.d.ts +43 -28
  33. package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
  34. package/dest/orchestrator/epoch-proving-state.js +179 -73
  35. package/dest/orchestrator/index.d.ts +4 -1
  36. package/dest/orchestrator/index.d.ts.map +1 -1
  37. package/dest/orchestrator/index.js +3 -0
  38. package/dest/orchestrator/orchestrator.d.ts +59 -51
  39. package/dest/orchestrator/orchestrator.d.ts.map +1 -1
  40. package/dest/orchestrator/orchestrator.js +808 -385
  41. package/dest/orchestrator/orchestrator_metrics.d.ts +1 -1
  42. package/dest/orchestrator/orchestrator_metrics.d.ts.map +1 -1
  43. package/dest/orchestrator/orchestrator_metrics.js +2 -6
  44. package/dest/orchestrator/proving-scheduler.d.ts +72 -0
  45. package/dest/orchestrator/proving-scheduler.d.ts.map +1 -0
  46. package/dest/orchestrator/proving-scheduler.js +117 -0
  47. package/dest/orchestrator/top-tree-orchestrator.d.ts +83 -0
  48. package/dest/orchestrator/top-tree-orchestrator.d.ts.map +1 -0
  49. package/dest/orchestrator/top-tree-orchestrator.js +182 -0
  50. package/dest/orchestrator/top-tree-proving-scheduler.d.ts +62 -0
  51. package/dest/orchestrator/top-tree-proving-scheduler.d.ts.map +1 -0
  52. package/dest/orchestrator/top-tree-proving-scheduler.js +73 -0
  53. package/dest/orchestrator/top-tree-proving-state.d.ts +61 -0
  54. package/dest/orchestrator/top-tree-proving-state.d.ts.map +1 -0
  55. package/dest/orchestrator/top-tree-proving-state.js +185 -0
  56. package/dest/orchestrator/tx-proving-state.d.ts +15 -12
  57. package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
  58. package/dest/orchestrator/tx-proving-state.js +27 -44
  59. package/dest/prover-client/factory.d.ts +3 -3
  60. package/dest/prover-client/factory.d.ts.map +1 -1
  61. package/dest/prover-client/index.d.ts +1 -1
  62. package/dest/prover-client/prover-client.d.ts +68 -9
  63. package/dest/prover-client/prover-client.d.ts.map +1 -1
  64. package/dest/prover-client/prover-client.js +68 -14
  65. package/dest/prover-client/server-epoch-prover.d.ts +16 -12
  66. package/dest/prover-client/server-epoch-prover.d.ts.map +1 -1
  67. package/dest/prover-client/server-epoch-prover.js +11 -11
  68. package/dest/proving_broker/broker_prover_facade.d.ts +28 -19
  69. package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
  70. package/dest/proving_broker/broker_prover_facade.js +74 -61
  71. package/dest/proving_broker/config.d.ts +18 -61
  72. package/dest/proving_broker/config.d.ts.map +1 -1
  73. package/dest/proving_broker/config.js +43 -9
  74. package/dest/proving_broker/factory.d.ts +2 -2
  75. package/dest/proving_broker/factory.d.ts.map +1 -1
  76. package/dest/proving_broker/factory.js +5 -1
  77. package/dest/proving_broker/fixtures.d.ts +3 -2
  78. package/dest/proving_broker/fixtures.d.ts.map +1 -1
  79. package/dest/proving_broker/fixtures.js +3 -2
  80. package/dest/proving_broker/index.d.ts +2 -1
  81. package/dest/proving_broker/index.d.ts.map +1 -1
  82. package/dest/proving_broker/index.js +1 -0
  83. package/dest/proving_broker/proof_store/factory.d.ts +2 -5
  84. package/dest/proving_broker/proof_store/factory.d.ts.map +1 -1
  85. package/dest/proving_broker/proof_store/factory.js +7 -30
  86. package/dest/proving_broker/proof_store/file_store_proof_store.d.ts +18 -0
  87. package/dest/proving_broker/proof_store/file_store_proof_store.d.ts.map +1 -0
  88. package/dest/proving_broker/proof_store/file_store_proof_store.js +60 -0
  89. package/dest/proving_broker/proof_store/index.d.ts +2 -1
  90. package/dest/proving_broker/proof_store/index.d.ts.map +1 -1
  91. package/dest/proving_broker/proof_store/index.js +1 -0
  92. package/dest/proving_broker/proof_store/inline_proof_store.d.ts +1 -1
  93. package/dest/proving_broker/proof_store/inline_proof_store.d.ts.map +1 -1
  94. package/dest/proving_broker/proof_store/proof_store.d.ts +1 -1
  95. package/dest/proving_broker/proving_agent.d.ts +8 -12
  96. package/dest/proving_broker/proving_agent.d.ts.map +1 -1
  97. package/dest/proving_broker/proving_agent.js +86 -65
  98. package/dest/proving_broker/proving_broker.d.ts +18 -6
  99. package/dest/proving_broker/proving_broker.d.ts.map +1 -1
  100. package/dest/proving_broker/proving_broker.js +108 -44
  101. package/dest/proving_broker/proving_broker_database/memory.d.ts +3 -2
  102. package/dest/proving_broker/proving_broker_database/memory.d.ts.map +1 -1
  103. package/dest/proving_broker/proving_broker_database/memory.js +1 -1
  104. package/dest/proving_broker/proving_broker_database/persisted.d.ts +5 -3
  105. package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
  106. package/dest/proving_broker/proving_broker_database/persisted.js +401 -11
  107. package/dest/proving_broker/proving_broker_database.d.ts +3 -2
  108. package/dest/proving_broker/proving_broker_database.d.ts.map +1 -1
  109. package/dest/proving_broker/proving_broker_instrumentation.d.ts +3 -1
  110. package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -1
  111. package/dest/proving_broker/proving_broker_instrumentation.js +22 -35
  112. package/dest/proving_broker/proving_job_controller.d.ts +11 -10
  113. package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
  114. package/dest/proving_broker/proving_job_controller.js +92 -62
  115. package/dest/proving_broker/rpc.d.ts +9 -7
  116. package/dest/proving_broker/rpc.d.ts.map +1 -1
  117. package/dest/proving_broker/rpc.js +88 -27
  118. package/dest/test/mock_proof_store.d.ts +9 -0
  119. package/dest/test/mock_proof_store.d.ts.map +1 -0
  120. package/dest/test/mock_proof_store.js +10 -0
  121. package/dest/test/mock_prover.d.ts +23 -17
  122. package/dest/test/mock_prover.d.ts.map +1 -1
  123. package/dest/test/mock_prover.js +38 -20
  124. package/package.json +34 -33
  125. package/src/config.ts +41 -9
  126. package/src/light/index.ts +1 -0
  127. package/src/light/lightweight_checkpoint_builder.ts +320 -0
  128. package/src/mocks/fixtures.ts +46 -40
  129. package/src/mocks/test_context.ts +231 -120
  130. package/src/orchestrator/block-building-helpers.ts +258 -334
  131. package/src/orchestrator/block-proving-state.ts +334 -231
  132. package/src/orchestrator/checkpoint-proving-state.ts +362 -0
  133. package/src/orchestrator/checkpoint-sub-tree-orchestrator.ts +271 -0
  134. package/src/orchestrator/epoch-proving-context.ts +101 -0
  135. package/src/orchestrator/epoch-proving-state.ts +239 -111
  136. package/src/orchestrator/index.ts +8 -0
  137. package/src/orchestrator/orchestrator.ts +591 -451
  138. package/src/orchestrator/orchestrator_metrics.ts +2 -6
  139. package/src/orchestrator/proving-scheduler.ts +156 -0
  140. package/src/orchestrator/top-tree-orchestrator.ts +314 -0
  141. package/src/orchestrator/top-tree-proving-scheduler.ts +154 -0
  142. package/src/orchestrator/top-tree-proving-state.ts +220 -0
  143. package/src/orchestrator/tx-proving-state.ts +48 -66
  144. package/src/prover-client/factory.ts +6 -2
  145. package/src/prover-client/prover-client.ts +173 -38
  146. package/src/prover-client/server-epoch-prover.ts +40 -22
  147. package/src/proving_broker/broker_prover_facade.ts +227 -149
  148. package/src/proving_broker/config.ts +49 -8
  149. package/src/proving_broker/factory.ts +2 -1
  150. package/src/proving_broker/fixtures.ts +8 -3
  151. package/src/proving_broker/index.ts +1 -0
  152. package/src/proving_broker/proof_store/factory.ts +10 -32
  153. package/src/proving_broker/proof_store/file_store_proof_store.ts +78 -0
  154. package/src/proving_broker/proof_store/index.ts +1 -0
  155. package/src/proving_broker/proof_store/inline_proof_store.ts +1 -1
  156. package/src/proving_broker/proving_agent.ts +95 -66
  157. package/src/proving_broker/proving_broker.ts +121 -49
  158. package/src/proving_broker/proving_broker_database/memory.ts +3 -2
  159. package/src/proving_broker/proving_broker_database/persisted.ts +31 -15
  160. package/src/proving_broker/proving_broker_database.ts +2 -1
  161. package/src/proving_broker/proving_broker_instrumentation.ts +23 -35
  162. package/src/proving_broker/proving_job_controller.ts +100 -83
  163. package/src/proving_broker/rpc.ts +46 -25
  164. package/src/test/mock_proof_store.ts +14 -0
  165. package/src/test/mock_prover.ts +156 -64
  166. package/dest/bin/get-proof-inputs.d.ts +0 -2
  167. package/dest/bin/get-proof-inputs.d.ts.map +0 -1
  168. package/dest/bin/get-proof-inputs.js +0 -51
  169. package/dest/block_builder/index.d.ts +0 -6
  170. package/dest/block_builder/index.d.ts.map +0 -1
  171. package/dest/block_builder/index.js +0 -1
  172. package/dest/block_builder/light.d.ts +0 -33
  173. package/dest/block_builder/light.d.ts.map +0 -1
  174. package/dest/block_builder/light.js +0 -82
  175. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts +0 -14
  176. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts.map +0 -1
  177. package/dest/proving_broker/proof_store/gcs_proof_store.js +0 -51
  178. package/dest/proving_broker/proving_agent_instrumentation.d.ts +0 -8
  179. package/dest/proving_broker/proving_agent_instrumentation.d.ts.map +0 -1
  180. package/dest/proving_broker/proving_agent_instrumentation.js +0 -16
  181. package/src/bin/get-proof-inputs.ts +0 -59
  182. package/src/block_builder/index.ts +0 -6
  183. package/src/block_builder/light.ts +0 -101
  184. package/src/proving_broker/proof_store/gcs_proof_store.ts +0 -72
  185. package/src/proving_broker/proving_agent_instrumentation.ts +0 -21
@@ -6,9 +6,10 @@ import { InMemoryBrokerDatabase } from './proving_broker_database/memory.js';
6
6
  import { KVBrokerDatabase } from './proving_broker_database/persisted.js';
7
7
 
8
8
  export async function createAndStartProvingBroker(
9
- config: ProverBrokerConfig,
9
+ _config: ProverBrokerConfig,
10
10
  client: TelemetryClient,
11
11
  ): Promise<ProvingBroker> {
12
+ const config = { ..._config, dataStoreMapSizeKb: _config.proverBrokerStoreMapSizeKb ?? _config.dataStoreMapSizeKb };
12
13
  const database = config.dataDirectory ? await KVBrokerDatabase.new(config, client) : new InMemoryBrokerDatabase();
13
14
 
14
15
  const broker = new ProvingBroker(database, config, client);
@@ -1,9 +1,14 @@
1
- import { randomBytes } from '@aztec/foundation/crypto';
1
+ import { EpochNumber } from '@aztec/foundation/branded-types';
2
+ import { randomBytes } from '@aztec/foundation/crypto/random';
2
3
  import { type ProofUri, type ProvingJobId, makeProvingJobId } from '@aztec/stdlib/interfaces/server';
3
4
  import { ProvingRequestType } from '@aztec/stdlib/proofs';
4
5
 
5
- export function makeRandomProvingJobId(epochNumber?: number): ProvingJobId {
6
- return makeProvingJobId(epochNumber ?? 1, ProvingRequestType.BASE_PARITY, randomBytes(8).toString('hex'));
6
+ export function makeRandomProvingJobId(epochNumber?: EpochNumber): ProvingJobId {
7
+ return makeProvingJobId(
8
+ epochNumber ?? EpochNumber(1),
9
+ ProvingRequestType.PARITY_BASE,
10
+ randomBytes(8).toString('hex'),
11
+ );
7
12
  }
8
13
 
9
14
  export function makeInputsUri(): ProofUri {
@@ -7,3 +7,4 @@ export * from './proving_broker_database/persisted.js';
7
7
  export * from './proof_store/index.js';
8
8
  export * from './factory.js';
9
9
  export * from './config.js';
10
+ export { BrokerCircuitProverFacade } from './broker_prover_facade.js';
@@ -1,42 +1,20 @@
1
1
  import { createLogger } from '@aztec/foundation/log';
2
+ import { createFileStore } from '@aztec/stdlib/file-store';
2
3
 
3
- import { GoogleCloudStorageProofStore } from './gcs_proof_store.js';
4
+ import { FileStoreProofStore } from './file_store_proof_store.js';
4
5
  import { InlineProofStore } from './inline_proof_store.js';
5
6
  import type { ProofStore } from './proof_store.js';
6
7
 
7
- export function createProofStore(config: string | undefined, logger = createLogger('prover-client:proof-store')) {
8
- if (config === undefined) {
8
+ export async function createProofStore(
9
+ config: string | undefined,
10
+ logger = createLogger('prover-client:proof-store'),
11
+ ): Promise<ProofStore> {
12
+ if (!config) {
9
13
  logger.info('Creating inline proof store');
10
14
  return new InlineProofStore();
11
- } else if (config.startsWith('gs://')) {
12
- try {
13
- const url = new URL(config);
14
- const bucket = url.host;
15
- const path = url.pathname.replace(/^\/+/, '');
16
- logger.info(`Creating google cloud proof store at ${bucket}`, { bucket, path });
17
- return new GoogleCloudStorageProofStore(bucket, path);
18
- } catch (err) {
19
- throw new Error(
20
- `Invalid google cloud proof store definition: '${config}'. Supported values are 'gs://bucket-name/path/to/store'.`,
21
- );
22
- }
23
- } else {
24
- throw new Error(`Unknown proof store config: '${config}'. Supported values are 'gs://bucket-name/path/to/store'.`);
25
15
  }
26
- }
27
16
 
28
- export function createProofStoreForUri(
29
- uri: string,
30
- logger = createLogger('prover-client:proof-store'),
31
- ): Pick<ProofStore, 'getProofInput' | 'getProofOutput'> {
32
- if (uri.startsWith('data://')) {
33
- return createProofStore(undefined, logger);
34
- } else if (uri.startsWith('gs://')) {
35
- const url = new URL(uri);
36
- const basePath = url.pathname.replace(/^\/+/, '').split('/').slice(0, -3);
37
- url.pathname = basePath.join('/');
38
- return createProofStore(uri, logger);
39
- } else {
40
- throw new Error(`Unknown proof store config: '${uri}'. Supported protocols are 'data://' and 'gs://'.`);
41
- }
17
+ const fileStore = await createFileStore(config, logger);
18
+ logger.info(`Creating file store proof store at ${config}`);
19
+ return new FileStoreProofStore(fileStore);
42
20
  }
@@ -0,0 +1,78 @@
1
+ import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc';
2
+ import type { FileStore } from '@aztec/stdlib/file-store';
3
+ import {
4
+ type ProofUri,
5
+ type ProvingJobId,
6
+ type ProvingJobInputs,
7
+ type ProvingJobInputsMap,
8
+ ProvingJobResult,
9
+ type ProvingJobResultsMap,
10
+ getProvingJobInputClassFor,
11
+ } from '@aztec/stdlib/interfaces/server';
12
+ import { ProvingRequestType } from '@aztec/stdlib/proofs';
13
+
14
+ import type { ProofStore } from './proof_store.js';
15
+
16
+ const INPUTS_PATH = 'inputs';
17
+ const OUTPUTS_PATH = 'outputs';
18
+
19
+ /**
20
+ * A proof store implementation backed by a generic FileStore.
21
+ * Supports any storage backend (GCS, S3, local filesystem) via the FileStore abstraction.
22
+ */
23
+ export class FileStoreProofStore implements ProofStore {
24
+ constructor(private readonly fileStore: FileStore) {}
25
+
26
+ async saveProofInput<T extends ProvingRequestType>(
27
+ id: ProvingJobId,
28
+ type: T,
29
+ inputs: ProvingJobInputsMap[T],
30
+ ): Promise<ProofUri> {
31
+ const path = `${INPUTS_PATH}/${ProvingRequestType[type]}/${id}`;
32
+ const uri = await this.fileStore.save(path, inputs.toBuffer());
33
+ return uri as ProofUri;
34
+ }
35
+
36
+ async saveProofOutput<T extends ProvingRequestType>(
37
+ id: ProvingJobId,
38
+ type: T,
39
+ result: ProvingJobResultsMap[T],
40
+ ): Promise<ProofUri> {
41
+ const jobResult = { type, result } as ProvingJobResult;
42
+ const json = jsonStringify(jobResult);
43
+ const path = `${OUTPUTS_PATH}/${ProvingRequestType[type]}/${id}.json`;
44
+ const uri = await this.fileStore.save(path, Buffer.from(json, 'utf-8'));
45
+ return uri as ProofUri;
46
+ }
47
+
48
+ async getProofInput(uri: ProofUri): Promise<ProvingJobInputs> {
49
+ try {
50
+ const buffer = await this.fileStore.read(uri);
51
+ const type = this.extractTypeFromUri(uri);
52
+ const inputs = getProvingJobInputClassFor(type).fromBuffer(buffer);
53
+ return { inputs, type } as ProvingJobInputs;
54
+ } catch (err) {
55
+ throw new Error(`Error getting proof input at ${uri}: ${err}`);
56
+ }
57
+ }
58
+
59
+ async getProofOutput(uri: ProofUri): Promise<ProvingJobResult> {
60
+ try {
61
+ const buffer = await this.fileStore.read(uri);
62
+ return jsonParseWithSchema(buffer.toString('utf-8'), ProvingJobResult);
63
+ } catch (err) {
64
+ throw new Error(`Error getting proof output at ${uri}: ${err}`);
65
+ }
66
+ }
67
+
68
+ private extractTypeFromUri(uri: string): ProvingRequestType {
69
+ const url = new URL(uri);
70
+ const pathParts = url.pathname.split('/').filter(Boolean);
71
+ const typeString = pathParts.at(-2);
72
+ const type = typeString ? ProvingRequestType[typeString as keyof typeof ProvingRequestType] : undefined;
73
+ if (type === undefined) {
74
+ throw new Error(`Unrecognized proof type ${typeString} in URI ${uri}`);
75
+ }
76
+ return type;
77
+ }
78
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './proof_store.js';
2
2
  export * from './inline_proof_store.js';
3
3
  export * from './factory.js';
4
+ export * from './file_store_proof_store.js';
@@ -52,7 +52,7 @@ export class InlineProofStore implements ProofStore {
52
52
  return (PREFIX + SEPARATOR + encoded) as ProofUri;
53
53
  }
54
54
 
55
- private decode<T>(uri: ProofUri, schema: ZodFor<T>): Promise<T> {
55
+ private decode<T>(uri: ProofUri, schema: ZodFor<T>): T {
56
56
  const [prefix, data] = uri.split(SEPARATOR);
57
57
  if (prefix !== PREFIX) {
58
58
  throw new Error('Invalid proof input URI: ' + prefix);
@@ -1,10 +1,11 @@
1
- import { createLogger } from '@aztec/foundation/log';
1
+ import { AbortError } from '@aztec/foundation/error';
2
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
2
3
  import { RunningPromise } from '@aztec/foundation/running-promise';
3
4
  import { truncate } from '@aztec/foundation/string';
4
- import { Timer } from '@aztec/foundation/timer';
5
5
  import { ProvingError } from '@aztec/stdlib/errors';
6
6
  import type {
7
- ProvingJob,
7
+ GetProvingJobResponse,
8
+ ProverAgentStatus,
8
9
  ProvingJobConsumer,
9
10
  ProvingJobId,
10
11
  ProvingJobInputs,
@@ -12,28 +13,17 @@ import type {
12
13
  ServerCircuitProver,
13
14
  } from '@aztec/stdlib/interfaces/server';
14
15
  import { ProvingRequestType } from '@aztec/stdlib/proofs';
15
- import {
16
- type TelemetryClient,
17
- type Traceable,
18
- type Tracer,
19
- getTelemetryClient,
20
- trackSpan,
21
- } from '@aztec/telemetry-client';
22
16
 
23
17
  import type { ProofStore } from './proof_store/index.js';
24
- import { ProvingAgentInstrumentation } from './proving_agent_instrumentation.js';
25
18
  import { ProvingJobController, ProvingJobControllerStatus } from './proving_job_controller.js';
26
19
 
27
20
  /**
28
21
  * A helper class that encapsulates a circuit prover and connects it to a job source.
29
22
  */
30
- export class ProvingAgent implements Traceable {
23
+ export class ProvingAgent {
31
24
  private currentJobController?: ProvingJobController;
32
25
  private runningPromise: RunningPromise;
33
- private instrumentation: ProvingAgentInstrumentation;
34
- private idleTimer: Timer | undefined;
35
-
36
- public readonly tracer: Tracer;
26
+ private log: Logger;
37
27
 
38
28
  constructor(
39
29
  /** The source of proving jobs */
@@ -46,12 +36,9 @@ export class ProvingAgent implements Traceable {
46
36
  private proofAllowList: Array<ProvingRequestType> = [],
47
37
  /** How long to wait between jobs */
48
38
  private pollIntervalMs = 1000,
49
- /** A telemetry client through which to emit metrics */
50
- client: TelemetryClient = getTelemetryClient(),
51
- private log = createLogger('prover-client:proving-agent'),
39
+ bindings?: LoggerBindings,
52
40
  ) {
53
- this.tracer = client.getTracer('ProvingAgent');
54
- this.instrumentation = new ProvingAgentInstrumentation(client);
41
+ this.log = createLogger('prover-client:proving-agent', bindings);
55
42
  this.runningPromise = new RunningPromise(this.work.bind(this), this.log, this.pollIntervalMs);
56
43
  }
57
44
 
@@ -64,7 +51,6 @@ export class ProvingAgent implements Traceable {
64
51
  }
65
52
 
66
53
  public start(): void {
67
- this.idleTimer = new Timer();
68
54
  this.runningPromise.start();
69
55
  }
70
56
 
@@ -73,41 +59,77 @@ export class ProvingAgent implements Traceable {
73
59
  await this.runningPromise.stop();
74
60
  }
75
61
 
76
- @trackSpan('ProvingAgent.safeWork')
62
+ public getStatus(): ProverAgentStatus {
63
+ if (this.currentJobController) {
64
+ return {
65
+ status: 'proving',
66
+ jobId: this.currentJobController.getJobId(),
67
+ proofType: this.currentJobController.getProofType(),
68
+ startedAtISO: new Date(this.currentJobController.getStartedAt()).toISOString(),
69
+ };
70
+ }
71
+
72
+ return this.runningPromise.isRunning() ? { status: 'running' } : { status: 'stopped' };
73
+ }
74
+
77
75
  private async work() {
78
- // every tick we need to
79
- // (1) either do a heartbeat, telling the broker that we're working
80
- // (2) get a new job
81
- // If during (1) the broker returns a new job that means we can cancel the current job and start the new one
82
- let maybeJob: { job: ProvingJob; time: number } | undefined;
83
- if (this.currentJobController?.getStatus() === ProvingJobControllerStatus.PROVING) {
84
- maybeJob = await this.broker.reportProvingJobProgress(
85
- this.currentJobController.getJobId(),
86
- this.currentJobController.getStartedAt(),
87
- { allowList: this.proofAllowList },
88
- );
76
+ // every tick we need to take one of the following actions:
77
+ // 1. send a hearbeat to the broker that we're working on some job
78
+ // 2. if the job is complete, send its result to the broker
79
+ // 3. get a job from the broker
80
+ // Any one of these actions could give us a new job to work on. If that happens we abort the current job.
81
+ //
82
+ // This loop gets triggered in one of two ways:
83
+ // - either on a timer (see pollIntervalMs)
84
+ // - or when a proof completes
85
+ let maybeJob: GetProvingJobResponse | undefined;
86
+
87
+ if (this.currentJobController) {
88
+ const status = this.currentJobController.getStatus();
89
+ const jobId = this.currentJobController.getJobId();
90
+ const proofType = this.currentJobController.getProofType();
91
+ const startedAt = this.currentJobController.getStartedAt();
92
+ const result = this.currentJobController.getResult();
93
+
94
+ if (status === ProvingJobControllerStatus.RUNNING) {
95
+ maybeJob = await this.broker.reportProvingJobProgress(jobId, startedAt, { allowList: this.proofAllowList });
96
+ } else if (status === ProvingJobControllerStatus.DONE) {
97
+ if (result) {
98
+ maybeJob = await this.reportResult(jobId, proofType, result);
99
+ } else {
100
+ this.log.warn(
101
+ `Job controller for job ${this.currentJobController.getJobId()} is done but doesn't have a result`,
102
+ { jobId },
103
+ );
104
+ maybeJob = await this.reportResult(
105
+ jobId,
106
+ proofType,
107
+ new ProvingError('No result found after proving', undefined, /* retry */ true),
108
+ );
109
+ }
110
+
111
+ this.currentJobController = undefined;
112
+ } else {
113
+ // IDLE status should not be seen because a job is started as soon as it is created
114
+ this.log.warn(`Idle job controller for job: ${this.currentJobController.getJobId()}. Skipping main loop work`, {
115
+ jobId: this.currentJobController.getJobId(),
116
+ });
117
+ return;
118
+ }
89
119
  } else {
90
120
  maybeJob = await this.broker.getProvingJob({ allowList: this.proofAllowList });
91
121
  }
92
122
 
93
- if (!maybeJob) {
94
- return;
95
- }
96
-
97
- if (this.idleTimer) {
98
- this.instrumentation.recordIdleTime(this.idleTimer);
123
+ if (maybeJob) {
124
+ await this.startJob(maybeJob);
99
125
  }
100
- this.idleTimer = undefined;
101
-
102
- const { job, time } = maybeJob;
103
- await this.startJob(job, time);
104
126
  }
105
127
 
106
- private async startJob(job: ProvingJob, startedAt: number): Promise<void> {
128
+ private async startJob({ job, time: startedAt }: GetProvingJobResponse): Promise<void> {
107
129
  let abortedProofJobId: string | undefined;
108
130
  let abortedProofName: string | undefined;
109
131
 
110
- if (this.currentJobController?.getStatus() === ProvingJobControllerStatus.PROVING) {
132
+ if (this.currentJobController?.getStatus() === ProvingJobControllerStatus.RUNNING) {
111
133
  abortedProofJobId = this.currentJobController.getJobId();
112
134
  abortedProofName = this.currentJobController.getProofTypeName();
113
135
  this.currentJobController?.abort();
@@ -116,13 +138,13 @@ export class ProvingAgent implements Traceable {
116
138
  let inputs: ProvingJobInputs;
117
139
  try {
118
140
  inputs = await this.proofStore.getProofInput(job.inputsUri);
119
- } catch (err) {
141
+ } catch {
120
142
  const maybeJob = await this.broker.reportProvingJobError(job.id, 'Failed to load proof inputs', true, {
121
143
  allowList: this.proofAllowList,
122
144
  });
123
145
 
124
146
  if (maybeJob) {
125
- return this.startJob(maybeJob.job, maybeJob.time);
147
+ return this.startJob(maybeJob);
126
148
  }
127
149
 
128
150
  return;
@@ -134,7 +156,12 @@ export class ProvingAgent implements Traceable {
134
156
  job.epochNumber,
135
157
  startedAt,
136
158
  this.circuitProver,
137
- this.handleJobResult,
159
+ () => {
160
+ // trigger a run of the main work loop when proving completes
161
+ // no need to await this here. The controller will stay alive (in DONE state) until the result is send to the broker
162
+ void this.runningPromise.trigger();
163
+ },
164
+ this.log.getBindings(),
138
165
  );
139
166
 
140
167
  if (abortedProofJobId) {
@@ -154,28 +181,30 @@ export class ProvingAgent implements Traceable {
154
181
  this.currentJobController.start();
155
182
  }
156
183
 
157
- handleJobResult = async <T extends ProvingRequestType>(
184
+ private async reportResult<T extends ProvingRequestType>(
158
185
  jobId: ProvingJobId,
159
186
  type: T,
160
- err: Error | undefined,
161
- result: ProvingJobResultsMap[T] | undefined,
162
- ) => {
163
- let maybeJob: { job: ProvingJob; time: number } | undefined;
164
- if (err) {
165
- const retry = err.name === ProvingError.NAME ? (err as ProvingError).retry : false;
166
- this.log.error(`Job id=${jobId} type=${ProvingRequestType[type]} failed err=${err.message} retry=${retry}`, err);
167
- maybeJob = await this.broker.reportProvingJobError(jobId, err.message, retry, { allowList: this.proofAllowList });
168
- } else if (result) {
187
+ result: ProvingJobResultsMap[T] | Error,
188
+ ): Promise<GetProvingJobResponse | undefined> {
189
+ let maybeJob: GetProvingJobResponse | undefined;
190
+ if (result instanceof AbortError) {
191
+ // no-op
192
+ this.log.warn(`Job id=${jobId} was aborted. Not reporting result back to broker`, result);
193
+ } else if (result instanceof Error) {
194
+ const retry = result.name === ProvingError.NAME ? (result as ProvingError).retry : false;
195
+ this.log.error(
196
+ `Job id=${jobId} type=${ProvingRequestType[type]} failed err=${result.message} retry=${retry}`,
197
+ result,
198
+ );
199
+ maybeJob = await this.broker.reportProvingJobError(jobId, result.message, retry, {
200
+ allowList: this.proofAllowList,
201
+ });
202
+ } else {
169
203
  const outputUri = await this.proofStore.saveProofOutput(jobId, type, result);
170
204
  this.log.info(`Job id=${jobId} type=${ProvingRequestType[type]} completed outputUri=${truncate(outputUri)}`);
171
205
  maybeJob = await this.broker.reportProvingJobSuccess(jobId, outputUri, { allowList: this.proofAllowList });
172
206
  }
173
207
 
174
- if (maybeJob) {
175
- const { job, time } = maybeJob;
176
- await this.startJob(job, time);
177
- } else {
178
- this.idleTimer = new Timer();
179
- }
180
- };
208
+ return maybeJob;
209
+ }
181
210
  }