@aztec/prover-client 0.75.0-commit.c03ba01a2a4122e43e90d5133ba017e54b90e9d2 → 0.76.0

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