@aztec/prover-client 3.0.0-canary.a9708bd → 3.0.0-devnet.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/block-factory/light.d.ts +5 -3
- package/dest/block-factory/light.d.ts.map +1 -1
- package/dest/block-factory/light.js +16 -9
- package/dest/mocks/fixtures.d.ts +4 -1
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +31 -3
- package/dest/mocks/test_context.d.ts +32 -9
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +78 -22
- package/dest/orchestrator/block-building-helpers.d.ts +33 -31
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
- package/dest/orchestrator/block-building-helpers.js +126 -137
- package/dest/orchestrator/block-proving-state.d.ts +60 -53
- package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/block-proving-state.js +214 -187
- package/dest/orchestrator/checkpoint-proving-state.d.ts +63 -0
- package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -0
- package/dest/orchestrator/checkpoint-proving-state.js +211 -0
- package/dest/orchestrator/epoch-proving-state.d.ts +34 -28
- package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/epoch-proving-state.js +125 -81
- package/dest/orchestrator/orchestrator.d.ts +26 -25
- package/dest/orchestrator/orchestrator.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator.js +350 -218
- package/dest/orchestrator/tx-proving-state.d.ts +11 -9
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/tx-proving-state.js +26 -23
- package/dest/prover-client/server-epoch-prover.d.ts +8 -7
- package/dest/prover-client/server-epoch-prover.d.ts.map +1 -1
- package/dest/prover-client/server-epoch-prover.js +7 -7
- package/dest/proving_broker/broker_prover_facade.d.ts +20 -15
- package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
- package/dest/proving_broker/broker_prover_facade.js +36 -21
- package/dest/proving_broker/config.d.ts +8 -8
- package/dest/proving_broker/config.js +5 -5
- package/dest/proving_broker/factory.js +1 -1
- package/dest/proving_broker/fixtures.js +1 -1
- package/dest/proving_broker/proof_store/index.d.ts +1 -0
- package/dest/proving_broker/proof_store/index.d.ts.map +1 -1
- package/dest/proving_broker/proof_store/index.js +1 -0
- package/dest/proving_broker/proving_broker.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker.js +29 -18
- package/dest/proving_broker/proving_broker_database/persisted.js +5 -5
- package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
- package/dest/proving_broker/proving_job_controller.js +38 -18
- package/dest/test/mock_prover.d.ts +22 -17
- package/dest/test/mock_prover.d.ts.map +1 -1
- package/dest/test/mock_prover.js +35 -20
- package/package.json +16 -17
- package/src/block-factory/light.ts +35 -9
- package/src/mocks/fixtures.ts +39 -11
- package/src/mocks/test_context.ts +137 -31
- package/src/orchestrator/block-building-helpers.ts +213 -211
- package/src/orchestrator/block-proving-state.ts +235 -245
- package/src/orchestrator/checkpoint-proving-state.ts +299 -0
- package/src/orchestrator/epoch-proving-state.ts +169 -126
- package/src/orchestrator/orchestrator.ts +519 -286
- package/src/orchestrator/tx-proving-state.ts +45 -43
- package/src/prover-client/server-epoch-prover.ts +26 -16
- package/src/proving_broker/broker_prover_facade.ts +157 -88
- package/src/proving_broker/config.ts +7 -7
- package/src/proving_broker/factory.ts +1 -1
- package/src/proving_broker/fixtures.ts +1 -1
- package/src/proving_broker/proof_store/index.ts +1 -0
- package/src/proving_broker/proving_broker.ts +36 -18
- package/src/proving_broker/proving_broker_database/persisted.ts +5 -5
- package/src/proving_broker/proving_job_controller.ts +38 -18
- package/src/test/mock_prover.ts +142 -62
- package/dest/bin/get-proof-inputs.d.ts +0 -2
- package/dest/bin/get-proof-inputs.d.ts.map +0 -1
- package/dest/bin/get-proof-inputs.js +0 -51
- package/src/bin/get-proof-inputs.ts +0 -59
|
@@ -1,35 +1,44 @@
|
|
|
1
1
|
import type { BBProverConfig } from '@aztec/bb-prover';
|
|
2
|
+
import { TestCircuitProver } from '@aztec/bb-prover';
|
|
3
|
+
import { SpongeBlob } from '@aztec/blob-lib';
|
|
2
4
|
import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
3
5
|
import { padArrayEnd, times, timesParallel } from '@aztec/foundation/collection';
|
|
4
6
|
import { Fr } from '@aztec/foundation/fields';
|
|
5
7
|
import type { Logger } from '@aztec/foundation/log';
|
|
6
8
|
import { TestDateProvider } from '@aztec/foundation/timer';
|
|
9
|
+
import type { FieldsOf } from '@aztec/foundation/types';
|
|
7
10
|
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
8
|
-
import {
|
|
11
|
+
import { ProtocolContractsList } from '@aztec/protocol-contracts';
|
|
9
12
|
import { computeFeePayerBalanceLeafSlot } from '@aztec/protocol-contracts/fee-juice';
|
|
10
13
|
import { SimpleContractDataSource } from '@aztec/simulator/public/fixtures';
|
|
11
14
|
import { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
12
15
|
import { PublicDataWrite } from '@aztec/stdlib/avm';
|
|
13
16
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
14
|
-
import { EthAddress
|
|
17
|
+
import { EthAddress } from '@aztec/stdlib/block';
|
|
18
|
+
import { getCheckpointBlobFields } from '@aztec/stdlib/checkpoint';
|
|
15
19
|
import type { ServerCircuitProver } from '@aztec/stdlib/interfaces/server';
|
|
20
|
+
import type { CheckpointConstantData } from '@aztec/stdlib/rollup';
|
|
16
21
|
import { makeBloatedProcessedTx } from '@aztec/stdlib/testing';
|
|
17
|
-
import {
|
|
22
|
+
import { MerkleTreeId, PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
18
23
|
import { type BlockHeader, type GlobalVariables, type ProcessedTx, TreeSnapshots, type Tx } from '@aztec/stdlib/tx';
|
|
19
24
|
import type { MerkleTreeAdminDatabase } from '@aztec/world-state';
|
|
20
25
|
import { NativeWorldStateService } from '@aztec/world-state/native';
|
|
21
26
|
|
|
22
27
|
import { promises as fs } from 'fs';
|
|
23
28
|
|
|
24
|
-
// TODO(#12613) This means of sharing test code is not ideal.
|
|
25
|
-
// eslint-disable-next-line import/no-relative-packages
|
|
26
|
-
import { TestCircuitProver } from '../../../bb-prover/src/test/test_circuit_prover.js';
|
|
27
29
|
import { buildBlockWithCleanDB } from '../block-factory/light.js';
|
|
28
30
|
import { getTreeSnapshot } from '../orchestrator/block-building-helpers.js';
|
|
31
|
+
import type { BlockProvingState } from '../orchestrator/block-proving-state.js';
|
|
29
32
|
import { ProvingOrchestrator } from '../orchestrator/index.js';
|
|
30
33
|
import { BrokerCircuitProverFacade } from '../proving_broker/broker_prover_facade.js';
|
|
31
34
|
import { TestBroker } from '../test/mock_prover.js';
|
|
32
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
getEnvironmentConfig,
|
|
37
|
+
getSimulator,
|
|
38
|
+
makeCheckpointConstants,
|
|
39
|
+
makeGlobals,
|
|
40
|
+
updateExpectedTreesFromTxs,
|
|
41
|
+
} from './fixtures.js';
|
|
33
42
|
|
|
34
43
|
export class TestContext {
|
|
35
44
|
private headers: Map<number, BlockHeader> = new Map();
|
|
@@ -37,6 +46,7 @@ export class TestContext {
|
|
|
37
46
|
|
|
38
47
|
constructor(
|
|
39
48
|
public worldState: MerkleTreeAdminDatabase,
|
|
49
|
+
public firstCheckpointNumber: Fr,
|
|
40
50
|
public globalVariables: GlobalVariables,
|
|
41
51
|
public prover: ServerCircuitProver,
|
|
42
52
|
public broker: TestBroker,
|
|
@@ -55,20 +65,27 @@ export class TestContext {
|
|
|
55
65
|
return this.orchestrator;
|
|
56
66
|
}
|
|
57
67
|
|
|
68
|
+
public getCheckpointConstants(checkpointIndex = 0): CheckpointConstantData {
|
|
69
|
+
return makeCheckpointConstants(this.firstCheckpointNumber.toNumber() + checkpointIndex);
|
|
70
|
+
}
|
|
71
|
+
|
|
58
72
|
static async new(
|
|
59
73
|
logger: Logger,
|
|
60
74
|
{
|
|
61
75
|
proverCount = 4,
|
|
62
76
|
createProver = async (bbConfig: BBProverConfig) => new TestCircuitProver(await getSimulator(bbConfig, logger)),
|
|
77
|
+
slotNumber = 1,
|
|
63
78
|
blockNumber = 1,
|
|
64
79
|
}: {
|
|
65
80
|
proverCount?: number;
|
|
66
81
|
createProver?: (bbConfig: BBProverConfig) => Promise<ServerCircuitProver>;
|
|
82
|
+
slotNumber?: number;
|
|
67
83
|
blockNumber?: number;
|
|
68
84
|
} = {},
|
|
69
85
|
) {
|
|
70
86
|
const directoriesToCleanup: string[] = [];
|
|
71
|
-
const
|
|
87
|
+
const firstCheckpointNumber = new Fr(slotNumber);
|
|
88
|
+
const globalVariables = makeGlobals(blockNumber, slotNumber);
|
|
72
89
|
|
|
73
90
|
const feePayer = AztecAddress.fromNumber(42222);
|
|
74
91
|
const initialFeePayerBalance = new Fr(10n ** 20n);
|
|
@@ -112,6 +129,7 @@ export class TestContext {
|
|
|
112
129
|
|
|
113
130
|
return new this(
|
|
114
131
|
ws,
|
|
132
|
+
firstCheckpointNumber,
|
|
115
133
|
globalVariables,
|
|
116
134
|
localProver,
|
|
117
135
|
broker,
|
|
@@ -131,14 +149,10 @@ export class TestContext {
|
|
|
131
149
|
|
|
132
150
|
public getBlockHeader(blockNumber: 0): BlockHeader;
|
|
133
151
|
public getBlockHeader(blockNumber: number): BlockHeader | undefined;
|
|
134
|
-
public getBlockHeader(blockNumber = 0) {
|
|
152
|
+
public getBlockHeader(blockNumber = 0): BlockHeader | undefined {
|
|
135
153
|
return blockNumber === 0 ? this.worldState.getCommitted().getInitialHeader() : this.headers.get(blockNumber);
|
|
136
154
|
}
|
|
137
155
|
|
|
138
|
-
public setBlockHeader(header: BlockHeader, blockNumber: number) {
|
|
139
|
-
this.headers.set(blockNumber, header);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
156
|
public getPreviousBlockHeader(currentBlockNumber = this.blockNumber): BlockHeader {
|
|
143
157
|
return this.getBlockHeader(currentBlockNumber - 1)!;
|
|
144
158
|
}
|
|
@@ -155,14 +169,15 @@ export class TestContext {
|
|
|
155
169
|
}
|
|
156
170
|
}
|
|
157
171
|
|
|
158
|
-
|
|
159
|
-
const
|
|
160
|
-
const
|
|
172
|
+
async makeProcessedTx(opts?: Parameters<typeof makeBloatedProcessedTx>[0]): Promise<ProcessedTx> {
|
|
173
|
+
const globalVariables = opts?.globalVariables ?? this.globalVariables;
|
|
174
|
+
const blockNumber = globalVariables.blockNumber;
|
|
175
|
+
const header = opts?.header ?? this.getBlockHeader(blockNumber - 1);
|
|
161
176
|
const tx = await makeBloatedProcessedTx({
|
|
162
177
|
header,
|
|
163
178
|
vkTreeRoot: getVKTreeRoot(),
|
|
164
|
-
|
|
165
|
-
globalVariables
|
|
179
|
+
protocolContracts: ProtocolContractsList,
|
|
180
|
+
globalVariables,
|
|
166
181
|
feePayer: this.feePayer,
|
|
167
182
|
...opts,
|
|
168
183
|
});
|
|
@@ -177,18 +192,27 @@ export class TestContext {
|
|
|
177
192
|
/** Creates a block with the given number of txs and adds it to world-state */
|
|
178
193
|
public async makePendingBlock(
|
|
179
194
|
numTxs: number,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
195
|
+
{
|
|
196
|
+
checkpointIndex = 0,
|
|
197
|
+
numL1ToL2Messages = 0,
|
|
198
|
+
blockNumber = this.blockNumber,
|
|
199
|
+
makeProcessedTxOpts = () => ({}),
|
|
200
|
+
}: {
|
|
201
|
+
checkpointIndex?: number;
|
|
202
|
+
numL1ToL2Messages?: number;
|
|
203
|
+
blockNumber?: number;
|
|
204
|
+
makeProcessedTxOpts?: (index: number) => Partial<Parameters<typeof makeBloatedProcessedTx>[0]>;
|
|
205
|
+
} = {},
|
|
183
206
|
) {
|
|
184
|
-
const
|
|
207
|
+
const slotNumber = this.firstCheckpointNumber.toNumber() + checkpointIndex;
|
|
208
|
+
const globalVariables = makeGlobals(blockNumber, slotNumber);
|
|
185
209
|
const blockNum = globalVariables.blockNumber;
|
|
186
210
|
const db = await this.worldState.fork();
|
|
187
211
|
const l1ToL2Messages = times(numL1ToL2Messages, i => new Fr(blockNum * 100 + i));
|
|
188
212
|
const merkleTrees = await this.worldState.fork();
|
|
189
213
|
await merkleTrees.appendLeaves(
|
|
190
214
|
MerkleTreeId.L1_TO_L2_MESSAGE_TREE,
|
|
191
|
-
padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
|
|
215
|
+
padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
|
|
192
216
|
);
|
|
193
217
|
const newL1ToL2Snapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, merkleTrees);
|
|
194
218
|
const txs = await timesParallel(numTxs, i =>
|
|
@@ -202,11 +226,93 @@ export class TestContext {
|
|
|
202
226
|
await this.setTreeRoots(txs);
|
|
203
227
|
|
|
204
228
|
const block = await buildBlockWithCleanDB(txs, globalVariables, l1ToL2Messages, db);
|
|
205
|
-
this.headers.set(blockNum, block.
|
|
229
|
+
this.headers.set(blockNum, block.getBlockHeader());
|
|
206
230
|
await this.worldState.handleL2BlockAndMessages(block, l1ToL2Messages);
|
|
207
231
|
return { block, txs, l1ToL2Messages };
|
|
208
232
|
}
|
|
209
233
|
|
|
234
|
+
public async makePendingBlocksInCheckpoint(
|
|
235
|
+
numBlocks: number,
|
|
236
|
+
{
|
|
237
|
+
checkpointIndex = 0,
|
|
238
|
+
numTxsPerBlock = 1,
|
|
239
|
+
numL1ToL2Messages = 0,
|
|
240
|
+
firstBlockNumber = this.blockNumber + checkpointIndex * numBlocks,
|
|
241
|
+
makeGlobalVariablesOpts = () => ({}),
|
|
242
|
+
makeProcessedTxOpts = () => ({}),
|
|
243
|
+
}: {
|
|
244
|
+
checkpointIndex?: number;
|
|
245
|
+
numTxsPerBlock?: number | number[];
|
|
246
|
+
numL1ToL2Messages?: number;
|
|
247
|
+
firstBlockNumber?: number;
|
|
248
|
+
makeGlobalVariablesOpts?: (
|
|
249
|
+
blockNumber: number,
|
|
250
|
+
checkpointIndex: number,
|
|
251
|
+
) => Partial<FieldsOf<GlobalVariables> & FieldsOf<CheckpointConstantData>>;
|
|
252
|
+
makeProcessedTxOpts?: (
|
|
253
|
+
blockGlobalVariables: GlobalVariables,
|
|
254
|
+
txIndex: number,
|
|
255
|
+
) => Partial<Parameters<typeof makeBloatedProcessedTx>[0]>;
|
|
256
|
+
} = {},
|
|
257
|
+
) {
|
|
258
|
+
const slotNumber = this.firstCheckpointNumber.toNumber() + checkpointIndex;
|
|
259
|
+
const l1ToL2Messages = times(numL1ToL2Messages, i => new Fr(slotNumber * 100 + i));
|
|
260
|
+
const merkleTrees = await this.worldState.fork();
|
|
261
|
+
await merkleTrees.appendLeaves(
|
|
262
|
+
MerkleTreeId.L1_TO_L2_MESSAGE_TREE,
|
|
263
|
+
padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
|
|
264
|
+
);
|
|
265
|
+
const newL1ToL2Snapshot = await getTreeSnapshot(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, merkleTrees);
|
|
266
|
+
|
|
267
|
+
const blockGlobalVariables = times(numBlocks, i =>
|
|
268
|
+
makeGlobals(firstBlockNumber + i, slotNumber, makeGlobalVariablesOpts(firstBlockNumber + i, checkpointIndex)),
|
|
269
|
+
);
|
|
270
|
+
let totalTxs = 0;
|
|
271
|
+
const blockTxs = await timesParallel(numBlocks, blockIndex => {
|
|
272
|
+
const txIndexOffset = totalTxs;
|
|
273
|
+
const numTxs = typeof numTxsPerBlock === 'number' ? numTxsPerBlock : numTxsPerBlock[blockIndex];
|
|
274
|
+
totalTxs += numTxs;
|
|
275
|
+
return timesParallel(numTxs, txIndex =>
|
|
276
|
+
this.makeProcessedTx({
|
|
277
|
+
seed: (txIndexOffset + txIndex + 1) * 321 + (checkpointIndex + 1) * 123456,
|
|
278
|
+
globalVariables: blockGlobalVariables[blockIndex],
|
|
279
|
+
header: this.getBlockHeader(firstBlockNumber - 1),
|
|
280
|
+
newL1ToL2Snapshot,
|
|
281
|
+
...makeProcessedTxOpts(blockGlobalVariables[blockIndex], txIndexOffset + txIndex),
|
|
282
|
+
}),
|
|
283
|
+
);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const blobFields = getCheckpointBlobFields(blockTxs.map(txs => txs.map(tx => tx.txEffect)));
|
|
287
|
+
const spongeBlobState = await SpongeBlob.init(blobFields.length);
|
|
288
|
+
|
|
289
|
+
const blocks: { header: BlockHeader; txs: ProcessedTx[] }[] = [];
|
|
290
|
+
for (let i = 0; i < numBlocks; i++) {
|
|
291
|
+
const isFirstBlock = i === 0;
|
|
292
|
+
const blockNumber = firstBlockNumber + i;
|
|
293
|
+
const globalVariables = blockGlobalVariables[i];
|
|
294
|
+
const txs = blockTxs[i];
|
|
295
|
+
|
|
296
|
+
await this.setTreeRoots(txs);
|
|
297
|
+
|
|
298
|
+
const fork = await this.worldState.fork();
|
|
299
|
+
const blockMsgs = isFirstBlock ? l1ToL2Messages : [];
|
|
300
|
+
const block = await buildBlockWithCleanDB(txs, globalVariables, blockMsgs, fork, spongeBlobState, isFirstBlock);
|
|
301
|
+
|
|
302
|
+
const header = block.getBlockHeader();
|
|
303
|
+
this.headers.set(blockNumber, header);
|
|
304
|
+
|
|
305
|
+
await this.worldState.handleL2BlockAndMessages(block, blockMsgs, isFirstBlock);
|
|
306
|
+
|
|
307
|
+
const blockBlobFields = block.body.toBlobFields();
|
|
308
|
+
await spongeBlobState.absorb(blockBlobFields);
|
|
309
|
+
|
|
310
|
+
blocks.push({ header, txs });
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return { blocks, l1ToL2Messages, blobFields };
|
|
314
|
+
}
|
|
315
|
+
|
|
210
316
|
public async processPublicFunctions(
|
|
211
317
|
txs: Tx[],
|
|
212
318
|
{
|
|
@@ -223,14 +329,17 @@ export class TestContext {
|
|
|
223
329
|
const merkleTrees = await this.worldState.fork();
|
|
224
330
|
await merkleTrees.appendLeaves(
|
|
225
331
|
MerkleTreeId.L1_TO_L2_MESSAGE_TREE,
|
|
226
|
-
padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
|
|
332
|
+
padArrayEnd<Fr, number>(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP),
|
|
227
333
|
);
|
|
228
334
|
|
|
229
335
|
const processorFactory = new PublicProcessorFactory(
|
|
230
336
|
contractDataSource ?? new SimpleContractDataSource(),
|
|
231
337
|
new TestDateProvider(),
|
|
232
338
|
);
|
|
233
|
-
const publicProcessor = processorFactory.create(merkleTrees, this.globalVariables,
|
|
339
|
+
const publicProcessor = processorFactory.create(merkleTrees, this.globalVariables, {
|
|
340
|
+
skipFeeEnforcement: false,
|
|
341
|
+
clientInitiatedSimulation: false,
|
|
342
|
+
});
|
|
234
343
|
|
|
235
344
|
return await publicProcessor.process(txs, { maxTransactions });
|
|
236
345
|
}
|
|
@@ -265,12 +374,9 @@ class TestProvingOrchestrator extends ProvingOrchestrator {
|
|
|
265
374
|
|
|
266
375
|
// Disable this check by default, since it requires seeding world state with the block being built
|
|
267
376
|
// This is only enabled in some tests with multiple blocks that populate the pending chain via makePendingBlock
|
|
268
|
-
protected override verifyBuiltBlockAgainstSyncedState(
|
|
269
|
-
l2Block: L2Block,
|
|
270
|
-
newArchive: AppendOnlyTreeSnapshot,
|
|
271
|
-
): Promise<void> {
|
|
377
|
+
protected override verifyBuiltBlockAgainstSyncedState(provingState: BlockProvingState): Promise<void> {
|
|
272
378
|
if (this.isVerifyBuiltBlockAgainstSyncedStateEnabled) {
|
|
273
|
-
return super.verifyBuiltBlockAgainstSyncedState(
|
|
379
|
+
return super.verifyBuiltBlockAgainstSyncedState(provingState);
|
|
274
380
|
}
|
|
275
381
|
return Promise.resolve();
|
|
276
382
|
}
|