@aztec/prover-client 0.76.4 → 0.77.0-testnet-ignition.17

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 (136) hide show
  1. package/dest/bin/get-proof-inputs.js +20 -17
  2. package/dest/block_builder/index.d.ts +1 -1
  3. package/dest/block_builder/index.d.ts.map +1 -1
  4. package/dest/block_builder/index.js +0 -1
  5. package/dest/block_builder/light.d.ts +4 -2
  6. package/dest/block_builder/light.d.ts.map +1 -1
  7. package/dest/block_builder/light.js +28 -15
  8. package/dest/config.d.ts +2 -2
  9. package/dest/config.d.ts.map +1 -1
  10. package/dest/config.js +10 -12
  11. package/dest/index.d.ts +1 -1
  12. package/dest/index.d.ts.map +1 -1
  13. package/dest/index.js +0 -1
  14. package/dest/mocks/fixtures.d.ts +4 -3
  15. package/dest/mocks/fixtures.d.ts.map +1 -1
  16. package/dest/mocks/fixtures.js +37 -30
  17. package/dest/mocks/test_context.d.ts +16 -12
  18. package/dest/mocks/test_context.d.ts.map +1 -1
  19. package/dest/mocks/test_context.js +85 -62
  20. package/dest/orchestrator/block-building-helpers.d.ts +12 -7
  21. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
  22. package/dest/orchestrator/block-building-helpers.js +98 -87
  23. package/dest/orchestrator/block-proving-state.d.ts +13 -8
  24. package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
  25. package/dest/orchestrator/block-proving-state.js +101 -73
  26. package/dest/orchestrator/epoch-proving-state.d.ts +10 -6
  27. package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
  28. package/dest/orchestrator/epoch-proving-state.js +57 -41
  29. package/dest/orchestrator/index.js +0 -1
  30. package/dest/orchestrator/orchestrator.d.ts +7 -5
  31. package/dest/orchestrator/orchestrator.d.ts.map +1 -1
  32. package/dest/orchestrator/orchestrator.js +656 -654
  33. package/dest/orchestrator/orchestrator_metrics.js +4 -3
  34. package/dest/orchestrator/tx-proving-state.d.ts +7 -4
  35. package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
  36. package/dest/orchestrator/tx-proving-state.js +54 -52
  37. package/dest/prover-client/factory.d.ts +2 -2
  38. package/dest/prover-client/factory.d.ts.map +1 -1
  39. package/dest/prover-client/factory.js +0 -1
  40. package/dest/prover-client/index.js +0 -1
  41. package/dest/prover-client/prover-client.d.ts +3 -3
  42. package/dest/prover-client/prover-client.d.ts.map +1 -1
  43. package/dest/prover-client/prover-client.js +31 -26
  44. package/dest/prover-client/server-epoch-prover.d.ts +8 -5
  45. package/dest/prover-client/server-epoch-prover.d.ts.map +1 -1
  46. package/dest/prover-client/server-epoch-prover.js +4 -4
  47. package/dest/proving_broker/broker_prover_facade.d.ts +5 -3
  48. package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
  49. package/dest/proving_broker/broker_prover_facade.js +80 -67
  50. package/dest/proving_broker/config.d.ts +15 -2
  51. package/dest/proving_broker/config.d.ts.map +1 -1
  52. package/dest/proving_broker/config.js +49 -44
  53. package/dest/proving_broker/factory.d.ts +2 -2
  54. package/dest/proving_broker/factory.d.ts.map +1 -1
  55. package/dest/proving_broker/factory.js +1 -6
  56. package/dest/proving_broker/fixtures.d.ts +1 -1
  57. package/dest/proving_broker/fixtures.d.ts.map +1 -1
  58. package/dest/proving_broker/fixtures.js +2 -2
  59. package/dest/proving_broker/index.js +0 -1
  60. package/dest/proving_broker/proof_store/factory.d.ts +1 -1
  61. package/dest/proving_broker/proof_store/factory.d.ts.map +1 -1
  62. package/dest/proving_broker/proof_store/factory.js +9 -12
  63. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts +3 -2
  64. package/dest/proving_broker/proof_store/gcs_proof_store.d.ts.map +1 -1
  65. package/dest/proving_broker/proof_store/gcs_proof_store.js +12 -7
  66. package/dest/proving_broker/proof_store/index.js +0 -1
  67. package/dest/proving_broker/proof_store/inline_proof_store.d.ts +3 -2
  68. package/dest/proving_broker/proof_store/inline_proof_store.d.ts.map +1 -1
  69. package/dest/proving_broker/proof_store/inline_proof_store.js +11 -7
  70. package/dest/proving_broker/proof_store/proof_store.d.ts +2 -1
  71. package/dest/proving_broker/proof_store/proof_store.d.ts.map +1 -1
  72. package/dest/proving_broker/proof_store/proof_store.js +3 -2
  73. package/dest/proving_broker/proving_agent.d.ts +3 -2
  74. package/dest/proving_broker/proving_agent.d.ts.map +1 -1
  75. package/dest/proving_broker/proving_agent.js +121 -124
  76. package/dest/proving_broker/proving_agent_instrumentation.d.ts +1 -1
  77. package/dest/proving_broker/proving_agent_instrumentation.d.ts.map +1 -1
  78. package/dest/proving_broker/proving_agent_instrumentation.js +6 -6
  79. package/dest/proving_broker/proving_broker.d.ts +4 -11
  80. package/dest/proving_broker/proving_broker.d.ts.map +1 -1
  81. package/dest/proving_broker/proving_broker.js +490 -446
  82. package/dest/proving_broker/proving_broker_database/memory.d.ts +2 -2
  83. package/dest/proving_broker/proving_broker_database/memory.d.ts.map +1 -1
  84. package/dest/proving_broker/proving_broker_database/memory.js +19 -13
  85. package/dest/proving_broker/proving_broker_database/persisted.d.ts +3 -3
  86. package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
  87. package/dest/proving_broker/proving_broker_database/persisted.js +62 -29
  88. package/dest/proving_broker/proving_broker_database.d.ts +1 -1
  89. package/dest/proving_broker/proving_broker_database.d.ts.map +1 -1
  90. package/dest/proving_broker/proving_broker_database.js +3 -2
  91. package/dest/proving_broker/proving_broker_instrumentation.d.ts +6 -2
  92. package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -1
  93. package/dest/proving_broker/proving_broker_instrumentation.js +47 -22
  94. package/dest/proving_broker/proving_job_controller.d.ts +2 -1
  95. package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
  96. package/dest/proving_broker/proving_job_controller.js +81 -62
  97. package/dest/proving_broker/rpc.d.ts +4 -3
  98. package/dest/proving_broker/rpc.d.ts.map +1 -1
  99. package/dest/proving_broker/rpc.js +29 -25
  100. package/dest/test/mock_prover.d.ts +7 -5
  101. package/dest/test/mock_prover.d.ts.map +1 -1
  102. package/dest/test/mock_prover.js +13 -9
  103. package/package.json +16 -15
  104. package/src/bin/get-proof-inputs.ts +2 -1
  105. package/src/block_builder/index.ts +1 -1
  106. package/src/block_builder/light.ts +7 -10
  107. package/src/config.ts +2 -2
  108. package/src/index.ts +1 -1
  109. package/src/mocks/fixtures.ts +13 -15
  110. package/src/mocks/test_context.ts +60 -102
  111. package/src/orchestrator/block-building-helpers.ts +50 -45
  112. package/src/orchestrator/block-proving-state.ts +18 -22
  113. package/src/orchestrator/epoch-proving-state.ts +11 -16
  114. package/src/orchestrator/orchestrator.ts +26 -33
  115. package/src/orchestrator/tx-proving-state.ts +10 -13
  116. package/src/prover-client/factory.ts +2 -2
  117. package/src/prover-client/prover-client.ts +12 -12
  118. package/src/prover-client/server-epoch-prover.ts +8 -5
  119. package/src/proving_broker/broker_prover_facade.ts +29 -31
  120. package/src/proving_broker/config.ts +31 -3
  121. package/src/proving_broker/factory.ts +3 -11
  122. package/src/proving_broker/fixtures.ts +2 -1
  123. package/src/proving_broker/proof_store/factory.ts +1 -1
  124. package/src/proving_broker/proof_store/gcs_proof_store.ts +3 -3
  125. package/src/proving_broker/proof_store/inline_proof_store.ts +5 -5
  126. package/src/proving_broker/proof_store/proof_store.ts +9 -9
  127. package/src/proving_broker/proving_agent.ts +11 -11
  128. package/src/proving_broker/proving_agent_instrumentation.ts +5 -5
  129. package/src/proving_broker/proving_broker.ts +35 -32
  130. package/src/proving_broker/proving_broker_database/memory.ts +2 -2
  131. package/src/proving_broker/proving_broker_database/persisted.ts +8 -8
  132. package/src/proving_broker/proving_broker_database.ts +1 -1
  133. package/src/proving_broker/proving_broker_instrumentation.ts +24 -2
  134. package/src/proving_broker/proving_job_controller.ts +7 -7
  135. package/src/proving_broker/rpc.ts +6 -7
  136. package/src/test/mock_prover.ts +28 -30
@@ -1,18 +1,29 @@
1
- import { __esDecorate, __runInitializers } from "tslib";
2
- import { L2Block, MerkleTreeId, toNumBlobFields, } from '@aztec/circuit-types';
3
- import { AVM_PROOF_LENGTH_IN_FIELDS, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, BaseParityInputs, Fr, L1_TO_L2_MSG_SUBTREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUM_BASE_PARITY_PER_ROOT_PARITY, VerificationKeyData, makeEmptyRecursiveProof, } from '@aztec/circuits.js';
4
- import { EmptyBlockRootRollupInputs, PrivateBaseRollupInputs, SingleTxBlockRootRollupInputs, TubeInputs, } from '@aztec/circuits.js/rollup';
1
+ function _ts_decorate(decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ }
7
+ import { AVM_PROOF_LENGTH_IN_FIELDS, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, L1_TO_L2_MSG_SUBTREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUM_BASE_PARITY_PER_ROOT_PARITY } from '@aztec/constants';
5
8
  import { padArrayEnd, times } from '@aztec/foundation/collection';
6
9
  import { AbortError } from '@aztec/foundation/error';
10
+ import { Fr } from '@aztec/foundation/fields';
7
11
  import { createLogger } from '@aztec/foundation/log';
8
12
  import { promiseWithResolvers } from '@aztec/foundation/promise';
9
13
  import { assertLength } from '@aztec/foundation/serialize';
10
14
  import { pushTestData } from '@aztec/foundation/testing';
11
15
  import { elapsed } from '@aztec/foundation/timer';
12
- import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vks';
13
- import { Attributes, getTelemetryClient, trackSpan, wrapCallbackInSpan, } from '@aztec/telemetry-client';
16
+ import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
17
+ import { L2Block } from '@aztec/stdlib/block';
18
+ import { BaseParityInputs } from '@aztec/stdlib/parity';
19
+ import { makeEmptyRecursiveProof } from '@aztec/stdlib/proofs';
20
+ import { EmptyBlockRootRollupInputs, PrivateBaseRollupInputs, SingleTxBlockRootRollupInputs, TubeInputs } from '@aztec/stdlib/rollup';
21
+ import { MerkleTreeId } from '@aztec/stdlib/trees';
22
+ import { toNumBlobFields } from '@aztec/stdlib/tx';
23
+ import { VerificationKeyData } from '@aztec/stdlib/vks';
24
+ import { Attributes, getTelemetryClient, trackSpan, wrapCallbackInSpan } from '@aztec/telemetry-client';
14
25
  import { inspect } from 'util';
15
- import { buildBaseRollupHints, buildHeaderAndBodyFromTxs, getRootTreeSiblingPath, getSubtreeSiblingPath, getTreeSnapshot, validatePartialState, validateTx, } from './block-building-helpers.js';
26
+ import { buildBaseRollupHints, buildHeaderAndBodyFromTxs, getRootTreeSiblingPath, getSubtreeSiblingPath, getTreeSnapshot, validatePartialState, validateTx } from './block-building-helpers.js';
16
27
  import { EpochProvingState } from './epoch-proving-state.js';
17
28
  import { ProvingOrchestratorMetrics } from './orchestrator_metrics.js';
18
29
  import { TxProvingState } from './tx-proving-state.js';
@@ -26,663 +37,654 @@ const logger = createLogger('prover-client:orchestrator');
26
37
  * 5. Merge proofs are produced at each level of the tree until the root proof is produced
27
38
  *
28
39
  * The proving implementation is determined by the provided prover. This could be for example a local prover or a remote prover pool.
29
- */
30
- /**
40
+ */ /**
31
41
  * The orchestrator, managing the flow of recursive proving operations required to build the rollup proof tree.
32
- */
33
- let ProvingOrchestrator = (() => {
34
- var _a;
35
- let _instanceExtraInitializers = [];
36
- let _startNewBlock_decorators;
37
- let _addTxs_decorators;
38
- let _startTubeCircuits_decorators;
39
- let _setBlockCompleted_decorators;
40
- let _prepareBaseRollupInputs_decorators;
41
- return _a = class ProvingOrchestrator {
42
- constructor(dbProvider, prover, proverId = Fr.ZERO, telemetryClient = getTelemetryClient()) {
43
- this.dbProvider = (__runInitializers(this, _instanceExtraInitializers), dbProvider);
44
- this.prover = prover;
45
- this.proverId = proverId;
46
- this.provingState = undefined;
47
- this.pendingProvingJobs = [];
48
- this.provingPromise = undefined;
49
- this.dbs = new Map();
50
- this.metrics = new ProvingOrchestratorMetrics(telemetryClient, 'ProvingOrchestrator');
51
- }
52
- get tracer() {
53
- return this.metrics.tracer;
54
- }
55
- getProverId() {
56
- return this.proverId;
57
- }
58
- stop() {
59
- this.cancel();
60
- return Promise.resolve();
61
- }
62
- startNewEpoch(epochNumber, firstBlockNumber, totalNumBlocks) {
63
- const { promise: _promise, resolve, reject } = promiseWithResolvers();
64
- const promise = _promise.catch((reason) => ({ status: 'failure', reason }));
65
- if (totalNumBlocks <= 0 || !Number.isInteger(totalNumBlocks)) {
66
- throw new Error(`Invalid number of blocks for epoch (got ${totalNumBlocks})`);
67
- }
68
- logger.info(`Starting epoch ${epochNumber} with ${totalNumBlocks} blocks`);
69
- this.provingState = new EpochProvingState(epochNumber, firstBlockNumber, totalNumBlocks, resolve, reject);
70
- this.provingPromise = promise;
71
- }
72
- /**
73
- * Starts off a new block
74
- * @param globalVariables - The global variables for the block
75
- * @param l1ToL2Messages - The l1 to l2 messages for the block
76
- * @returns A proving ticket, containing a promise notifying of proving completion
77
- */
78
- async startNewBlock(globalVariables, l1ToL2Messages, previousBlockHeader) {
79
- if (!this.provingState) {
80
- throw new Error(`Invalid proving state, call startNewEpoch before starting a block`);
81
- }
82
- if (!this.provingState?.isAcceptingBlocks()) {
83
- throw new Error(`Epoch not accepting further blocks`);
84
- }
85
- logger.info(`Starting block ${globalVariables.blockNumber.toNumber()} for slot ${globalVariables.slotNumber.toNumber()}`);
86
- // Fork world state at the end of the immediately previous block
87
- const db = await this.dbProvider.fork(globalVariables.blockNumber.toNumber() - 1);
88
- this.dbs.set(globalVariables.blockNumber.toNumber(), db);
89
- // we start the block by enqueueing all of the base parity circuits
90
- const { l1ToL2MessageSubtreeSiblingPath, l1ToL2MessageTreeSnapshotAfterInsertion, baseParityInputs } = await this.prepareBaseParityInputs(l1ToL2Messages, db);
91
- // Get archive snapshot before this block lands
92
- const lastArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
93
- const newArchiveSiblingPath = await getRootTreeSiblingPath(MerkleTreeId.ARCHIVE, db);
94
- const blockProvingState = this.provingState.startNewBlock(globalVariables, l1ToL2Messages, l1ToL2MessageSubtreeSiblingPath, l1ToL2MessageTreeSnapshotAfterInsertion, lastArchive, newArchiveSiblingPath, previousBlockHeader);
95
- // Enqueue base parity circuits for the block
96
- for (let i = 0; i < baseParityInputs.length; i++) {
97
- this.enqueueBaseParityCircuit(blockProvingState, baseParityInputs[i], i);
98
- }
99
- }
100
- /**
101
- * The interface to add simulated transactions to the scheduler. This can only be called once per block.
102
- * @param txs - The transactions to be proven
103
- */
104
- async addTxs(txs) {
105
- if (!txs.length) {
106
- // To avoid an ugly throw below. If we require an empty block, we can just call setBlockCompleted
107
- // on a block with no txs. We cannot do that here because we cannot find the blockNumber without any txs.
108
- logger.warn(`Provided no txs to orchestrator addTxs.`);
109
- return;
110
- }
111
- const blockNumber = txs[0].constants.globalVariables.blockNumber.toNumber();
112
- const provingState = this.provingState?.getBlockProvingStateByBlockNumber(blockNumber);
113
- if (!provingState) {
114
- throw new Error(`Block proving state for ${blockNumber} not found`);
115
- }
116
- if (provingState.totalNumTxs) {
117
- throw new Error(`Block ${blockNumber} has been initialized with transactions.`);
118
- }
119
- const numBlobFields = toNumBlobFields(txs);
120
- provingState.startNewBlock(txs.length, numBlobFields);
121
- logger.info(`Adding ${txs.length} transactions with ${numBlobFields} blob fields to block ${provingState.blockNumber}`);
122
- for (const tx of txs) {
123
- try {
124
- if (!provingState.verifyState()) {
125
- throw new Error(`Invalid proving state when adding a tx`);
126
- }
127
- validateTx(tx);
128
- logger.info(`Received transaction: ${tx.hash}`);
129
- const [hints, treeSnapshots] = await this.prepareTransaction(tx, provingState);
130
- const txProvingState = new TxProvingState(tx, hints, treeSnapshots);
131
- const txIndex = provingState.addNewTx(txProvingState);
132
- this.getOrEnqueueTube(provingState, txIndex);
133
- if (txProvingState.requireAvmProof) {
134
- logger.debug(`Enqueueing public VM for tx ${txIndex}`);
135
- this.enqueueVM(provingState, txIndex);
136
- }
137
- }
138
- catch (err) {
139
- throw new Error(`Error adding transaction ${tx.hash.toString()} to block ${blockNumber}: ${err.message}`, {
140
- cause: err,
141
- });
142
- }
143
- }
144
- }
145
- /**
146
- * Kickstarts tube circuits for the specified txs. These will be used during epoch proving.
147
- * Note that if the tube circuits are not started this way, they will be started nontheless after processing.
148
- */
149
- async startTubeCircuits(txs) {
150
- if (!this.provingState?.verifyState()) {
151
- throw new Error(`Invalid proving state, call startNewEpoch before starting tube circuits`);
152
- }
153
- for (const tx of txs) {
154
- const txHash = (await tx.getTxHash()).toString();
155
- const tubeInputs = new TubeInputs(tx.clientIvcProof);
156
- const tubeProof = promiseWithResolvers();
157
- logger.debug(`Starting tube circuit for tx ${txHash}`);
158
- this.doEnqueueTube(txHash, tubeInputs, proof => tubeProof.resolve(proof));
159
- this.provingState?.cachedTubeProofs.set(txHash, tubeProof.promise);
160
- }
161
- }
162
- /**
163
- * Marks the block as completed.
164
- * Computes the block header and updates the archive tree.
165
- */
166
- async setBlockCompleted(blockNumber, expectedHeader) {
167
- const provingState = this.provingState?.getBlockProvingStateByBlockNumber(blockNumber);
168
- if (!provingState) {
169
- throw new Error(`Block proving state for ${blockNumber} not found`);
170
- }
171
- if (!provingState.spongeBlobState) {
172
- // If we are completing an empty block, initialise the provingState.
173
- // We will have 0 txs and no blob fields.
174
- provingState.startNewBlock(0, 0);
175
- }
42
+ */ export class ProvingOrchestrator {
43
+ dbProvider;
44
+ prover;
45
+ proverId;
46
+ provingState;
47
+ pendingProvingJobs;
48
+ provingPromise;
49
+ metrics;
50
+ dbs;
51
+ constructor(dbProvider, prover, proverId = Fr.ZERO, telemetryClient = getTelemetryClient()){
52
+ this.dbProvider = dbProvider;
53
+ this.prover = prover;
54
+ this.proverId = proverId;
55
+ this.provingState = undefined;
56
+ this.pendingProvingJobs = [];
57
+ this.provingPromise = undefined;
58
+ this.dbs = new Map();
59
+ this.metrics = new ProvingOrchestratorMetrics(telemetryClient, 'ProvingOrchestrator');
60
+ }
61
+ get tracer() {
62
+ return this.metrics.tracer;
63
+ }
64
+ getProverId() {
65
+ return this.proverId;
66
+ }
67
+ stop() {
68
+ this.cancel();
69
+ return Promise.resolve();
70
+ }
71
+ startNewEpoch(epochNumber, firstBlockNumber, totalNumBlocks) {
72
+ const { promise: _promise, resolve, reject } = promiseWithResolvers();
73
+ const promise = _promise.catch((reason)=>({
74
+ status: 'failure',
75
+ reason
76
+ }));
77
+ if (totalNumBlocks <= 0 || !Number.isInteger(totalNumBlocks)) {
78
+ throw new Error(`Invalid number of blocks for epoch (got ${totalNumBlocks})`);
79
+ }
80
+ logger.info(`Starting epoch ${epochNumber} with ${totalNumBlocks} blocks`);
81
+ this.provingState = new EpochProvingState(epochNumber, firstBlockNumber, totalNumBlocks, resolve, reject);
82
+ this.provingPromise = promise;
83
+ }
84
+ /**
85
+ * Starts off a new block
86
+ * @param globalVariables - The global variables for the block
87
+ * @param l1ToL2Messages - The l1 to l2 messages for the block
88
+ * @returns A proving ticket, containing a promise notifying of proving completion
89
+ */ async startNewBlock(globalVariables, l1ToL2Messages, previousBlockHeader) {
90
+ if (!this.provingState) {
91
+ throw new Error(`Invalid proving state, call startNewEpoch before starting a block`);
92
+ }
93
+ if (!this.provingState?.isAcceptingBlocks()) {
94
+ throw new Error(`Epoch not accepting further blocks`);
95
+ }
96
+ logger.info(`Starting block ${globalVariables.blockNumber.toNumber()} for slot ${globalVariables.slotNumber.toNumber()}`);
97
+ // Fork world state at the end of the immediately previous block
98
+ const db = await this.dbProvider.fork(globalVariables.blockNumber.toNumber() - 1);
99
+ this.dbs.set(globalVariables.blockNumber.toNumber(), db);
100
+ // we start the block by enqueueing all of the base parity circuits
101
+ const { l1ToL2MessageSubtreeSiblingPath, l1ToL2MessageTreeSnapshotAfterInsertion, baseParityInputs } = await this.prepareBaseParityInputs(l1ToL2Messages, db);
102
+ // Get archive snapshot before this block lands
103
+ const lastArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
104
+ const newArchiveSiblingPath = await getRootTreeSiblingPath(MerkleTreeId.ARCHIVE, db);
105
+ const blockProvingState = this.provingState.startNewBlock(globalVariables, l1ToL2Messages, l1ToL2MessageSubtreeSiblingPath, l1ToL2MessageTreeSnapshotAfterInsertion, lastArchive, newArchiveSiblingPath, previousBlockHeader);
106
+ // Enqueue base parity circuits for the block
107
+ for(let i = 0; i < baseParityInputs.length; i++){
108
+ this.enqueueBaseParityCircuit(blockProvingState, baseParityInputs[i], i);
109
+ }
110
+ }
111
+ /**
112
+ * The interface to add simulated transactions to the scheduler. This can only be called once per block.
113
+ * @param txs - The transactions to be proven
114
+ */ async addTxs(txs) {
115
+ if (!txs.length) {
116
+ // To avoid an ugly throw below. If we require an empty block, we can just call setBlockCompleted
117
+ // on a block with no txs. We cannot do that here because we cannot find the blockNumber without any txs.
118
+ logger.warn(`Provided no txs to orchestrator addTxs.`);
119
+ return;
120
+ }
121
+ const blockNumber = txs[0].constants.globalVariables.blockNumber.toNumber();
122
+ const provingState = this.provingState?.getBlockProvingStateByBlockNumber(blockNumber);
123
+ if (!provingState) {
124
+ throw new Error(`Block proving state for ${blockNumber} not found`);
125
+ }
126
+ if (provingState.totalNumTxs) {
127
+ throw new Error(`Block ${blockNumber} has been initialized with transactions.`);
128
+ }
129
+ const numBlobFields = toNumBlobFields(txs);
130
+ provingState.startNewBlock(txs.length, numBlobFields);
131
+ logger.info(`Adding ${txs.length} transactions with ${numBlobFields} blob fields to block ${provingState.blockNumber}`);
132
+ for (const tx of txs){
133
+ try {
176
134
  if (!provingState.verifyState()) {
177
- throw new Error(`Block proving failed: ${provingState.error}`);
178
- }
179
- // And build the block header
180
- logger.verbose(`Block ${blockNumber} completed. Assembling header.`);
181
- await this.buildBlock(provingState, expectedHeader);
182
- // If the proofs were faster than the block building, then we need to try the block root rollup again here
183
- await this.checkAndEnqueueBlockRootRollup(provingState);
184
- return provingState.block;
185
- }
186
- /** Returns the block as built for a given index. */
187
- getBlock(index) {
188
- const block = this.provingState?.blocks[index]?.block;
189
- if (!block) {
190
- throw new Error(`Block at index ${index} not available`);
191
- }
192
- return block;
193
- }
194
- async buildBlock(provingState, expectedHeader) {
195
- // Collect all new nullifiers, commitments, and contracts from all txs in this block to build body
196
- const txs = provingState.allTxs.map(a => a.processedTx);
197
- // Get db for this block
198
- const db = this.dbs.get(provingState.blockNumber);
199
- // Given we've applied every change from this block, now assemble the block header
200
- // and update the archive tree, so we're ready to start processing the next block
201
- const { header, body } = await buildHeaderAndBodyFromTxs(txs, provingState.globalVariables, provingState.newL1ToL2Messages, db);
202
- if (expectedHeader && !header.equals(expectedHeader)) {
203
- logger.error(`Block header mismatch: header=${header} expectedHeader=${expectedHeader}`);
204
- throw new Error('Block header mismatch');
205
- }
206
- logger.verbose(`Updating archive tree with block ${provingState.blockNumber} header ${(await header.hash()).toString()}`);
207
- await db.updateArchive(header);
208
- // Assemble the L2 block
209
- const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
210
- const l2Block = new L2Block(newArchive, header, body);
211
- await this.verifyBuiltBlockAgainstSyncedState(l2Block, newArchive);
212
- logger.verbose(`Orchestrator finalised block ${l2Block.number}`);
213
- provingState.block = l2Block;
214
- }
215
- // Flagged as protected to disable in certain unit tests
216
- async verifyBuiltBlockAgainstSyncedState(l2Block, newArchive) {
217
- const syncedArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.dbProvider.getSnapshot(l2Block.number));
218
- if (!syncedArchive.equals(newArchive)) {
219
- throw new Error(`Archive tree mismatch for block ${l2Block.number}: world state synced to ${inspect(syncedArchive)} but built ${inspect(newArchive)}`);
220
- }
221
- }
222
- /**
223
- * Cancel any further proving
224
- */
225
- cancel() {
226
- for (const controller of this.pendingProvingJobs) {
227
- controller.abort();
228
- }
229
- this.provingState?.cancel();
230
- }
231
- /**
232
- * Returns the proof for the current epoch.
233
- */
234
- async finaliseEpoch() {
235
- if (!this.provingState || !this.provingPromise) {
236
- throw new Error(`Invalid proving state, an epoch must be proven before it can be finalised`);
237
- }
238
- const result = await this.provingPromise;
239
- if (result.status === 'failure') {
240
- throw new Error(`Epoch proving failed: ${result.reason}`);
241
- }
242
- const epochProofResult = this.provingState.getEpochProofResult();
243
- pushTestData('epochProofResult', {
244
- proof: epochProofResult.proof.toString(),
245
- publicInputs: epochProofResult.publicInputs.toString(),
246
- });
247
- return epochProofResult;
248
- }
249
- /**
250
- * Starts the proving process for the given transaction and adds it to our state
251
- * @param tx - The transaction whose proving we wish to commence
252
- * @param provingState - The proving state being worked on
253
- */
254
- async prepareTransaction(tx, provingState) {
255
- const txInputs = await this.prepareBaseRollupInputs(provingState, tx);
256
- if (!txInputs) {
257
- // This should not be possible
258
- throw new Error(`Unable to add transaction, preparing base inputs failed`);
259
- }
260
- return txInputs;
261
- }
262
- /**
263
- * Enqueue a job to be scheduled
264
- * @param provingState - The proving state object being operated on
265
- * @param jobType - The type of job to be queued
266
- * @param job - The actual job, returns a promise notifying of the job's completion
267
- */
268
- deferredProving(provingState, request, callback) {
269
- if (!provingState?.verifyState()) {
270
- logger.debug(`Not enqueuing job, state no longer valid`);
271
- return;
272
- }
273
- const controller = new AbortController();
274
- this.pendingProvingJobs.push(controller);
275
- // We use a 'safeJob'. We don't want promise rejections in the proving pool, we want to capture the error here
276
- // and reject the proving job whilst keeping the event loop free of rejections
277
- const safeJob = async () => {
278
- try {
279
- // there's a delay between enqueueing this job and it actually running
280
- if (controller.signal.aborted) {
281
- return;
282
- }
283
- const result = await request(controller.signal);
284
- if (!provingState?.verifyState()) {
285
- logger.debug(`State no longer valid, discarding result`);
286
- return;
287
- }
288
- // we could have been cancelled whilst waiting for the result
289
- // and the prover ignored the signal. Drop the result in that case
290
- if (controller.signal.aborted) {
291
- return;
292
- }
293
- await callback(result);
294
- }
295
- catch (err) {
296
- if (err instanceof AbortError) {
297
- // operation was cancelled, probably because the block was cancelled
298
- // drop this result
299
- return;
300
- }
301
- logger.error(`Error thrown when proving job`, err);
302
- provingState.reject(`${err}`);
303
- }
304
- finally {
305
- const index = this.pendingProvingJobs.indexOf(controller);
306
- if (index > -1) {
307
- this.pendingProvingJobs.splice(index, 1);
308
- }
309
- }
310
- };
311
- // let the callstack unwind before adding the job to the queue
312
- setImmediate(() => void safeJob());
313
- }
314
- async prepareBaseParityInputs(l1ToL2Messages, db) {
315
- const l1ToL2MessagesPadded = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 'Too many L1 to L2 messages');
316
- const baseParityInputs = times(NUM_BASE_PARITY_PER_ROOT_PARITY, i => BaseParityInputs.fromSlice(l1ToL2MessagesPadded, i, getVKTreeRoot()));
317
- const l1ToL2MessageSubtreeSiblingPath = assertLength(await getSubtreeSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_SUBTREE_HEIGHT, db), L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH);
318
- // Update the local trees to include the new l1 to l2 messages
319
- await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
320
- const l1ToL2MessageTreeSnapshotAfterInsertion = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
321
- return {
322
- l1ToL2MessageSubtreeSiblingPath,
323
- l1ToL2MessageTreeSnapshotAfterInsertion,
324
- baseParityInputs,
325
- };
326
- }
327
- // Updates the merkle trees for a transaction. The first enqueued job for a transaction
328
- async prepareBaseRollupInputs(provingState, tx) {
329
- if (!provingState.verifyState() || !provingState.spongeBlobState) {
330
- logger.debug('Not preparing base rollup inputs, state invalid');
331
- return;
332
- }
333
- const db = this.dbs.get(provingState.blockNumber);
334
- // We build the base rollup inputs using a mock proof and verification key.
335
- // These will be overwritten later once we have proven the tube circuit and any public kernels
336
- const [ms, hints] = await elapsed(buildBaseRollupHints(tx, provingState.globalVariables, db, provingState.spongeBlobState));
337
- this.metrics.recordBaseRollupInputs(ms);
338
- const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map(async (id) => {
339
- return { key: id, value: await getTreeSnapshot(id, db) };
135
+ throw new Error(`Invalid proving state when adding a tx`);
136
+ }
137
+ validateTx(tx);
138
+ logger.info(`Received transaction: ${tx.hash}`);
139
+ const [hints, treeSnapshots] = await this.prepareTransaction(tx, provingState);
140
+ const txProvingState = new TxProvingState(tx, hints, treeSnapshots);
141
+ const txIndex = provingState.addNewTx(txProvingState);
142
+ this.getOrEnqueueTube(provingState, txIndex);
143
+ if (txProvingState.requireAvmProof) {
144
+ logger.debug(`Enqueueing public VM for tx ${txIndex}`);
145
+ this.enqueueVM(provingState, txIndex);
146
+ }
147
+ } catch (err) {
148
+ throw new Error(`Error adding transaction ${tx.hash.toString()} to block ${blockNumber}: ${err.message}`, {
149
+ cause: err
340
150
  });
341
- const treeSnapshots = new Map((await Promise.all(promises)).map(obj => [obj.key, obj.value]));
342
- if (!provingState.verifyState()) {
343
- logger.debug(`Discarding proving job, state no longer valid`);
344
- return;
345
- }
346
- return [hints, treeSnapshots];
347
151
  }
348
- // Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit
349
- // Executes the next level of merge if all inputs are available
350
- enqueueBaseRollup(provingState, txIndex) {
351
- if (!provingState.verifyState()) {
352
- logger.debug('Not running base rollup, state invalid');
152
+ }
153
+ }
154
+ /**
155
+ * Kickstarts tube circuits for the specified txs. These will be used during epoch proving.
156
+ * Note that if the tube circuits are not started this way, they will be started nontheless after processing.
157
+ */ async startTubeCircuits(txs) {
158
+ if (!this.provingState?.verifyState()) {
159
+ throw new Error(`Invalid proving state, call startNewEpoch before starting tube circuits`);
160
+ }
161
+ for (const tx of txs){
162
+ const txHash = (await tx.getTxHash()).toString();
163
+ const tubeInputs = new TubeInputs(tx.clientIvcProof);
164
+ const tubeProof = promiseWithResolvers();
165
+ logger.debug(`Starting tube circuit for tx ${txHash}`);
166
+ this.doEnqueueTube(txHash, tubeInputs, (proof)=>tubeProof.resolve(proof));
167
+ this.provingState?.cachedTubeProofs.set(txHash, tubeProof.promise);
168
+ }
169
+ }
170
+ /**
171
+ * Marks the block as completed.
172
+ * Computes the block header and updates the archive tree.
173
+ */ async setBlockCompleted(blockNumber, expectedHeader) {
174
+ const provingState = this.provingState?.getBlockProvingStateByBlockNumber(blockNumber);
175
+ if (!provingState) {
176
+ throw new Error(`Block proving state for ${blockNumber} not found`);
177
+ }
178
+ if (!provingState.spongeBlobState) {
179
+ // If we are completing an empty block, initialise the provingState.
180
+ // We will have 0 txs and no blob fields.
181
+ provingState.startNewBlock(0, 0);
182
+ }
183
+ if (!provingState.verifyState()) {
184
+ throw new Error(`Block proving failed: ${provingState.error}`);
185
+ }
186
+ // And build the block header
187
+ logger.verbose(`Block ${blockNumber} completed. Assembling header.`);
188
+ await this.buildBlock(provingState, expectedHeader);
189
+ // If the proofs were faster than the block building, then we need to try the block root rollup again here
190
+ await this.checkAndEnqueueBlockRootRollup(provingState);
191
+ return provingState.block;
192
+ }
193
+ /** Returns the block as built for a given index. */ getBlock(index) {
194
+ const block = this.provingState?.blocks[index]?.block;
195
+ if (!block) {
196
+ throw new Error(`Block at index ${index} not available`);
197
+ }
198
+ return block;
199
+ }
200
+ async buildBlock(provingState, expectedHeader) {
201
+ // Collect all new nullifiers, commitments, and contracts from all txs in this block to build body
202
+ const txs = provingState.allTxs.map((a)=>a.processedTx);
203
+ // Get db for this block
204
+ const db = this.dbs.get(provingState.blockNumber);
205
+ // Given we've applied every change from this block, now assemble the block header
206
+ // and update the archive tree, so we're ready to start processing the next block
207
+ const { header, body } = await buildHeaderAndBodyFromTxs(txs, provingState.globalVariables, provingState.newL1ToL2Messages, db);
208
+ if (expectedHeader && !header.equals(expectedHeader)) {
209
+ logger.error(`Block header mismatch: header=${header} expectedHeader=${expectedHeader}`);
210
+ throw new Error('Block header mismatch');
211
+ }
212
+ logger.verbose(`Updating archive tree with block ${provingState.blockNumber} header ${(await header.hash()).toString()}`);
213
+ await db.updateArchive(header);
214
+ // Assemble the L2 block
215
+ const newArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, db);
216
+ const l2Block = new L2Block(newArchive, header, body);
217
+ await this.verifyBuiltBlockAgainstSyncedState(l2Block, newArchive);
218
+ logger.verbose(`Orchestrator finalised block ${l2Block.number}`);
219
+ provingState.block = l2Block;
220
+ }
221
+ // Flagged as protected to disable in certain unit tests
222
+ async verifyBuiltBlockAgainstSyncedState(l2Block, newArchive) {
223
+ const syncedArchive = await getTreeSnapshot(MerkleTreeId.ARCHIVE, this.dbProvider.getSnapshot(l2Block.number));
224
+ if (!syncedArchive.equals(newArchive)) {
225
+ throw new Error(`Archive tree mismatch for block ${l2Block.number}: world state synced to ${inspect(syncedArchive)} but built ${inspect(newArchive)}`);
226
+ }
227
+ }
228
+ /**
229
+ * Cancel any further proving
230
+ */ cancel() {
231
+ for (const controller of this.pendingProvingJobs){
232
+ controller.abort();
233
+ }
234
+ this.provingState?.cancel();
235
+ }
236
+ /**
237
+ * Returns the proof for the current epoch.
238
+ */ async finaliseEpoch() {
239
+ if (!this.provingState || !this.provingPromise) {
240
+ throw new Error(`Invalid proving state, an epoch must be proven before it can be finalised`);
241
+ }
242
+ const result = await this.provingPromise;
243
+ if (result.status === 'failure') {
244
+ throw new Error(`Epoch proving failed: ${result.reason}`);
245
+ }
246
+ const epochProofResult = this.provingState.getEpochProofResult();
247
+ pushTestData('epochProofResult', {
248
+ proof: epochProofResult.proof.toString(),
249
+ publicInputs: epochProofResult.publicInputs.toString()
250
+ });
251
+ return epochProofResult;
252
+ }
253
+ /**
254
+ * Starts the proving process for the given transaction and adds it to our state
255
+ * @param tx - The transaction whose proving we wish to commence
256
+ * @param provingState - The proving state being worked on
257
+ */ async prepareTransaction(tx, provingState) {
258
+ const txInputs = await this.prepareBaseRollupInputs(provingState, tx);
259
+ if (!txInputs) {
260
+ // This should not be possible
261
+ throw new Error(`Unable to add transaction, preparing base inputs failed`);
262
+ }
263
+ return txInputs;
264
+ }
265
+ /**
266
+ * Enqueue a job to be scheduled
267
+ * @param provingState - The proving state object being operated on
268
+ * @param jobType - The type of job to be queued
269
+ * @param job - The actual job, returns a promise notifying of the job's completion
270
+ */ deferredProving(provingState, request, callback) {
271
+ if (!provingState?.verifyState()) {
272
+ logger.debug(`Not enqueuing job, state no longer valid`);
273
+ return;
274
+ }
275
+ const controller = new AbortController();
276
+ this.pendingProvingJobs.push(controller);
277
+ // We use a 'safeJob'. We don't want promise rejections in the proving pool, we want to capture the error here
278
+ // and reject the proving job whilst keeping the event loop free of rejections
279
+ const safeJob = async ()=>{
280
+ try {
281
+ // there's a delay between enqueueing this job and it actually running
282
+ if (controller.signal.aborted) {
353
283
  return;
354
284
  }
355
- const txProvingState = provingState.getTxProvingState(txIndex);
356
- const { processedTx } = txProvingState;
357
- const { rollupType, inputs } = txProvingState.getBaseRollupTypeAndInputs();
358
- logger.debug(`Enqueuing deferred proving base rollup for ${processedTx.hash.toString()}`);
359
- this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, `ProvingOrchestrator.prover.${inputs instanceof PrivateBaseRollupInputs ? 'getPrivateBaseRollupProof' : 'getPublicBaseRollupProof'}`, {
360
- [Attributes.TX_HASH]: processedTx.hash.toString(),
361
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
362
- [Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType,
363
- }, signal => {
364
- if (inputs instanceof PrivateBaseRollupInputs) {
365
- return this.prover.getPrivateBaseRollupProof(inputs, signal, provingState.epochNumber);
366
- }
367
- else {
368
- return this.prover.getPublicBaseRollupProof(inputs, signal, provingState.epochNumber);
369
- }
370
- }), async (result) => {
371
- logger.debug(`Completed proof for ${rollupType} for tx ${processedTx.hash.toString()}`);
372
- validatePartialState(result.inputs.end, txProvingState.treeSnapshots);
373
- const leafLocation = provingState.setBaseRollupProof(txIndex, result);
374
- if (provingState.totalNumTxs === 1) {
375
- await this.checkAndEnqueueBlockRootRollup(provingState);
376
- }
377
- else {
378
- await this.checkAndEnqueueNextMergeRollup(provingState, leafLocation);
379
- }
380
- });
381
- }
382
- // Enqueues the tube circuit for a given transaction index, or reuses the one already enqueued
383
- // Once completed, will enqueue the next circuit, either a public kernel or the base rollup
384
- getOrEnqueueTube(provingState, txIndex) {
385
- if (!provingState.verifyState()) {
386
- logger.debug('Not running tube circuit, state invalid');
387
- return;
388
- }
389
- const txProvingState = provingState.getTxProvingState(txIndex);
390
- const txHash = txProvingState.processedTx.hash.toString();
391
- const handleResult = (result) => {
392
- logger.debug(`Got tube proof for tx index: ${txIndex}`, { txHash });
393
- txProvingState.setTubeProof(result);
394
- this.provingState?.cachedTubeProofs.delete(txHash);
395
- this.checkAndEnqueueNextTxCircuit(provingState, txIndex);
396
- };
397
- if (this.provingState?.cachedTubeProofs.has(txHash)) {
398
- logger.debug(`Tube proof already enqueued for tx index: ${txIndex}`, { txHash });
399
- void this.provingState.cachedTubeProofs.get(txHash).then(handleResult);
400
- return;
401
- }
402
- logger.debug(`Enqueuing tube circuit for tx index: ${txIndex}`);
403
- this.doEnqueueTube(txHash, txProvingState.getTubeInputs(), handleResult);
404
- }
405
- doEnqueueTube(txHash, inputs, handler, provingState = this.provingState) {
285
+ const result = await request(controller.signal);
406
286
  if (!provingState?.verifyState()) {
407
- logger.debug('Not running tube circuit, state invalid');
287
+ logger.debug(`State no longer valid, discarding result`);
408
288
  return;
409
289
  }
410
- this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getTubeProof', {
411
- [Attributes.TX_HASH]: txHash,
412
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
413
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'tube-circuit',
414
- }, signal => this.prover.getTubeProof(inputs, signal, this.provingState.epochNumber)), handler);
415
- }
416
- // Executes the merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit
417
- // Enqueues the next level of merge if all inputs are available
418
- enqueueMergeRollup(provingState, location) {
419
- if (!provingState.verifyState()) {
420
- logger.debug('Not running merge rollup. State no longer valid.');
290
+ // we could have been cancelled whilst waiting for the result
291
+ // and the prover ignored the signal. Drop the result in that case
292
+ if (controller.signal.aborted) {
421
293
  return;
422
294
  }
423
- const inputs = provingState.getMergeRollupInputs(location);
424
- this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getMergeRollupProof', {
425
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
426
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'merge-rollup',
427
- }, signal => this.prover.getMergeRollupProof(inputs, signal, provingState.epochNumber)), async (result) => {
428
- provingState.setMergeRollupProof(location, result);
429
- await this.checkAndEnqueueNextMergeRollup(provingState, location);
430
- });
431
- }
432
- // Executes the block root rollup circuit
433
- async enqueueBlockRootRollup(provingState) {
434
- if (!provingState.verifyState()) {
435
- logger.debug('Not running block root rollup, state no longer valid');
436
- return;
437
- }
438
- provingState.blockRootRollupStarted = true;
439
- const { rollupType, inputs } = await provingState.getBlockRootRollupTypeAndInputs(this.proverId);
440
- logger.debug(`Enqueuing ${rollupType} for block ${provingState.blockNumber} with ${provingState.newL1ToL2Messages.length} l1 to l2 msgs.`);
441
- this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBlockRootRollupProof', {
442
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
443
- [Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType,
444
- }, signal => {
445
- if (inputs instanceof EmptyBlockRootRollupInputs) {
446
- return this.prover.getEmptyBlockRootRollupProof(inputs, signal, provingState.epochNumber);
447
- }
448
- else if (inputs instanceof SingleTxBlockRootRollupInputs) {
449
- return this.prover.getSingleTxBlockRootRollupProof(inputs, signal, provingState.epochNumber);
450
- }
451
- else {
452
- return this.prover.getBlockRootRollupProof(inputs, signal, provingState.epochNumber);
453
- }
454
- }), async (result) => {
455
- provingState.setBlockRootRollupProof(result);
456
- const header = await provingState.buildHeaderFromProvingOutputs(logger);
457
- if (!(await header.hash()).equals(await provingState.block.header.hash())) {
458
- logger.error(`Block header mismatch\nCircuit:${inspect(header)}\nComputed:${inspect(provingState.block.header)}`);
459
- provingState.reject(`Block header hash mismatch`);
460
- }
461
- logger.debug(`Completed ${rollupType} proof for block ${provingState.block.number}`);
462
- // validatePartialState(result.inputs.end, tx.treeSnapshots); // TODO(palla/prover)
463
- const epochProvingState = this.provingState;
464
- const leafLocation = epochProvingState.setBlockRootRollupProof(provingState.index, result);
465
- if (epochProvingState.totalNumBlocks === 1) {
466
- await this.enqueueEpochPadding(epochProvingState);
467
- }
468
- else {
469
- this.checkAndEnqueueNextBlockMergeRollup(epochProvingState, leafLocation);
470
- }
471
- });
472
- }
473
- // Executes the base parity circuit and stores the intermediate state for the root parity circuit
474
- // Enqueues the root parity circuit if all inputs are available
475
- enqueueBaseParityCircuit(provingState, inputs, index) {
476
- if (!provingState.verifyState()) {
477
- logger.debug('Not running base parity. State no longer valid.');
478
- return;
479
- }
480
- this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBaseParityProof', {
481
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
482
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity',
483
- }, signal => this.prover.getBaseParityProof(inputs, signal, provingState.epochNumber)), provingOutput => {
484
- provingState.setBaseParityProof(index, provingOutput);
485
- this.checkAndEnqueueRootParityCircuit(provingState);
486
- });
487
- }
488
- checkAndEnqueueRootParityCircuit(provingState) {
489
- if (!provingState.isReadyForRootParity()) {
490
- return;
491
- }
492
- this.enqueueRootParityCircuit(provingState);
493
- }
494
- // Runs the root parity circuit ans stored the outputs
495
- // Enqueues the root rollup proof if all inputs are available
496
- enqueueRootParityCircuit(provingState) {
497
- if (!provingState.verifyState()) {
498
- logger.debug('Not running root parity. State no longer valid.');
499
- return;
500
- }
501
- const inputs = provingState.getRootParityInputs();
502
- this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getRootParityProof', {
503
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
504
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity',
505
- }, signal => this.prover.getRootParityProof(inputs, signal, provingState.epochNumber)), async (result) => {
506
- provingState.setRootParityProof(result);
507
- await this.checkAndEnqueueBlockRootRollup(provingState);
508
- });
509
- }
510
- // Executes the block merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit
511
- // Enqueues the next level of merge if all inputs are available
512
- enqueueBlockMergeRollup(provingState, location) {
513
- if (!provingState.verifyState()) {
514
- logger.debug('Not running block merge rollup. State no longer valid.');
515
- return;
516
- }
517
- const inputs = provingState.getBlockMergeRollupInputs(location);
518
- this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBlockMergeRollupProof', {
519
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
520
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'block-merge-rollup',
521
- }, signal => this.prover.getBlockMergeRollupProof(inputs, signal, provingState.epochNumber)), result => {
522
- provingState.setBlockMergeRollupProof(location, result);
523
- this.checkAndEnqueueNextBlockMergeRollup(provingState, location);
524
- });
525
- }
526
- async enqueueEpochPadding(provingState) {
527
- if (!provingState.verifyState()) {
528
- logger.debug('Not running epoch padding. State no longer valid.');
529
- return;
530
- }
531
- logger.debug('Padding epoch proof with an empty block root proof.');
532
- const inputs = await provingState.getPaddingBlockRootInputs(this.proverId);
533
- this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getEmptyBlockRootRollupProof', {
534
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
535
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'empty-block-root-rollup',
536
- }, signal => this.prover.getEmptyBlockRootRollupProof(inputs, signal, provingState.epochNumber)), result => {
537
- logger.debug('Completed proof for padding block root.');
538
- provingState.setPaddingBlockRootProof(result);
539
- this.checkAndEnqueueRootRollup(provingState);
540
- });
541
- }
542
- // Executes the root rollup circuit
543
- enqueueRootRollup(provingState) {
544
- if (!provingState.verifyState()) {
545
- logger.debug('Not running root rollup, state no longer valid');
295
+ await callback(result);
296
+ } catch (err) {
297
+ if (err instanceof AbortError) {
298
+ // operation was cancelled, probably because the block was cancelled
299
+ // drop this result
546
300
  return;
547
301
  }
548
- logger.debug(`Preparing root rollup`);
549
- const inputs = provingState.getRootRollupInputs(this.proverId);
550
- this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getRootRollupProof', {
551
- [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
552
- [Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-rollup',
553
- }, signal => this.prover.getRootRollupProof(inputs, signal, provingState.epochNumber)), result => {
554
- logger.verbose(`Orchestrator completed root rollup for epoch ${provingState.epochNumber}`);
555
- provingState.setRootRollupProof(result);
556
- provingState.resolve({ status: 'success' });
557
- });
558
- }
559
- async checkAndEnqueueNextMergeRollup(provingState, currentLocation) {
560
- if (!provingState.isReadyForMergeRollup(currentLocation)) {
561
- return;
562
- }
563
- const parentLocation = provingState.getParentLocation(currentLocation);
564
- if (parentLocation.level === 0) {
565
- await this.checkAndEnqueueBlockRootRollup(provingState);
566
- }
567
- else {
568
- this.enqueueMergeRollup(provingState, parentLocation);
569
- }
570
- }
571
- async checkAndEnqueueBlockRootRollup(provingState) {
572
- if (!provingState.isReadyForBlockRootRollup()) {
573
- logger.debug('Not ready for root rollup');
574
- return;
575
- }
576
- if (provingState.blockRootRollupStarted) {
577
- logger.debug('Block root rollup already started');
578
- return;
579
- }
580
- const blockNumber = provingState.blockNumber;
581
- // TODO(palla/prover): This closes the fork only on the happy path. If this epoch orchestrator
582
- // is aborted and never reaches this point, it will leak the fork. We need to add a global cleanup,
583
- // but have to make sure it only runs once all operations are completed, otherwise some function here
584
- // will attempt to access the fork after it was closed.
585
- logger.debug(`Cleaning up world state fork for ${blockNumber}`);
586
- void this.dbs
587
- .get(blockNumber)
588
- ?.close()
589
- .then(() => this.dbs.delete(blockNumber))
590
- .catch(err => logger.error(`Error closing db for block ${blockNumber}`, err));
591
- await this.enqueueBlockRootRollup(provingState);
592
- }
593
- checkAndEnqueueNextBlockMergeRollup(provingState, currentLocation) {
594
- if (!provingState.isReadyForBlockMerge(currentLocation)) {
595
- return;
596
- }
597
- const parentLocation = provingState.getParentLocation(currentLocation);
598
- if (parentLocation.level === 0) {
599
- this.checkAndEnqueueRootRollup(provingState);
600
- }
601
- else {
602
- this.enqueueBlockMergeRollup(provingState, parentLocation);
603
- }
604
- }
605
- checkAndEnqueueRootRollup(provingState) {
606
- if (!provingState.isReadyForRootRollup()) {
607
- logger.debug('Not ready for root rollup');
608
- return;
609
- }
610
- this.enqueueRootRollup(provingState);
611
- }
612
- /**
613
- * Executes the VM circuit for a public function, will enqueue the corresponding kernel if the
614
- * previous kernel is ready
615
- * @param provingState - The proving state being operated on
616
- * @param txIndex - The index of the transaction being proven
617
- */
618
- enqueueVM(provingState, txIndex) {
619
- if (!provingState.verifyState()) {
620
- logger.debug(`Not running VM circuit as state is no longer valid`);
621
- return;
622
- }
623
- const txProvingState = provingState.getTxProvingState(txIndex);
624
- // This function tries to do AVM proving. If there is a failure, it fakes the proof unless AVM_PROVING_STRICT is defined.
625
- // Nothing downstream depends on the AVM proof yet. So having this mode lets us incrementally build the AVM circuit.
626
- const doAvmProving = wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getAvmProof', {
627
- [Attributes.TX_HASH]: txProvingState.processedTx.hash.toString(),
628
- }, async (signal) => {
629
- const inputs = txProvingState.getAvmInputs();
630
- try {
631
- return await this.prover.getAvmProof(inputs, signal, provingState.epochNumber);
632
- }
633
- catch (err) {
634
- if (process.env.AVM_PROVING_STRICT) {
635
- logger.error(`Error thrown when proving AVM circuit with AVM_PROVING_STRICT on`, err);
636
- throw err;
637
- }
638
- else {
639
- logger.warn(`Error thrown when proving AVM circuit but AVM_PROVING_STRICT is off. Faking AVM proof and carrying on. ${inspect(err)}.`);
640
- return {
641
- proof: makeEmptyRecursiveProof(AVM_PROOF_LENGTH_IN_FIELDS),
642
- verificationKey: VerificationKeyData.makeFake(AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS),
643
- };
644
- }
645
- }
646
- });
647
- this.deferredProving(provingState, doAvmProving, proofAndVk => {
648
- logger.debug(`Proven VM for tx index: ${txIndex}`);
649
- txProvingState.setAvmProof(proofAndVk);
650
- this.checkAndEnqueueNextTxCircuit(provingState, txIndex);
651
- });
652
- }
653
- checkAndEnqueueNextTxCircuit(provingState, txIndex) {
654
- const txProvingState = provingState.getTxProvingState(txIndex);
655
- if (!txProvingState.ready()) {
656
- return;
657
- }
658
- // We must have completed all proving (tube proof and (if required) vm proof are generated), we now move to the base rollup.
659
- logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`);
660
- this.enqueueBaseRollup(provingState, txIndex);
661
- }
662
- },
663
- (() => {
664
- const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
665
- _startNewBlock_decorators = [trackSpan('ProvingOrchestrator.startNewBlock', globalVariables => ({
666
- [Attributes.BLOCK_NUMBER]: globalVariables.blockNumber.toNumber(),
667
- }))];
668
- _addTxs_decorators = [trackSpan('ProvingOrchestrator.addTxs', txs => ({
669
- [Attributes.BLOCK_TXS_COUNT]: txs.length,
670
- }))];
671
- _startTubeCircuits_decorators = [trackSpan('ProvingOrchestrator.startTubeCircuits')];
672
- _setBlockCompleted_decorators = [trackSpan('ProvingOrchestrator.setBlockCompleted', (blockNumber) => ({
673
- [Attributes.BLOCK_NUMBER]: blockNumber,
674
- }))];
675
- _prepareBaseRollupInputs_decorators = [trackSpan('ProvingOrchestrator.prepareBaseRollupInputs', (_, tx) => ({
676
- [Attributes.TX_HASH]: tx.hash.toString(),
677
- }))];
678
- __esDecorate(_a, null, _startNewBlock_decorators, { kind: "method", name: "startNewBlock", static: false, private: false, access: { has: obj => "startNewBlock" in obj, get: obj => obj.startNewBlock }, metadata: _metadata }, null, _instanceExtraInitializers);
679
- __esDecorate(_a, null, _addTxs_decorators, { kind: "method", name: "addTxs", static: false, private: false, access: { has: obj => "addTxs" in obj, get: obj => obj.addTxs }, metadata: _metadata }, null, _instanceExtraInitializers);
680
- __esDecorate(_a, null, _startTubeCircuits_decorators, { kind: "method", name: "startTubeCircuits", static: false, private: false, access: { has: obj => "startTubeCircuits" in obj, get: obj => obj.startTubeCircuits }, metadata: _metadata }, null, _instanceExtraInitializers);
681
- __esDecorate(_a, null, _setBlockCompleted_decorators, { kind: "method", name: "setBlockCompleted", static: false, private: false, access: { has: obj => "setBlockCompleted" in obj, get: obj => obj.setBlockCompleted }, metadata: _metadata }, null, _instanceExtraInitializers);
682
- __esDecorate(_a, null, _prepareBaseRollupInputs_decorators, { kind: "method", name: "prepareBaseRollupInputs", static: false, private: false, access: { has: obj => "prepareBaseRollupInputs" in obj, get: obj => obj.prepareBaseRollupInputs }, metadata: _metadata }, null, _instanceExtraInitializers);
683
- if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
684
- })(),
685
- _a;
686
- })();
687
- export { ProvingOrchestrator };
688
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JjaGVzdHJhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL29yY2hlc3RyYXRvci9vcmNoZXN0cmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFDTCxPQUFPLEVBQ1AsWUFBWSxFQUlaLGVBQWUsR0FDaEIsTUFBTSxzQkFBc0IsQ0FBQztBQVE5QixPQUFPLEVBQ0wsMEJBQTBCLEVBQzFCLHFDQUFxQyxFQUVyQyxnQkFBZ0IsRUFFaEIsRUFBRSxFQUVGLDJCQUEyQixFQUMzQix3Q0FBd0MsRUFDeEMsbUNBQW1DLEVBQ25DLCtCQUErQixFQUUvQixtQkFBbUIsRUFDbkIsdUJBQXVCLEdBQ3hCLE1BQU0sb0JBQW9CLENBQUM7QUFDNUIsT0FBTyxFQUVMLDBCQUEwQixFQUMxQix1QkFBdUIsRUFDdkIsNkJBQTZCLEVBQzdCLFVBQVUsR0FDWCxNQUFNLDJCQUEyQixDQUFDO0FBQ25DLE9BQU8sRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDM0QsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUVsRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDeEUsT0FBTyxFQUNMLFVBQVUsRUFHVixrQkFBa0IsRUFDbEIsU0FBUyxFQUNULGtCQUFrQixHQUNuQixNQUFNLHlCQUF5QixDQUFDO0FBRWpDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFB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
302
+ logger.error(`Error thrown when proving job`, err);
303
+ provingState.reject(`${err}`);
304
+ } finally{
305
+ const index = this.pendingProvingJobs.indexOf(controller);
306
+ if (index > -1) {
307
+ this.pendingProvingJobs.splice(index, 1);
308
+ }
309
+ }
310
+ };
311
+ // let the callstack unwind before adding the job to the queue
312
+ setImmediate(()=>void safeJob());
313
+ }
314
+ async prepareBaseParityInputs(l1ToL2Messages, db) {
315
+ const l1ToL2MessagesPadded = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 'Too many L1 to L2 messages');
316
+ const baseParityInputs = times(NUM_BASE_PARITY_PER_ROOT_PARITY, (i)=>BaseParityInputs.fromSlice(l1ToL2MessagesPadded, i, getVKTreeRoot()));
317
+ const l1ToL2MessageSubtreeSiblingPath = assertLength(await getSubtreeSiblingPath(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, L1_TO_L2_MSG_SUBTREE_HEIGHT, db), L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH);
318
+ // Update the local trees to include the new l1 to l2 messages
319
+ await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
320
+ const l1ToL2MessageTreeSnapshotAfterInsertion = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, db);
321
+ return {
322
+ l1ToL2MessageSubtreeSiblingPath,
323
+ l1ToL2MessageTreeSnapshotAfterInsertion,
324
+ baseParityInputs
325
+ };
326
+ }
327
+ // Updates the merkle trees for a transaction. The first enqueued job for a transaction
328
+ async prepareBaseRollupInputs(provingState, tx) {
329
+ if (!provingState.verifyState() || !provingState.spongeBlobState) {
330
+ logger.debug('Not preparing base rollup inputs, state invalid');
331
+ return;
332
+ }
333
+ const db = this.dbs.get(provingState.blockNumber);
334
+ // We build the base rollup inputs using a mock proof and verification key.
335
+ // These will be overwritten later once we have proven the tube circuit and any public kernels
336
+ const [ms, hints] = await elapsed(buildBaseRollupHints(tx, provingState.globalVariables, db, provingState.spongeBlobState));
337
+ this.metrics.recordBaseRollupInputs(ms);
338
+ const promises = [
339
+ MerkleTreeId.NOTE_HASH_TREE,
340
+ MerkleTreeId.NULLIFIER_TREE,
341
+ MerkleTreeId.PUBLIC_DATA_TREE
342
+ ].map(async (id)=>{
343
+ return {
344
+ key: id,
345
+ value: await getTreeSnapshot(id, db)
346
+ };
347
+ });
348
+ const treeSnapshots = new Map((await Promise.all(promises)).map((obj)=>[
349
+ obj.key,
350
+ obj.value
351
+ ]));
352
+ if (!provingState.verifyState()) {
353
+ logger.debug(`Discarding proving job, state no longer valid`);
354
+ return;
355
+ }
356
+ return [
357
+ hints,
358
+ treeSnapshots
359
+ ];
360
+ }
361
+ // Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit
362
+ // Executes the next level of merge if all inputs are available
363
+ enqueueBaseRollup(provingState, txIndex) {
364
+ if (!provingState.verifyState()) {
365
+ logger.debug('Not running base rollup, state invalid');
366
+ return;
367
+ }
368
+ const txProvingState = provingState.getTxProvingState(txIndex);
369
+ const { processedTx } = txProvingState;
370
+ const { rollupType, inputs } = txProvingState.getBaseRollupTypeAndInputs();
371
+ logger.debug(`Enqueuing deferred proving base rollup for ${processedTx.hash.toString()}`);
372
+ this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, `ProvingOrchestrator.prover.${inputs instanceof PrivateBaseRollupInputs ? 'getPrivateBaseRollupProof' : 'getPublicBaseRollupProof'}`, {
373
+ [Attributes.TX_HASH]: processedTx.hash.toString(),
374
+ [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
375
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType
376
+ }, (signal)=>{
377
+ if (inputs instanceof PrivateBaseRollupInputs) {
378
+ return this.prover.getPrivateBaseRollupProof(inputs, signal, provingState.epochNumber);
379
+ } else {
380
+ return this.prover.getPublicBaseRollupProof(inputs, signal, provingState.epochNumber);
381
+ }
382
+ }), async (result)=>{
383
+ logger.debug(`Completed proof for ${rollupType} for tx ${processedTx.hash.toString()}`);
384
+ validatePartialState(result.inputs.end, txProvingState.treeSnapshots);
385
+ const leafLocation = provingState.setBaseRollupProof(txIndex, result);
386
+ if (provingState.totalNumTxs === 1) {
387
+ await this.checkAndEnqueueBlockRootRollup(provingState);
388
+ } else {
389
+ await this.checkAndEnqueueNextMergeRollup(provingState, leafLocation);
390
+ }
391
+ });
392
+ }
393
+ // Enqueues the tube circuit for a given transaction index, or reuses the one already enqueued
394
+ // Once completed, will enqueue the next circuit, either a public kernel or the base rollup
395
+ getOrEnqueueTube(provingState, txIndex) {
396
+ if (!provingState.verifyState()) {
397
+ logger.debug('Not running tube circuit, state invalid');
398
+ return;
399
+ }
400
+ const txProvingState = provingState.getTxProvingState(txIndex);
401
+ const txHash = txProvingState.processedTx.hash.toString();
402
+ const handleResult = (result)=>{
403
+ logger.debug(`Got tube proof for tx index: ${txIndex}`, {
404
+ txHash
405
+ });
406
+ txProvingState.setTubeProof(result);
407
+ this.provingState?.cachedTubeProofs.delete(txHash);
408
+ this.checkAndEnqueueNextTxCircuit(provingState, txIndex);
409
+ };
410
+ if (this.provingState?.cachedTubeProofs.has(txHash)) {
411
+ logger.debug(`Tube proof already enqueued for tx index: ${txIndex}`, {
412
+ txHash
413
+ });
414
+ void this.provingState.cachedTubeProofs.get(txHash).then(handleResult);
415
+ return;
416
+ }
417
+ logger.debug(`Enqueuing tube circuit for tx index: ${txIndex}`);
418
+ this.doEnqueueTube(txHash, txProvingState.getTubeInputs(), handleResult);
419
+ }
420
+ doEnqueueTube(txHash, inputs, handler, provingState = this.provingState) {
421
+ if (!provingState?.verifyState()) {
422
+ logger.debug('Not running tube circuit, state invalid');
423
+ return;
424
+ }
425
+ this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getTubeProof', {
426
+ [Attributes.TX_HASH]: txHash,
427
+ [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
428
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'tube-circuit'
429
+ }, (signal)=>this.prover.getTubeProof(inputs, signal, this.provingState.epochNumber)), handler);
430
+ }
431
+ // Executes the merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit
432
+ // Enqueues the next level of merge if all inputs are available
433
+ enqueueMergeRollup(provingState, location) {
434
+ if (!provingState.verifyState()) {
435
+ logger.debug('Not running merge rollup. State no longer valid.');
436
+ return;
437
+ }
438
+ const inputs = provingState.getMergeRollupInputs(location);
439
+ this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getMergeRollupProof', {
440
+ [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
441
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'merge-rollup'
442
+ }, (signal)=>this.prover.getMergeRollupProof(inputs, signal, provingState.epochNumber)), async (result)=>{
443
+ provingState.setMergeRollupProof(location, result);
444
+ await this.checkAndEnqueueNextMergeRollup(provingState, location);
445
+ });
446
+ }
447
+ // Executes the block root rollup circuit
448
+ async enqueueBlockRootRollup(provingState) {
449
+ if (!provingState.verifyState()) {
450
+ logger.debug('Not running block root rollup, state no longer valid');
451
+ return;
452
+ }
453
+ provingState.blockRootRollupStarted = true;
454
+ const { rollupType, inputs } = await provingState.getBlockRootRollupTypeAndInputs(this.proverId);
455
+ logger.debug(`Enqueuing ${rollupType} for block ${provingState.blockNumber} with ${provingState.newL1ToL2Messages.length} l1 to l2 msgs.`);
456
+ this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBlockRootRollupProof', {
457
+ [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
458
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: rollupType
459
+ }, (signal)=>{
460
+ if (inputs instanceof EmptyBlockRootRollupInputs) {
461
+ return this.prover.getEmptyBlockRootRollupProof(inputs, signal, provingState.epochNumber);
462
+ } else if (inputs instanceof SingleTxBlockRootRollupInputs) {
463
+ return this.prover.getSingleTxBlockRootRollupProof(inputs, signal, provingState.epochNumber);
464
+ } else {
465
+ return this.prover.getBlockRootRollupProof(inputs, signal, provingState.epochNumber);
466
+ }
467
+ }), async (result)=>{
468
+ provingState.setBlockRootRollupProof(result);
469
+ const header = await provingState.buildHeaderFromProvingOutputs(logger);
470
+ if (!(await header.hash()).equals(await provingState.block.header.hash())) {
471
+ logger.error(`Block header mismatch\nCircuit:${inspect(header)}\nComputed:${inspect(provingState.block.header)}`);
472
+ provingState.reject(`Block header hash mismatch`);
473
+ }
474
+ logger.debug(`Completed ${rollupType} proof for block ${provingState.block.number}`);
475
+ // validatePartialState(result.inputs.end, tx.treeSnapshots); // TODO(palla/prover)
476
+ const epochProvingState = this.provingState;
477
+ const leafLocation = epochProvingState.setBlockRootRollupProof(provingState.index, result);
478
+ if (epochProvingState.totalNumBlocks === 1) {
479
+ await this.enqueueEpochPadding(epochProvingState);
480
+ } else {
481
+ this.checkAndEnqueueNextBlockMergeRollup(epochProvingState, leafLocation);
482
+ }
483
+ });
484
+ }
485
+ // Executes the base parity circuit and stores the intermediate state for the root parity circuit
486
+ // Enqueues the root parity circuit if all inputs are available
487
+ enqueueBaseParityCircuit(provingState, inputs, index) {
488
+ if (!provingState.verifyState()) {
489
+ logger.debug('Not running base parity. State no longer valid.');
490
+ return;
491
+ }
492
+ this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBaseParityProof', {
493
+ [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
494
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'base-parity'
495
+ }, (signal)=>this.prover.getBaseParityProof(inputs, signal, provingState.epochNumber)), (provingOutput)=>{
496
+ provingState.setBaseParityProof(index, provingOutput);
497
+ this.checkAndEnqueueRootParityCircuit(provingState);
498
+ });
499
+ }
500
+ checkAndEnqueueRootParityCircuit(provingState) {
501
+ if (!provingState.isReadyForRootParity()) {
502
+ return;
503
+ }
504
+ this.enqueueRootParityCircuit(provingState);
505
+ }
506
+ // Runs the root parity circuit ans stored the outputs
507
+ // Enqueues the root rollup proof if all inputs are available
508
+ enqueueRootParityCircuit(provingState) {
509
+ if (!provingState.verifyState()) {
510
+ logger.debug('Not running root parity. State no longer valid.');
511
+ return;
512
+ }
513
+ const inputs = provingState.getRootParityInputs();
514
+ this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getRootParityProof', {
515
+ [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
516
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-parity'
517
+ }, (signal)=>this.prover.getRootParityProof(inputs, signal, provingState.epochNumber)), async (result)=>{
518
+ provingState.setRootParityProof(result);
519
+ await this.checkAndEnqueueBlockRootRollup(provingState);
520
+ });
521
+ }
522
+ // Executes the block merge rollup circuit and stored the output as intermediate state for the parent merge/block root circuit
523
+ // Enqueues the next level of merge if all inputs are available
524
+ enqueueBlockMergeRollup(provingState, location) {
525
+ if (!provingState.verifyState()) {
526
+ logger.debug('Not running block merge rollup. State no longer valid.');
527
+ return;
528
+ }
529
+ const inputs = provingState.getBlockMergeRollupInputs(location);
530
+ this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getBlockMergeRollupProof', {
531
+ [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
532
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'block-merge-rollup'
533
+ }, (signal)=>this.prover.getBlockMergeRollupProof(inputs, signal, provingState.epochNumber)), (result)=>{
534
+ provingState.setBlockMergeRollupProof(location, result);
535
+ this.checkAndEnqueueNextBlockMergeRollup(provingState, location);
536
+ });
537
+ }
538
+ async enqueueEpochPadding(provingState) {
539
+ if (!provingState.verifyState()) {
540
+ logger.debug('Not running epoch padding. State no longer valid.');
541
+ return;
542
+ }
543
+ logger.debug('Padding epoch proof with an empty block root proof.');
544
+ const inputs = await provingState.getPaddingBlockRootInputs(this.proverId);
545
+ this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getEmptyBlockRootRollupProof', {
546
+ [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
547
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'empty-block-root-rollup'
548
+ }, (signal)=>this.prover.getEmptyBlockRootRollupProof(inputs, signal, provingState.epochNumber)), (result)=>{
549
+ logger.debug('Completed proof for padding block root.');
550
+ provingState.setPaddingBlockRootProof(result);
551
+ this.checkAndEnqueueRootRollup(provingState);
552
+ });
553
+ }
554
+ // Executes the root rollup circuit
555
+ enqueueRootRollup(provingState) {
556
+ if (!provingState.verifyState()) {
557
+ logger.debug('Not running root rollup, state no longer valid');
558
+ return;
559
+ }
560
+ logger.debug(`Preparing root rollup`);
561
+ const inputs = provingState.getRootRollupInputs(this.proverId);
562
+ this.deferredProving(provingState, wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getRootRollupProof', {
563
+ [Attributes.PROTOCOL_CIRCUIT_TYPE]: 'server',
564
+ [Attributes.PROTOCOL_CIRCUIT_NAME]: 'root-rollup'
565
+ }, (signal)=>this.prover.getRootRollupProof(inputs, signal, provingState.epochNumber)), (result)=>{
566
+ logger.verbose(`Orchestrator completed root rollup for epoch ${provingState.epochNumber}`);
567
+ provingState.setRootRollupProof(result);
568
+ provingState.resolve({
569
+ status: 'success'
570
+ });
571
+ });
572
+ }
573
+ async checkAndEnqueueNextMergeRollup(provingState, currentLocation) {
574
+ if (!provingState.isReadyForMergeRollup(currentLocation)) {
575
+ return;
576
+ }
577
+ const parentLocation = provingState.getParentLocation(currentLocation);
578
+ if (parentLocation.level === 0) {
579
+ await this.checkAndEnqueueBlockRootRollup(provingState);
580
+ } else {
581
+ this.enqueueMergeRollup(provingState, parentLocation);
582
+ }
583
+ }
584
+ async checkAndEnqueueBlockRootRollup(provingState) {
585
+ if (!provingState.isReadyForBlockRootRollup()) {
586
+ logger.debug('Not ready for root rollup');
587
+ return;
588
+ }
589
+ if (provingState.blockRootRollupStarted) {
590
+ logger.debug('Block root rollup already started');
591
+ return;
592
+ }
593
+ const blockNumber = provingState.blockNumber;
594
+ // TODO(palla/prover): This closes the fork only on the happy path. If this epoch orchestrator
595
+ // is aborted and never reaches this point, it will leak the fork. We need to add a global cleanup,
596
+ // but have to make sure it only runs once all operations are completed, otherwise some function here
597
+ // will attempt to access the fork after it was closed.
598
+ logger.debug(`Cleaning up world state fork for ${blockNumber}`);
599
+ void this.dbs.get(blockNumber)?.close().then(()=>this.dbs.delete(blockNumber)).catch((err)=>logger.error(`Error closing db for block ${blockNumber}`, err));
600
+ await this.enqueueBlockRootRollup(provingState);
601
+ }
602
+ checkAndEnqueueNextBlockMergeRollup(provingState, currentLocation) {
603
+ if (!provingState.isReadyForBlockMerge(currentLocation)) {
604
+ return;
605
+ }
606
+ const parentLocation = provingState.getParentLocation(currentLocation);
607
+ if (parentLocation.level === 0) {
608
+ this.checkAndEnqueueRootRollup(provingState);
609
+ } else {
610
+ this.enqueueBlockMergeRollup(provingState, parentLocation);
611
+ }
612
+ }
613
+ checkAndEnqueueRootRollup(provingState) {
614
+ if (!provingState.isReadyForRootRollup()) {
615
+ logger.debug('Not ready for root rollup');
616
+ return;
617
+ }
618
+ this.enqueueRootRollup(provingState);
619
+ }
620
+ /**
621
+ * Executes the VM circuit for a public function, will enqueue the corresponding kernel if the
622
+ * previous kernel is ready
623
+ * @param provingState - The proving state being operated on
624
+ * @param txIndex - The index of the transaction being proven
625
+ */ enqueueVM(provingState, txIndex) {
626
+ if (!provingState.verifyState()) {
627
+ logger.debug(`Not running VM circuit as state is no longer valid`);
628
+ return;
629
+ }
630
+ const txProvingState = provingState.getTxProvingState(txIndex);
631
+ // This function tries to do AVM proving. If there is a failure, it fakes the proof unless AVM_PROVING_STRICT is defined.
632
+ // Nothing downstream depends on the AVM proof yet. So having this mode lets us incrementally build the AVM circuit.
633
+ const doAvmProving = wrapCallbackInSpan(this.tracer, 'ProvingOrchestrator.prover.getAvmProof', {
634
+ [Attributes.TX_HASH]: txProvingState.processedTx.hash.toString()
635
+ }, async (signal)=>{
636
+ const inputs = txProvingState.getAvmInputs();
637
+ try {
638
+ return await this.prover.getAvmProof(inputs, signal, provingState.epochNumber);
639
+ } catch (err) {
640
+ if (process.env.AVM_PROVING_STRICT) {
641
+ logger.error(`Error thrown when proving AVM circuit with AVM_PROVING_STRICT on`, err);
642
+ throw err;
643
+ } else {
644
+ logger.warn(`Error thrown when proving AVM circuit but AVM_PROVING_STRICT is off. Faking AVM proof and carrying on. ${inspect(err)}.`);
645
+ return {
646
+ proof: makeEmptyRecursiveProof(AVM_PROOF_LENGTH_IN_FIELDS),
647
+ verificationKey: VerificationKeyData.makeFake(AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS)
648
+ };
649
+ }
650
+ }
651
+ });
652
+ this.deferredProving(provingState, doAvmProving, (proofAndVk)=>{
653
+ logger.debug(`Proven VM for tx index: ${txIndex}`);
654
+ txProvingState.setAvmProof(proofAndVk);
655
+ this.checkAndEnqueueNextTxCircuit(provingState, txIndex);
656
+ });
657
+ }
658
+ checkAndEnqueueNextTxCircuit(provingState, txIndex) {
659
+ const txProvingState = provingState.getTxProvingState(txIndex);
660
+ if (!txProvingState.ready()) {
661
+ return;
662
+ }
663
+ // We must have completed all proving (tube proof and (if required) vm proof are generated), we now move to the base rollup.
664
+ logger.debug(`Public functions completed for tx ${txIndex} enqueueing base rollup`);
665
+ this.enqueueBaseRollup(provingState, txIndex);
666
+ }
667
+ }
668
+ _ts_decorate([
669
+ trackSpan('ProvingOrchestrator.startNewBlock', (globalVariables)=>({
670
+ [Attributes.BLOCK_NUMBER]: globalVariables.blockNumber.toNumber()
671
+ }))
672
+ ], ProvingOrchestrator.prototype, "startNewBlock", null);
673
+ _ts_decorate([
674
+ trackSpan('ProvingOrchestrator.addTxs', (txs)=>({
675
+ [Attributes.BLOCK_TXS_COUNT]: txs.length
676
+ }))
677
+ ], ProvingOrchestrator.prototype, "addTxs", null);
678
+ _ts_decorate([
679
+ trackSpan('ProvingOrchestrator.startTubeCircuits')
680
+ ], ProvingOrchestrator.prototype, "startTubeCircuits", null);
681
+ _ts_decorate([
682
+ trackSpan('ProvingOrchestrator.setBlockCompleted', (blockNumber)=>({
683
+ [Attributes.BLOCK_NUMBER]: blockNumber
684
+ }))
685
+ ], ProvingOrchestrator.prototype, "setBlockCompleted", null);
686
+ _ts_decorate([
687
+ trackSpan('ProvingOrchestrator.prepareBaseRollupInputs', (_, tx)=>({
688
+ [Attributes.TX_HASH]: tx.hash.toString()
689
+ }))
690
+ ], ProvingOrchestrator.prototype, "prepareBaseRollupInputs", null);