@aztec/simulator 0.0.1-commit.c0b82b2 → 0.0.1-commit.c2eed6949

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 (38) hide show
  1. package/dest/private/circuit_recording/circuit_recorder.js +2 -2
  2. package/dest/public/contracts_db_checkpoint.d.ts +2 -2
  3. package/dest/public/contracts_db_checkpoint.d.ts.map +1 -1
  4. package/dest/public/contracts_db_checkpoint.js +1 -1
  5. package/dest/public/fixtures/public_tx_simulation_tester.d.ts +6 -5
  6. package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
  7. package/dest/public/fixtures/public_tx_simulation_tester.js +8 -8
  8. package/dest/public/fixtures/utils.d.ts +2 -2
  9. package/dest/public/fixtures/utils.d.ts.map +1 -1
  10. package/dest/public/fixtures/utils.js +2 -2
  11. package/dest/public/hinting_db_sources.d.ts +4 -4
  12. package/dest/public/hinting_db_sources.d.ts.map +1 -1
  13. package/dest/public/hinting_db_sources.js +6 -5
  14. package/dest/public/public_db_sources.d.ts +3 -3
  15. package/dest/public/public_db_sources.d.ts.map +1 -1
  16. package/dest/public/public_db_sources.js +10 -10
  17. package/dest/public/public_processor/guarded_merkle_tree.d.ts +4 -4
  18. package/dest/public/public_processor/guarded_merkle_tree.d.ts.map +1 -1
  19. package/dest/public/public_processor/guarded_merkle_tree.js +4 -4
  20. package/dest/public/public_processor/public_processor.d.ts +2 -2
  21. package/dest/public/public_processor/public_processor.d.ts.map +1 -1
  22. package/dest/public/public_processor/public_processor.js +37 -37
  23. package/dest/public/public_tx_simulator/contract_provider_for_cpp.d.ts +1 -1
  24. package/dest/public/public_tx_simulator/contract_provider_for_cpp.d.ts.map +1 -1
  25. package/dest/public/public_tx_simulator/contract_provider_for_cpp.js +2 -1
  26. package/dest/public/public_tx_simulator/public_tx_simulator.js +2 -2
  27. package/package.json +15 -16
  28. package/src/private/circuit_recording/circuit_recorder.ts +2 -2
  29. package/src/public/avm/opcodes/external_calls.ts +1 -1
  30. package/src/public/contracts_db_checkpoint.ts +1 -1
  31. package/src/public/fixtures/public_tx_simulation_tester.ts +17 -2
  32. package/src/public/fixtures/utils.ts +2 -1
  33. package/src/public/hinting_db_sources.ts +8 -6
  34. package/src/public/public_db_sources.ts +12 -14
  35. package/src/public/public_processor/guarded_merkle_tree.ts +5 -5
  36. package/src/public/public_processor/public_processor.ts +46 -42
  37. package/src/public/public_tx_simulator/contract_provider_for_cpp.ts +2 -1
  38. package/src/public/public_tx_simulator/public_tx_simulator.ts +2 -2
@@ -160,8 +160,8 @@ export class PublicProcessor implements Traceable {
160
160
  txs: Iterable<Tx> | AsyncIterable<Tx>,
161
161
  limits: PublicProcessorLimits = {},
162
162
  validator: PublicProcessorValidator = {},
163
- ): Promise<[ProcessedTx[], FailedTx[], Tx[], NestedProcessReturnValues[], number, DebugLog[]]> {
164
- const { maxTransactions, maxBlockSize, deadline, maxBlockGas, maxBlobFields } = limits;
163
+ ): Promise<[ProcessedTx[], FailedTx[], Tx[], NestedProcessReturnValues[], DebugLog[]]> {
164
+ const { maxTransactions, deadline, maxBlockGas, maxBlobFields, isBuildingProposal } = limits;
165
165
  const { preprocessValidator, nullifierCache } = validator;
166
166
  const result: ProcessedTx[] = [];
167
167
  const usedTxs: Tx[] = [];
@@ -188,22 +188,23 @@ export class PublicProcessor implements Traceable {
188
188
  break;
189
189
  }
190
190
 
191
- // Skip this tx if it'd exceed max block size
192
191
  const txHash = tx.getTxHash().toString();
193
- const preTxSizeInBytes = tx.getEstimatedPrivateTxEffectsSize();
194
- if (maxBlockSize !== undefined && totalSizeInBytes + preTxSizeInBytes > maxBlockSize) {
195
- this.log.warn(`Skipping processing of tx ${txHash} sized ${preTxSizeInBytes} bytes due to block size limit`, {
196
- txHash,
197
- sizeInBytes: preTxSizeInBytes,
198
- totalSizeInBytes,
199
- maxBlockSize,
200
- });
192
+
193
+ // Skip this tx if its estimated blob fields would exceed the limit.
194
+ // Only done during proposal building: during re-execution we must process the exact txs from the proposal.
195
+ const txBlobFields = tx.getPrivateTxEffectsSizeInFields();
196
+ if (isBuildingProposal && maxBlobFields !== undefined && totalBlobFields + txBlobFields > maxBlobFields) {
197
+ this.log.warn(
198
+ `Skipping tx ${txHash} with ${txBlobFields} fields from private side effects due to blob fields limit`,
199
+ { txHash, txBlobFields, totalBlobFields, maxBlobFields },
200
+ );
201
201
  continue;
202
202
  }
203
203
 
204
- // Skip this tx if its gas limit would exceed the block gas limit
204
+ // Skip this tx if its gas limit would exceed the block gas limit (either da or l2).
205
+ // Only done during proposal building: during re-execution we must process the exact txs from the proposal.
205
206
  const txGasLimit = tx.data.constants.txContext.gasSettings.gasLimits;
206
- if (maxBlockGas !== undefined && totalBlockGas.add(txGasLimit).gtAny(maxBlockGas)) {
207
+ if (isBuildingProposal && maxBlockGas !== undefined && totalBlockGas.add(txGasLimit).gtAny(maxBlockGas)) {
207
208
  this.log.warn(`Skipping processing of tx ${txHash} due to block gas limit`, {
208
209
  txHash,
209
210
  txGasLimit,
@@ -252,23 +253,9 @@ export class PublicProcessor implements Traceable {
252
253
  }
253
254
 
254
255
  const txBlobFields = processedTx.txEffect.getNumBlobFields();
255
-
256
- // If the actual size of this tx would exceed block size, skip it
257
256
  const txSize = txBlobFields * Fr.SIZE_IN_BYTES;
258
- if (maxBlockSize !== undefined && totalSizeInBytes + txSize > maxBlockSize) {
259
- this.log.debug(`Skipping processed tx ${txHash} sized ${txSize} due to max block size.`, {
260
- txHash,
261
- sizeInBytes: txSize,
262
- totalSizeInBytes,
263
- maxBlockSize,
264
- });
265
- // Need to revert the checkpoint here and don't go any further
266
- await checkpoint.revert();
267
- this.contractsDB.revertCheckpoint();
268
- continue;
269
- }
270
257
 
271
- // If the actual blob fields of this tx would exceed the limit, skip it
258
+ // If the actual blob fields of this tx would exceed the limit, skip it.
272
259
  // Note: maxBlobFields already accounts for block end blob fields and previous blocks in checkpoint.
273
260
  if (maxBlobFields !== undefined && totalBlobFields + txBlobFields > maxBlobFields) {
274
261
  this.log.debug(
@@ -286,6 +273,25 @@ export class PublicProcessor implements Traceable {
286
273
  continue;
287
274
  }
288
275
 
276
+ // During re-execution, check if the actual gas used by this tx would push the block over the gas limit.
277
+ // Unlike the proposal-building check (which uses declared gas limits pessimistically before processing),
278
+ // this uses actual gas and stops processing when the limit is exceeded.
279
+ if (
280
+ !isBuildingProposal &&
281
+ maxBlockGas !== undefined &&
282
+ totalBlockGas.add(processedTx.gasUsed.totalGas).gtAny(maxBlockGas)
283
+ ) {
284
+ this.log.warn(`Stopping re-execution since tx ${txHash} would push block gas over limit`, {
285
+ txHash,
286
+ txGas: processedTx.gasUsed.totalGas,
287
+ totalBlockGas,
288
+ maxBlockGas,
289
+ });
290
+ await checkpoint.revert();
291
+ this.contractsDB.revertCheckpoint();
292
+ break;
293
+ }
294
+
289
295
  // FIXME(fcarreiro): it's ugly to have to notify the validator of nullifiers.
290
296
  // I'd rather pass the validators the processedTx as well and let them deal with it.
291
297
  nullifierCache?.addNullifiers(processedTx.txEffect.nullifiers.map(n => n.toBuffer()));
@@ -300,6 +306,9 @@ export class PublicProcessor implements Traceable {
300
306
  totalBlockGas = totalBlockGas.add(processedTx.gasUsed.totalGas);
301
307
  totalSizeInBytes += txSize;
302
308
  totalBlobFields += txBlobFields;
309
+
310
+ // Commit the tx-level contracts checkpoint on success
311
+ this.contractsDB.commitCheckpoint();
303
312
  } catch (err: any) {
304
313
  if (err?.name === 'PublicProcessorTimeoutError') {
305
314
  this.log.warn(`Stopping tx processing due to timeout.`);
@@ -319,14 +328,10 @@ export class PublicProcessor implements Traceable {
319
328
  // 1. At least one outstanding checkpoint that has not been committed (the one created before we processed the tx).
320
329
  // 2. Possible state updates on that checkpoint or any others created during execution.
321
330
 
322
- // First we revert a checkpoint as managed by the ForkCheckpoint. This will revert whatever is the current checkpoint
323
- // which may not be the one originally created by this object. But that is ok, we do this to fulfil the ForkCheckpoint
324
- // lifecycle expectations and ensure it doesn't attempt to commit later on.
325
- await checkpoint.revert();
326
-
327
- // Now we want to revert any/all remaining checkpoints, destroying any outstanding state updates.
328
- // This needs to be done directly on the underlying fork as the guarded fork has been stopped.
329
- await this.guardedMerkleTree.getUnderlyingFork().revertAllCheckpoints();
331
+ // Revert all checkpoints at or above this checkpoint's depth (inclusive), destroying any outstanding state
332
+ // updates from this tx and any nested checkpoints created during execution. This preserves any checkpoints
333
+ // created by callers below our depth.
334
+ await checkpoint.revertToCheckpoint();
330
335
 
331
336
  // Revert any contracts added to the DB for the tx.
332
337
  this.contractsDB.revertCheckpoint();
@@ -338,9 +343,9 @@ export class PublicProcessor implements Traceable {
338
343
  break;
339
344
  }
340
345
 
341
- // Roll back state to start of TX before proceeding to next TX
342
- await checkpoint.revert();
343
- await this.guardedMerkleTree.getUnderlyingFork().revertAllCheckpoints();
346
+ // Roll back state to start of TX before proceeding to next TX.
347
+ // Reverts all checkpoints at or above this checkpoint's depth, preserving any caller checkpoints below.
348
+ await checkpoint.revertToCheckpoint();
344
349
  this.contractsDB.revertCheckpoint();
345
350
  const errorMessage = err instanceof Error || err instanceof AssertionError ? err.message : 'Unknown error';
346
351
  this.log.warn(`Failed to process tx ${txHash.toString()}: ${errorMessage} ${err?.stack}`);
@@ -352,7 +357,6 @@ export class PublicProcessor implements Traceable {
352
357
  } finally {
353
358
  // Base case is we always commit the checkpoint. Using the ForkCheckpoint means this has no effect if the tx was previously reverted
354
359
  await checkpoint.commit();
355
- this.contractsDB.commitCheckpointOkIfNone();
356
360
  }
357
361
  }
358
362
 
@@ -368,7 +372,7 @@ export class PublicProcessor implements Traceable {
368
372
  totalSizeInBytes,
369
373
  });
370
374
 
371
- return [result, failed, usedTxs, returns, totalBlobFields, debugLogs];
375
+ return [result, failed, usedTxs, returns, debugLogs];
372
376
  }
373
377
 
374
378
  private async checkWorldStateUnchanged(
@@ -544,7 +548,7 @@ export class PublicProcessor implements Traceable {
544
548
  // Fee payment insertion has already been done. Do the rest.
545
549
  await this.doTreeInsertionsForPrivateOnlyTx(processedTx);
546
550
 
547
- await this.contractsDB.addNewContracts(tx);
551
+ this.contractsDB.addNewContracts(tx);
548
552
 
549
553
  return [processedTx, undefined, []];
550
554
  }
@@ -52,6 +52,7 @@ export class ContractProviderForCpp implements ContractProvider {
52
52
  return serializeWithMessagePack(contractClass);
53
53
  };
54
54
 
55
+ // eslint-disable-next-line require-await
55
56
  public addContracts = async (contractDeploymentDataBuffer: Buffer): Promise<void> => {
56
57
  this.log.trace(`Contract provider callback: addContracts`);
57
58
 
@@ -62,7 +63,7 @@ export class ContractProviderForCpp implements ContractProvider {
62
63
 
63
64
  // Add contracts to the contracts DB
64
65
  this.log.trace(`Calling contractsDB.addContracts`);
65
- await this.contractsDB.addContracts(contractDeploymentData);
66
+ this.contractsDB.addContracts(contractDeploymentData);
66
67
  };
67
68
 
68
69
  public getBytecodeCommitment = async (classId: string): Promise<Buffer | undefined> => {
@@ -401,7 +401,7 @@ export class PublicTxSimulator implements PublicTxSimulatorInterface {
401
401
  // However, things work as expected because later calls to getters on the hintingContractsDB
402
402
  // will pick up the new contracts and will generate the necessary hints.
403
403
  // So, a consumer of the hints will always see the new contracts.
404
- await this.contractsDB.addContracts(context.nonRevertibleContractDeploymentData);
404
+ this.contractsDB.addContracts(context.nonRevertibleContractDeploymentData);
405
405
  }
406
406
 
407
407
  /**
@@ -486,7 +486,7 @@ export class PublicTxSimulator implements PublicTxSimulatorInterface {
486
486
  // However, things work as expected because later calls to getters on the hintingContractsDB
487
487
  // will pick up the new contracts and will generate the necessary hints.
488
488
  // So, a consumer of the hints will always see the new contracts.
489
- await this.contractsDB.addContracts(context.revertibleContractDeploymentData);
489
+ this.contractsDB.addContracts(context.revertibleContractDeploymentData);
490
490
  }
491
491
 
492
492
  private async payFee(context: PublicTxContext) {