@aztec/prover-client 0.0.1-commit.d3ec352c → 0.0.1-commit.d58ff9d0

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 (164) hide show
  1. package/dest/config.d.ts +2 -2
  2. package/dest/config.d.ts.map +1 -1
  3. package/dest/config.js +17 -3
  4. package/dest/light/index.d.ts +2 -0
  5. package/dest/light/index.d.ts.map +1 -0
  6. package/dest/light/index.js +1 -0
  7. package/dest/light/lightweight_checkpoint_builder.d.ts +38 -15
  8. package/dest/light/lightweight_checkpoint_builder.d.ts.map +1 -1
  9. package/dest/light/lightweight_checkpoint_builder.js +162 -36
  10. package/dest/mocks/fixtures.d.ts +1 -1
  11. package/dest/mocks/fixtures.d.ts.map +1 -1
  12. package/dest/mocks/fixtures.js +4 -3
  13. package/dest/mocks/test_context.d.ts +15 -13
  14. package/dest/mocks/test_context.d.ts.map +1 -1
  15. package/dest/mocks/test_context.js +50 -36
  16. package/dest/orchestrator/block-building-helpers.d.ts +6 -6
  17. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
  18. package/dest/orchestrator/block-building-helpers.js +5 -5
  19. package/dest/orchestrator/block-proving-state.d.ts +5 -2
  20. package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
  21. package/dest/orchestrator/block-proving-state.js +8 -1
  22. package/dest/orchestrator/checkpoint-proving-state.d.ts +20 -23
  23. package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -1
  24. package/dest/orchestrator/checkpoint-proving-state.js +23 -87
  25. package/dest/orchestrator/checkpoint-sub-tree-orchestrator.d.ts +161 -0
  26. package/dest/orchestrator/checkpoint-sub-tree-orchestrator.d.ts.map +1 -0
  27. package/dest/orchestrator/checkpoint-sub-tree-orchestrator.js +1066 -0
  28. package/dest/orchestrator/chonk-cache.d.ts +39 -0
  29. package/dest/orchestrator/chonk-cache.d.ts.map +1 -0
  30. package/dest/orchestrator/chonk-cache.js +80 -0
  31. package/dest/orchestrator/index.d.ts +4 -2
  32. package/dest/orchestrator/index.d.ts.map +1 -1
  33. package/dest/orchestrator/index.js +3 -1
  34. package/dest/orchestrator/orchestrator_metrics.d.ts +1 -3
  35. package/dest/orchestrator/orchestrator_metrics.d.ts.map +1 -1
  36. package/dest/orchestrator/orchestrator_metrics.js +2 -15
  37. package/dest/orchestrator/proving-scheduler.d.ts +81 -0
  38. package/dest/orchestrator/proving-scheduler.d.ts.map +1 -0
  39. package/dest/orchestrator/proving-scheduler.js +120 -0
  40. package/dest/orchestrator/top-tree-orchestrator.d.ts +88 -0
  41. package/dest/orchestrator/top-tree-orchestrator.d.ts.map +1 -0
  42. package/dest/orchestrator/top-tree-orchestrator.js +232 -0
  43. package/dest/orchestrator/top-tree-proving-state.d.ts +61 -0
  44. package/dest/orchestrator/top-tree-proving-state.d.ts.map +1 -0
  45. package/dest/orchestrator/top-tree-proving-state.js +185 -0
  46. package/dest/orchestrator/tx-proving-state.d.ts +7 -6
  47. package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
  48. package/dest/orchestrator/tx-proving-state.js +8 -8
  49. package/dest/prover-client/factory.d.ts +3 -3
  50. package/dest/prover-client/factory.d.ts.map +1 -1
  51. package/dest/prover-client/prover-client.d.ts +65 -8
  52. package/dest/prover-client/prover-client.d.ts.map +1 -1
  53. package/dest/prover-client/prover-client.js +66 -14
  54. package/dest/proving_broker/broker_prover_facade.d.ts +8 -6
  55. package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
  56. package/dest/proving_broker/broker_prover_facade.js +18 -31
  57. package/dest/proving_broker/config.d.ts +13 -65
  58. package/dest/proving_broker/config.d.ts.map +1 -1
  59. package/dest/proving_broker/config.js +23 -6
  60. package/dest/proving_broker/fixtures.js +1 -1
  61. package/dest/proving_broker/index.d.ts +2 -1
  62. package/dest/proving_broker/index.d.ts.map +1 -1
  63. package/dest/proving_broker/index.js +1 -0
  64. package/dest/proving_broker/proof_store/factory.d.ts +2 -5
  65. package/dest/proving_broker/proof_store/factory.d.ts.map +1 -1
  66. package/dest/proving_broker/proof_store/factory.js +7 -30
  67. package/dest/proving_broker/proof_store/file_store_proof_store.d.ts +18 -0
  68. package/dest/proving_broker/proof_store/file_store_proof_store.d.ts.map +1 -0
  69. package/dest/proving_broker/proof_store/file_store_proof_store.js +60 -0
  70. package/dest/proving_broker/proof_store/index.d.ts +2 -2
  71. package/dest/proving_broker/proof_store/index.d.ts.map +1 -1
  72. package/dest/proving_broker/proof_store/index.js +1 -1
  73. package/dest/proving_broker/proving_agent.d.ts +5 -9
  74. package/dest/proving_broker/proving_agent.d.ts.map +1 -1
  75. package/dest/proving_broker/proving_agent.js +4 -19
  76. package/dest/proving_broker/proving_broker.d.ts +8 -5
  77. package/dest/proving_broker/proving_broker.d.ts.map +1 -1
  78. package/dest/proving_broker/proving_broker.js +72 -21
  79. package/dest/proving_broker/proving_broker_database/persisted.d.ts +3 -2
  80. package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
  81. package/dest/proving_broker/proving_broker_database/persisted.js +391 -3
  82. package/dest/proving_broker/proving_broker_instrumentation.d.ts +3 -1
  83. package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -1
  84. package/dest/proving_broker/proving_broker_instrumentation.js +22 -35
  85. package/dest/proving_broker/proving_job_controller.d.ts +4 -3
  86. package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
  87. package/dest/proving_broker/proving_job_controller.js +8 -6
  88. package/dest/proving_broker/rpc.d.ts +6 -2
  89. package/dest/proving_broker/rpc.d.ts.map +1 -1
  90. package/dest/proving_broker/rpc.js +87 -23
  91. package/dest/test/epoch_settlement.d.ts +36 -0
  92. package/dest/test/epoch_settlement.d.ts.map +1 -0
  93. package/dest/test/epoch_settlement.js +52 -0
  94. package/dest/test/index.d.ts +2 -0
  95. package/dest/test/index.d.ts.map +1 -0
  96. package/dest/test/index.js +1 -0
  97. package/dest/test/mock_proof_store.d.ts +3 -3
  98. package/dest/test/mock_proof_store.d.ts.map +1 -1
  99. package/dest/test/mock_prover.d.ts +5 -5
  100. package/dest/test/mock_prover.d.ts.map +1 -1
  101. package/dest/test/mock_prover.js +4 -4
  102. package/package.json +23 -22
  103. package/src/config.ts +19 -3
  104. package/src/light/index.ts +1 -0
  105. package/src/light/lightweight_checkpoint_builder.ts +229 -50
  106. package/src/mocks/fixtures.ts +4 -3
  107. package/src/mocks/test_context.ts +44 -48
  108. package/src/orchestrator/block-building-helpers.ts +5 -5
  109. package/src/orchestrator/block-proving-state.ts +10 -1
  110. package/src/orchestrator/checkpoint-proving-state.ts +22 -116
  111. package/src/orchestrator/checkpoint-sub-tree-orchestrator.ts +1044 -0
  112. package/src/orchestrator/chonk-cache.ts +99 -0
  113. package/src/orchestrator/index.ts +8 -1
  114. package/src/orchestrator/orchestrator_metrics.ts +2 -25
  115. package/src/orchestrator/proving-scheduler.ts +160 -0
  116. package/src/orchestrator/top-tree-orchestrator.ts +384 -0
  117. package/src/orchestrator/top-tree-proving-state.ts +219 -0
  118. package/src/orchestrator/tx-proving-state.ts +11 -15
  119. package/src/prover-client/factory.ts +6 -2
  120. package/src/prover-client/prover-client.ts +148 -29
  121. package/src/proving_broker/broker_prover_facade.ts +27 -37
  122. package/src/proving_broker/config.ts +26 -3
  123. package/src/proving_broker/fixtures.ts +1 -1
  124. package/src/proving_broker/index.ts +1 -0
  125. package/src/proving_broker/proof_store/factory.ts +10 -32
  126. package/src/proving_broker/proof_store/file_store_proof_store.ts +78 -0
  127. package/src/proving_broker/proof_store/index.ts +1 -1
  128. package/src/proving_broker/proving_agent.ts +6 -19
  129. package/src/proving_broker/proving_broker.ts +68 -16
  130. package/src/proving_broker/proving_broker_database/persisted.ts +17 -3
  131. package/src/proving_broker/proving_broker_instrumentation.ts +23 -35
  132. package/src/proving_broker/proving_job_controller.ts +11 -6
  133. package/src/proving_broker/rpc.ts +46 -20
  134. package/src/test/epoch_settlement.ts +82 -0
  135. package/src/test/index.ts +1 -0
  136. package/src/test/mock_prover.ts +3 -15
  137. package/dest/block-factory/index.d.ts +0 -2
  138. package/dest/block-factory/index.d.ts.map +0 -1
  139. package/dest/block-factory/index.js +0 -1
  140. package/dest/block-factory/light.d.ts +0 -38
  141. package/dest/block-factory/light.d.ts.map +0 -1
  142. package/dest/block-factory/light.js +0 -108
  143. package/dest/orchestrator/epoch-proving-state.d.ts +0 -74
  144. package/dest/orchestrator/epoch-proving-state.d.ts.map +0 -1
  145. package/dest/orchestrator/epoch-proving-state.js +0 -233
  146. package/dest/orchestrator/orchestrator.d.ts +0 -113
  147. package/dest/orchestrator/orchestrator.d.ts.map +0 -1
  148. package/dest/orchestrator/orchestrator.js +0 -842
  149. package/dest/prover-client/server-epoch-prover.d.ts +0 -32
  150. package/dest/prover-client/server-epoch-prover.d.ts.map +0 -1
  151. package/dest/prover-client/server-epoch-prover.js +0 -40
  152. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts +0 -14
  153. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts.map +0 -1
  154. package/dest/proving_broker/proof_store/gcs_proof_store.js +0 -52
  155. package/dest/proving_broker/proving_agent_instrumentation.d.ts +0 -8
  156. package/dest/proving_broker/proving_agent_instrumentation.d.ts.map +0 -1
  157. package/dest/proving_broker/proving_agent_instrumentation.js +0 -16
  158. package/src/block-factory/index.ts +0 -1
  159. package/src/block-factory/light.ts +0 -137
  160. package/src/orchestrator/epoch-proving-state.ts +0 -330
  161. package/src/orchestrator/orchestrator.ts +0 -1265
  162. package/src/prover-client/server-epoch-prover.ts +0 -69
  163. package/src/proving_broker/proof_store/gcs_proof_store.ts +0 -76
  164. package/src/proving_broker/proving_agent_instrumentation.ts +0 -21
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "@aztec/prover-client",
3
- "version": "0.0.1-commit.d3ec352c",
3
+ "version": "0.0.1-commit.d58ff9d0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
7
- "./block-factory": "./dest/block-factory/index.js",
8
7
  "./broker": "./dest/proving_broker/index.js",
8
+ "./broker/config": "./dest/proving_broker/config.js",
9
9
  "./orchestrator": "./dest/orchestrator/index.js",
10
10
  "./helpers": "./dest/orchestrator/block-building-helpers.js",
11
- "./config": "./dest/config.js"
11
+ "./light": "./dest/light/index.js",
12
+ "./config": "./dest/config.js",
13
+ "./test": "./dest/test/index.js"
12
14
  },
13
15
  "typedocOptions": {
14
16
  "entryPoints": [
@@ -26,8 +28,8 @@
26
28
  "build:dev": "../scripts/tsc.sh --watch",
27
29
  "clean": "rm -rf ./dest .tsbuildinfo",
28
30
  "bb": "node --no-warnings ./dest/bb/index.js",
29
- "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=3500000 --forceExit",
30
- "test:debug": "LOG_LEVEL=debug NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=1500000 --forceExit --testNamePattern prover/bb_prover/parity"
31
+ "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=3500000",
32
+ "test:debug": "LOG_LEVEL=\"debug; info: json-rpc, simulator\" NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=1500000 --testNamePattern prover/bb_prover/parity"
31
33
  },
32
34
  "jest": {
33
35
  "moduleNameMapper": {
@@ -67,34 +69,33 @@
67
69
  ]
68
70
  },
69
71
  "dependencies": {
70
- "@aztec/bb-prover": "0.0.1-commit.d3ec352c",
71
- "@aztec/blob-lib": "0.0.1-commit.d3ec352c",
72
- "@aztec/constants": "0.0.1-commit.d3ec352c",
73
- "@aztec/ethereum": "0.0.1-commit.d3ec352c",
74
- "@aztec/foundation": "0.0.1-commit.d3ec352c",
75
- "@aztec/kv-store": "0.0.1-commit.d3ec352c",
76
- "@aztec/noir-protocol-circuits-types": "0.0.1-commit.d3ec352c",
77
- "@aztec/noir-types": "0.0.1-commit.d3ec352c",
78
- "@aztec/protocol-contracts": "0.0.1-commit.d3ec352c",
79
- "@aztec/simulator": "0.0.1-commit.d3ec352c",
80
- "@aztec/stdlib": "0.0.1-commit.d3ec352c",
81
- "@aztec/telemetry-client": "0.0.1-commit.d3ec352c",
82
- "@aztec/world-state": "0.0.1-commit.d3ec352c",
83
- "@google-cloud/storage": "^7.15.0",
72
+ "@aztec/bb-prover": "0.0.1-commit.d58ff9d0",
73
+ "@aztec/blob-lib": "0.0.1-commit.d58ff9d0",
74
+ "@aztec/constants": "0.0.1-commit.d58ff9d0",
75
+ "@aztec/ethereum": "0.0.1-commit.d58ff9d0",
76
+ "@aztec/foundation": "0.0.1-commit.d58ff9d0",
77
+ "@aztec/kv-store": "0.0.1-commit.d58ff9d0",
78
+ "@aztec/noir-protocol-circuits-types": "0.0.1-commit.d58ff9d0",
79
+ "@aztec/noir-types": "0.0.1-commit.d58ff9d0",
80
+ "@aztec/protocol-contracts": "0.0.1-commit.d58ff9d0",
81
+ "@aztec/simulator": "0.0.1-commit.d58ff9d0",
82
+ "@aztec/stdlib": "0.0.1-commit.d58ff9d0",
83
+ "@aztec/telemetry-client": "0.0.1-commit.d58ff9d0",
84
+ "@aztec/world-state": "0.0.1-commit.d58ff9d0",
84
85
  "@iarna/toml": "^2.2.5",
85
86
  "commander": "^12.1.0",
86
87
  "lodash.chunk": "^4.2.0",
87
88
  "source-map-support": "^0.5.21",
88
89
  "tslib": "^2.4.0",
89
- "zod": "^3.23.8"
90
+ "zod": "^4"
90
91
  },
91
92
  "devDependencies": {
92
- "@aztec/noir-contracts.js": "0.0.1-commit.d3ec352c",
93
+ "@aztec/noir-contracts.js": "0.0.1-commit.d58ff9d0",
93
94
  "@jest/globals": "^30.0.0",
94
95
  "@types/jest": "^30.0.0",
95
96
  "@types/node": "^22.15.17",
96
97
  "@types/source-map-support": "^0.5.10",
97
- "@typescript/native-preview": "7.0.0-dev.20251126.1",
98
+ "@typescript/native-preview": "7.0.0-dev.20260113.1",
98
99
  "get-port": "^7.1.0",
99
100
  "jest": "^30.0.0",
100
101
  "jest-mock-extended": "^4.0.0",
package/src/config.ts CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  getConfigFromMappings,
6
6
  numberConfigHelper,
7
7
  } from '@aztec/foundation/config';
8
- import { type ProverConfig, proverConfigMappings } from '@aztec/stdlib/interfaces/server';
8
+ import { type ProverConfig, proverConfigMappings } from '@aztec/stdlib/interfaces/prover-config';
9
9
 
10
10
  import {
11
11
  type ProverAgentConfig,
@@ -44,14 +44,30 @@ export const bbConfigMappings: ConfigMappingsType<BBConfig & ACVMConfig> = {
44
44
  },
45
45
  numConcurrentIVCVerifiers: {
46
46
  env: 'BB_NUM_IVC_VERIFIERS',
47
- description: 'Max number of chonk verifiers to run concurrently',
47
+ description: 'Max concurrent verifications for the RPC verifier (QueuedIVCVerifier).',
48
48
  ...numberConfigHelper(8),
49
49
  },
50
50
  bbIVCConcurrency: {
51
51
  env: 'BB_IVC_CONCURRENCY',
52
- description: 'Number of threads to use for IVC verification',
52
+ description: 'Thread count for the RPC IVC verifier.',
53
53
  ...numberConfigHelper(1),
54
54
  },
55
+ bbChonkVerifyMaxBatch: {
56
+ env: 'BB_CHONK_VERIFY_MAX_BATCH',
57
+ description:
58
+ 'Upper bound on proofs per batch for the peer chonk batch verifier. Proofs are verified immediately as they arrive; this only caps how many can accumulate while a batch is already being processed.',
59
+ ...numberConfigHelper(16),
60
+ },
61
+ bbChonkVerifyConcurrency: {
62
+ env: 'BB_CHONK_VERIFY_BATCH_CONCURRENCY',
63
+ description: 'Thread count for the peer batch verifier parallel reduce. 0 = auto.',
64
+ ...numberConfigHelper(6),
65
+ },
66
+ bbDebugOutputDir: {
67
+ env: 'BB_DEBUG_OUTPUT_DIR',
68
+ description:
69
+ 'When set, bb.js operations write input/output files and log equivalent CLI commands to this directory',
70
+ },
55
71
  };
56
72
 
57
73
  export const proverClientConfigMappings: ConfigMappingsType<ProverClientUserConfig> = {
@@ -0,0 +1 @@
1
+ export * from './lightweight_checkpoint_builder.js';
@@ -1,16 +1,25 @@
1
1
  import { SpongeBlob, computeBlobsHashFromBlobs, encodeCheckpointEndMarker, getBlobsPerL1Block } from '@aztec/blob-lib';
2
- import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
3
- import type { CheckpointNumber } from '@aztec/foundation/branded-types';
4
- import { padArrayEnd } from '@aztec/foundation/collection';
5
- import { Fr } from '@aztec/foundation/fields';
6
- import { createLogger } from '@aztec/foundation/log';
7
- import { L2BlockNew } from '@aztec/stdlib/block';
2
+ import { type CheckpointNumber, IndexWithinCheckpoint } from '@aztec/foundation/branded-types';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
4
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
5
+ import { elapsed } from '@aztec/foundation/timer';
6
+ import { L2Block } from '@aztec/stdlib/block';
8
7
  import { Checkpoint } from '@aztec/stdlib/checkpoint';
9
8
  import type { MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
10
- import { computeCheckpointOutHash, computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
11
- import { CheckpointConstantData, CheckpointHeader, computeBlockHeadersHash } from '@aztec/stdlib/rollup';
9
+ import {
10
+ accumulateCheckpointOutHashes,
11
+ appendL1ToL2MessagesToTree,
12
+ computeCheckpointOutHash,
13
+ computeInHashFromL1ToL2Messages,
14
+ } from '@aztec/stdlib/messaging';
15
+ import { CheckpointHeader, computeBlockHeadersHash } from '@aztec/stdlib/rollup';
12
16
  import { AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
13
- import { ContentCommitment, type GlobalVariables, type ProcessedTx, StateReference } from '@aztec/stdlib/tx';
17
+ import {
18
+ type CheckpointGlobalVariables,
19
+ type GlobalVariables,
20
+ type ProcessedTx,
21
+ StateReference,
22
+ } from '@aztec/stdlib/tx';
14
23
 
15
24
  import {
16
25
  buildHeaderAndBodyFromTxs,
@@ -21,70 +30,209 @@ import {
21
30
  /**
22
31
  * Builds a checkpoint and its header and the blocks in it from a set of processed tx without running any circuits.
23
32
  *
24
- * It updates the l1-to-l2 message tree when starting a new checkpoint, inserts the side effects to note hash,
25
- * nullifier, and public data trees, then updates the archive tree when a block is added.
33
+ * It updates the l1-to-l2 message tree when starting a new checkpoint, and then updates the archive tree when each block is added.
34
+ * Finally completes the checkpoint by computing its header.
26
35
  */
27
36
  export class LightweightCheckpointBuilder {
28
- private readonly logger = createLogger('lightweight-checkpoint-builder');
37
+ private readonly logger: Logger;
38
+
29
39
  private lastArchives: AppendOnlyTreeSnapshot[] = [];
30
40
  private spongeBlob: SpongeBlob;
31
- private blocks: L2BlockNew[] = [];
41
+ private blocks: L2Block[] = [];
32
42
  private blobFields: Fr[] = [];
33
43
 
34
44
  constructor(
35
- private checkpointNumber: CheckpointNumber,
36
- private constants: CheckpointConstantData,
37
- private l1ToL2Messages: Fr[],
38
- private db: MerkleTreeWriteOperations,
45
+ public readonly checkpointNumber: CheckpointNumber,
46
+ public readonly constants: CheckpointGlobalVariables,
47
+ public feeAssetPriceModifier: bigint,
48
+ public readonly l1ToL2Messages: Fr[],
49
+ private readonly previousCheckpointOutHashes: Fr[],
50
+ public readonly db: MerkleTreeWriteOperations,
51
+ bindings?: LoggerBindings,
39
52
  ) {
53
+ this.logger = createLogger('checkpoint-builder', {
54
+ ...bindings,
55
+ instanceId: `checkpoint-${checkpointNumber}`,
56
+ });
40
57
  this.spongeBlob = SpongeBlob.init();
41
- this.logger.debug('Starting new checkpoint', { constants: constants.toInspect(), l1ToL2Messages });
58
+ this.logger.debug('Starting new checkpoint', { constants, l1ToL2Messages, feeAssetPriceModifier });
42
59
  }
43
60
 
44
61
  static async startNewCheckpoint(
45
62
  checkpointNumber: CheckpointNumber,
46
- constants: CheckpointConstantData,
63
+ constants: CheckpointGlobalVariables,
47
64
  l1ToL2Messages: Fr[],
65
+ previousCheckpointOutHashes: Fr[],
48
66
  db: MerkleTreeWriteOperations,
67
+ bindings?: LoggerBindings,
68
+ feeAssetPriceModifier: bigint = 0n,
49
69
  ): Promise<LightweightCheckpointBuilder> {
50
70
  // Insert l1-to-l2 messages into the tree.
51
- await db.appendLeaves(
52
- MerkleTreeId.L1_TO_L2_MESSAGE_TREE,
53
- padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
71
+ await appendL1ToL2MessagesToTree(db, l1ToL2Messages);
72
+
73
+ return new LightweightCheckpointBuilder(
74
+ checkpointNumber,
75
+ constants,
76
+ feeAssetPriceModifier,
77
+ l1ToL2Messages,
78
+ previousCheckpointOutHashes,
79
+ db,
80
+ bindings,
81
+ );
82
+ }
83
+
84
+ /**
85
+ * Resumes building a checkpoint from existing blocks. This is used for validator re-execution
86
+ * where blocks have already been built and their effects are already in the database.
87
+ * Unlike startNewCheckpoint, this does NOT append l1ToL2Messages to the tree since they
88
+ * were already added when the blocks were originally built.
89
+ */
90
+ static async resumeCheckpoint(
91
+ checkpointNumber: CheckpointNumber,
92
+ constants: CheckpointGlobalVariables,
93
+ feeAssetPriceModifier: bigint,
94
+ l1ToL2Messages: Fr[],
95
+ previousCheckpointOutHashes: Fr[],
96
+ db: MerkleTreeWriteOperations,
97
+ existingBlocks: L2Block[],
98
+ bindings?: LoggerBindings,
99
+ ): Promise<LightweightCheckpointBuilder> {
100
+ const builder = new LightweightCheckpointBuilder(
101
+ checkpointNumber,
102
+ constants,
103
+ feeAssetPriceModifier,
104
+ l1ToL2Messages,
105
+ previousCheckpointOutHashes,
106
+ db,
107
+ bindings,
54
108
  );
55
109
 
56
- return new LightweightCheckpointBuilder(checkpointNumber, constants, l1ToL2Messages, db);
110
+ builder.logger.debug('Resuming checkpoint from existing blocks', {
111
+ checkpointNumber,
112
+ numExistingBlocks: existingBlocks.length,
113
+ blockNumbers: existingBlocks.map(b => b.header.getBlockNumber()),
114
+ });
115
+
116
+ if (existingBlocks.length === 0) {
117
+ throw new Error(`Cannot resume checkpoint ${checkpointNumber} with no existing blocks`);
118
+ }
119
+
120
+ // Validate block order and consistency
121
+ for (let i = 1; i < existingBlocks.length; i++) {
122
+ const prev = existingBlocks[i - 1];
123
+ const curr = existingBlocks[i];
124
+ if (curr.number !== prev.number + 1) {
125
+ throw new Error(`Non-sequential block numbers in resumeCheckpoint: ${prev.number} -> ${curr.number}`);
126
+ }
127
+ if (!prev.archive.root.equals(curr.header.lastArchive.root)) {
128
+ throw new Error(`Archive root mismatch between blocks ${prev.number} and ${curr.number}`);
129
+ }
130
+ }
131
+
132
+ for (let i = 0; i < existingBlocks.length; i++) {
133
+ const block = existingBlocks[i];
134
+ const isFirstBlock = i === 0;
135
+
136
+ if (isFirstBlock) {
137
+ builder.lastArchives.push(block.header.lastArchive);
138
+ }
139
+
140
+ builder.lastArchives.push(block.archive);
141
+
142
+ const blockBlobFields = block.toBlobFields();
143
+ await builder.spongeBlob.absorb(blockBlobFields);
144
+ builder.blobFields.push(...blockBlobFields);
145
+
146
+ builder.blocks.push(block);
147
+ }
148
+
149
+ return builder;
150
+ }
151
+
152
+ /** Returns how many blocks have been added to this checkpoint so far */
153
+ public getBlockCount() {
154
+ return this.blocks.length;
155
+ }
156
+
157
+ public getBlocks() {
158
+ return this.blocks;
57
159
  }
58
160
 
59
- async addBlock(globalVariables: GlobalVariables, endState: StateReference, txs: ProcessedTx[]): Promise<L2BlockNew> {
161
+ /**
162
+ * Adds a new block to the checkpoint. The tx effects must have already been inserted into the db if
163
+ * this is called after tx processing, if that's not the case, then set `insertTxsEffects` to true.
164
+ */
165
+ public async addBlock(
166
+ globalVariables: GlobalVariables,
167
+ txs: ProcessedTx[],
168
+ opts: { insertTxsEffects?: boolean; expectedEndState?: StateReference } = {},
169
+ ): Promise<{ block: L2Block; timings: Record<string, number> }> {
170
+ const timings: Record<string, number> = {};
60
171
  const isFirstBlock = this.blocks.length === 0;
172
+
173
+ // Empty blocks are only allowed as the first block in a checkpoint
174
+ if (!isFirstBlock && txs.length === 0) {
175
+ throw new Error('Cannot add empty block that is not the first block in the checkpoint.');
176
+ }
177
+
61
178
  if (isFirstBlock) {
62
- this.lastArchives.push(await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.db));
179
+ const [msGetInitialArchive, initialArchive] = await elapsed(() => getTreeSnapshot(MerkleTreeId.ARCHIVE, this.db));
180
+ this.lastArchives.push(initialArchive);
181
+ timings.getInitialArchive = msGetInitialArchive;
63
182
  }
64
183
 
65
184
  const lastArchive = this.lastArchives.at(-1)!;
66
185
 
67
- for (const tx of txs) {
68
- await insertSideEffects(tx, this.db);
186
+ if (opts.insertTxsEffects) {
187
+ this.logger.debug(
188
+ `Inserting side effects for ${txs.length} txs for block ${globalVariables.blockNumber} into db`,
189
+ { txs: txs.map(tx => tx.hash.toString()) },
190
+ );
191
+ let msInsertSideEffects = 0;
192
+ for (const tx of txs) {
193
+ const [ms] = await elapsed(() => insertSideEffects(tx, this.db));
194
+ msInsertSideEffects += ms;
195
+ }
196
+ timings.insertSideEffects = msInsertSideEffects;
197
+ }
198
+
199
+ const [msGetEndState, endState] = await elapsed(() => this.db.getStateReference());
200
+ timings.getEndState = msGetEndState;
201
+
202
+ if (opts.expectedEndState && !endState.equals(opts.expectedEndState)) {
203
+ this.logger.error('End state after processing txs does not match expected end state', {
204
+ globalVariables: globalVariables.toInspect(),
205
+ expectedEndState: opts.expectedEndState.toInspect(),
206
+ actualEndState: endState.toInspect(),
207
+ });
208
+ throw new Error(`End state does not match expected end state when building block ${globalVariables.blockNumber}`);
69
209
  }
70
210
 
71
- const { header, body, blockBlobFields } = await buildHeaderAndBodyFromTxs(
72
- txs,
73
- lastArchive,
74
- endState,
75
- globalVariables,
76
- this.spongeBlob,
77
- isFirstBlock,
211
+ const [msBuildHeaderAndBody, { header, body, blockBlobFields }] = await elapsed(() =>
212
+ buildHeaderAndBodyFromTxs(txs, lastArchive, endState, globalVariables, this.spongeBlob, isFirstBlock),
78
213
  );
214
+ timings.buildHeaderAndBody = msBuildHeaderAndBody;
215
+
216
+ header.state.validate();
79
217
 
80
218
  await this.db.updateArchive(header);
81
- const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.db);
219
+ const [msUpdateArchive, newArchive] = await elapsed(() => getTreeSnapshot(MerkleTreeId.ARCHIVE, this.db));
220
+ timings.updateArchive = msUpdateArchive;
82
221
  this.lastArchives.push(newArchive);
83
222
 
84
- const block = new L2BlockNew(newArchive, header, body);
223
+ const expectedNextLeafIndex = Number(globalVariables.blockNumber) + 1;
224
+ if (newArchive.nextAvailableLeafIndex !== expectedNextLeafIndex) {
225
+ throw new Error(
226
+ `Archive tree next leaf index mismatch after building block ${globalVariables.blockNumber} (expected ${expectedNextLeafIndex} but got ${newArchive.nextAvailableLeafIndex})`,
227
+ );
228
+ }
229
+
230
+ const indexWithinCheckpoint = IndexWithinCheckpoint(this.blocks.length);
231
+ const block = new L2Block(newArchive, header, body, this.checkpointNumber, indexWithinCheckpoint);
85
232
  this.blocks.push(block);
86
233
 
87
- await this.spongeBlob.absorb(blockBlobFields);
234
+ const [msSpongeAbsorb] = await elapsed(() => this.spongeBlob.absorb(blockBlobFields));
235
+ timings.spongeAbsorb = msSpongeAbsorb;
88
236
  this.blobFields.push(...blockBlobFields);
89
237
 
90
238
  this.logger.debug(`Built block ${header.getBlockNumber()}`, {
@@ -95,12 +243,12 @@ export class LightweightCheckpointBuilder {
95
243
  txs: block.body.txEffects.map(tx => tx.txHash.toString()),
96
244
  });
97
245
 
98
- return block;
246
+ return { block, timings };
99
247
  }
100
248
 
101
249
  async completeCheckpoint(): Promise<Checkpoint> {
102
250
  if (!this.blocks.length) {
103
- throw new Error('No blocks added to checkpoint.');
251
+ throw new Error('Cannot complete a checkpoint with no blocks');
104
252
  }
105
253
 
106
254
  const numBlobFields = this.blobFields.length + 1; // +1 for the checkpoint end marker.
@@ -112,32 +260,63 @@ export class LightweightCheckpointBuilder {
112
260
 
113
261
  const newArchive = this.lastArchives[this.lastArchives.length - 1];
114
262
 
115
- const blobs = getBlobsPerL1Block(this.blobFields);
263
+ const blobs = await getBlobsPerL1Block(this.blobFields);
116
264
  const blobsHash = computeBlobsHashFromBlobs(blobs);
117
265
 
118
266
  const inHash = computeInHashFromL1ToL2Messages(this.l1ToL2Messages);
119
267
 
120
- const outHash = computeCheckpointOutHash(blocks.map(block => block.body.txEffects.map(tx => tx.l2ToL1Msgs)));
121
-
122
- const constants = this.constants!;
268
+ const { slotNumber, coinbase, feeRecipient, gasFees } = this.constants;
269
+ const checkpointOutHash = computeCheckpointOutHash(
270
+ blocks.map(block => block.body.txEffects.map(tx => tx.l2ToL1Msgs)),
271
+ );
272
+ const epochOutHash = accumulateCheckpointOutHashes([...this.previousCheckpointOutHashes, checkpointOutHash]);
123
273
 
124
- // timestamp of a checkpoint is the timestamp of the last block in the checkpoint.
274
+ // All blocks in the checkpoint have the same timestamp
125
275
  const timestamp = blocks[blocks.length - 1].timestamp;
126
276
 
127
277
  const totalManaUsed = blocks.reduce((acc, block) => acc.add(block.header.totalManaUsed), Fr.ZERO);
278
+ const accumulatedFees = blocks.reduce((acc, block) => acc.add(block.header.totalFees), Fr.ZERO);
128
279
 
129
280
  const header = CheckpointHeader.from({
130
281
  lastArchiveRoot: this.lastArchives[0].root,
282
+ blobsHash,
283
+ inHash,
284
+ epochOutHash,
131
285
  blockHeadersHash,
132
- contentCommitment: new ContentCommitment(blobsHash, inHash, outHash),
133
- slotNumber: constants.slotNumber,
286
+ slotNumber,
134
287
  timestamp,
135
- coinbase: constants.coinbase,
136
- feeRecipient: constants.feeRecipient,
137
- gasFees: constants.gasFees,
288
+ coinbase,
289
+ feeRecipient,
290
+ gasFees,
138
291
  totalManaUsed,
292
+ accumulatedFees,
139
293
  });
140
294
 
141
- return new Checkpoint(newArchive, header, blocks, this.checkpointNumber);
295
+ this.logger.debug(`Completed checkpoint ${this.checkpointNumber}`, {
296
+ checkpointNumber: this.checkpointNumber,
297
+ headerHash: header.hash().toString(),
298
+ checkpointOutHash: checkpointOutHash.toString(),
299
+ numPreviousCheckpointOutHashes: this.previousCheckpointOutHashes.length,
300
+ ...header.toInspect(),
301
+ });
302
+
303
+ return new Checkpoint(newArchive, header, blocks, this.checkpointNumber, this.feeAssetPriceModifier);
304
+ }
305
+
306
+ clone() {
307
+ const clone = new LightweightCheckpointBuilder(
308
+ this.checkpointNumber,
309
+ this.constants,
310
+ this.feeAssetPriceModifier,
311
+ [...this.l1ToL2Messages],
312
+ [...this.previousCheckpointOutHashes],
313
+ this.db,
314
+ this.logger.getBindings(),
315
+ );
316
+ clone.lastArchives = [...this.lastArchives];
317
+ clone.spongeBlob = this.spongeBlob.clone();
318
+ clone.blocks = [...this.blocks];
319
+ clone.blobFields = [...this.blobFields];
320
+ return clone;
142
321
  }
143
322
  }
@@ -1,7 +1,7 @@
1
1
  import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
- import { randomBytes } from '@aztec/foundation/crypto';
2
+ import { randomBytes } from '@aztec/foundation/crypto/random';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
4
  import { EthAddress } from '@aztec/foundation/eth-address';
4
- import { Fr } from '@aztec/foundation/fields';
5
5
  import type { Logger } from '@aztec/foundation/log';
6
6
  import type { FieldsOf } from '@aztec/foundation/types';
7
7
  import { fileURLToPath } from '@aztec/foundation/url';
@@ -75,7 +75,8 @@ export async function getSimulator(
75
75
  logger?.info(
76
76
  `Using native ACVM at ${config.acvmBinaryPath} and working directory ${config.acvmWorkingDirectory}`,
77
77
  );
78
- return new NativeACVMSimulator(config.acvmWorkingDirectory, config.acvmBinaryPath);
78
+ const acvmLogger = logger?.createChild('acvm-native');
79
+ return new NativeACVMSimulator(config.acvmWorkingDirectory, config.acvmBinaryPath, undefined, acvmLogger);
79
80
  } catch {
80
81
  logger?.warn(`Failed to access ACVM at ${config.acvmBinaryPath}, falling back to WASM`);
81
82
  }