@aztec/sequencer-client 0.0.1-commit.9b94fc1 → 0.0.1-commit.c7c42ec

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 (95) hide show
  1. package/dest/client/sequencer-client.d.ts +10 -9
  2. package/dest/client/sequencer-client.d.ts.map +1 -1
  3. package/dest/client/sequencer-client.js +32 -25
  4. package/dest/config.d.ts +12 -5
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +68 -30
  7. package/dest/global_variable_builder/global_builder.d.ts +19 -10
  8. package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
  9. package/dest/global_variable_builder/global_builder.js +39 -29
  10. package/dest/index.d.ts +2 -2
  11. package/dest/index.d.ts.map +1 -1
  12. package/dest/index.js +1 -1
  13. package/dest/publisher/config.d.ts +7 -4
  14. package/dest/publisher/config.d.ts.map +1 -1
  15. package/dest/publisher/config.js +9 -3
  16. package/dest/publisher/sequencer-publisher-factory.d.ts +5 -4
  17. package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
  18. package/dest/publisher/sequencer-publisher-factory.js +1 -1
  19. package/dest/publisher/sequencer-publisher-metrics.d.ts +3 -3
  20. package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
  21. package/dest/publisher/sequencer-publisher.d.ts +40 -33
  22. package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
  23. package/dest/publisher/sequencer-publisher.js +133 -74
  24. package/dest/sequencer/block_builder.d.ts +4 -5
  25. package/dest/sequencer/block_builder.d.ts.map +1 -1
  26. package/dest/sequencer/block_builder.js +8 -13
  27. package/dest/sequencer/checkpoint_builder.d.ts +63 -0
  28. package/dest/sequencer/checkpoint_builder.d.ts.map +1 -0
  29. package/dest/sequencer/checkpoint_builder.js +131 -0
  30. package/dest/sequencer/checkpoint_proposal_job.d.ts +74 -0
  31. package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -0
  32. package/dest/sequencer/checkpoint_proposal_job.js +642 -0
  33. package/dest/sequencer/checkpoint_voter.d.ts +34 -0
  34. package/dest/sequencer/checkpoint_voter.d.ts.map +1 -0
  35. package/dest/sequencer/checkpoint_voter.js +85 -0
  36. package/dest/sequencer/config.d.ts +3 -2
  37. package/dest/sequencer/config.d.ts.map +1 -1
  38. package/dest/sequencer/events.d.ts +46 -0
  39. package/dest/sequencer/events.d.ts.map +1 -0
  40. package/dest/sequencer/events.js +1 -0
  41. package/dest/sequencer/index.d.ts +5 -1
  42. package/dest/sequencer/index.d.ts.map +1 -1
  43. package/dest/sequencer/index.js +4 -0
  44. package/dest/sequencer/metrics.d.ts +22 -2
  45. package/dest/sequencer/metrics.d.ts.map +1 -1
  46. package/dest/sequencer/metrics.js +154 -0
  47. package/dest/sequencer/sequencer.d.ts +93 -127
  48. package/dest/sequencer/sequencer.d.ts.map +1 -1
  49. package/dest/sequencer/sequencer.js +223 -578
  50. package/dest/sequencer/timetable.d.ts +54 -14
  51. package/dest/sequencer/timetable.d.ts.map +1 -1
  52. package/dest/sequencer/timetable.js +148 -59
  53. package/dest/sequencer/types.d.ts +3 -0
  54. package/dest/sequencer/types.d.ts.map +1 -0
  55. package/dest/sequencer/types.js +1 -0
  56. package/dest/sequencer/utils.d.ts +14 -8
  57. package/dest/sequencer/utils.d.ts.map +1 -1
  58. package/dest/sequencer/utils.js +7 -4
  59. package/dest/test/index.d.ts +4 -2
  60. package/dest/test/index.d.ts.map +1 -1
  61. package/dest/test/mock_checkpoint_builder.d.ts +83 -0
  62. package/dest/test/mock_checkpoint_builder.d.ts.map +1 -0
  63. package/dest/test/mock_checkpoint_builder.js +179 -0
  64. package/dest/test/utils.d.ts +49 -0
  65. package/dest/test/utils.d.ts.map +1 -0
  66. package/dest/test/utils.js +94 -0
  67. package/dest/tx_validator/tx_validator_factory.d.ts +3 -2
  68. package/dest/tx_validator/tx_validator_factory.d.ts.map +1 -1
  69. package/dest/tx_validator/tx_validator_factory.js +1 -1
  70. package/package.json +29 -29
  71. package/src/client/sequencer-client.ts +28 -38
  72. package/src/config.ts +73 -34
  73. package/src/global_variable_builder/global_builder.ts +54 -50
  74. package/src/index.ts +2 -0
  75. package/src/publisher/config.ts +12 -9
  76. package/src/publisher/sequencer-publisher-factory.ts +5 -4
  77. package/src/publisher/sequencer-publisher-metrics.ts +2 -2
  78. package/src/publisher/sequencer-publisher.ts +214 -102
  79. package/src/sequencer/README.md +531 -0
  80. package/src/sequencer/block_builder.ts +11 -16
  81. package/src/sequencer/checkpoint_builder.ts +217 -0
  82. package/src/sequencer/checkpoint_proposal_job.ts +706 -0
  83. package/src/sequencer/checkpoint_voter.ts +105 -0
  84. package/src/sequencer/config.ts +2 -1
  85. package/src/sequencer/events.ts +27 -0
  86. package/src/sequencer/index.ts +4 -0
  87. package/src/sequencer/metrics.ts +203 -1
  88. package/src/sequencer/sequencer.ts +330 -788
  89. package/src/sequencer/timetable.ts +173 -79
  90. package/src/sequencer/types.ts +6 -0
  91. package/src/sequencer/utils.ts +18 -9
  92. package/src/test/index.ts +3 -1
  93. package/src/test/mock_checkpoint_builder.ts +247 -0
  94. package/src/test/utils.ts +137 -0
  95. package/src/tx_validator/tx_validator_factory.ts +3 -2
@@ -1,9 +1,12 @@
1
1
  import { Blob, getBlobsPerL1Block, getPrefixedEthBlobCommitments } from '@aztec/blob-lib';
2
- import { createBlobSinkClient } from '@aztec/blob-sink/client';
3
- import { FormattedViemError, MULTI_CALL_3_ADDRESS, Multicall3, RollupContract, WEI_CONST, formatViemError, tryExtractEvent } from '@aztec/ethereum';
2
+ import { MULTI_CALL_3_ADDRESS, Multicall3, RollupContract } from '@aztec/ethereum/contracts';
3
+ import { L1FeeAnalyzer } from '@aztec/ethereum/l1-fee-analysis';
4
+ import { WEI_CONST } from '@aztec/ethereum/l1-tx-utils';
5
+ import { FormattedViemError, formatViemError, tryExtractEvent } from '@aztec/ethereum/utils';
4
6
  import { sumBigint } from '@aztec/foundation/bigint';
5
7
  import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
6
- import { SlotNumber } from '@aztec/foundation/branded-types';
8
+ import { BlockNumber, CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
9
+ import { pick } from '@aztec/foundation/collection';
7
10
  import { EthAddress } from '@aztec/foundation/eth-address';
8
11
  import { Signature } from '@aztec/foundation/eth-signature';
9
12
  import { createLogger } from '@aztec/foundation/log';
@@ -11,7 +14,7 @@ import { bufferToHex } from '@aztec/foundation/string';
11
14
  import { Timer } from '@aztec/foundation/timer';
12
15
  import { EmpireBaseAbi, ErrorsAbi, RollupAbi } from '@aztec/l1-artifacts';
13
16
  import { encodeSlashConsensusVotes } from '@aztec/slasher';
14
- import { CommitteeAttestation, CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
17
+ import { CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
15
18
  import { getTelemetryClient } from '@aztec/telemetry-client';
16
19
  import { encodeFunctionData, toHex } from 'viem';
17
20
  import { SequencerPublisherMetrics } from './sequencer-publisher-metrics.js';
@@ -36,10 +39,12 @@ export class SequencerPublisher {
36
39
  governanceLog;
37
40
  slashingLog;
38
41
  lastActions;
42
+ isPayloadEmptyCache;
39
43
  log;
40
44
  ethereumSlotDuration;
41
- blobSinkClient;
45
+ blobClient;
42
46
  /** Address to use for simulations in fisherman mode (actual proposer's address) */ proposerAddressForSimulation;
47
+ /** L1 fee analyzer for fisherman mode */ l1FeeAnalyzer;
43
48
  // @note - with blobs, the below estimate seems too large.
44
49
  // Total used for full block from int_l1_pub e2e test: 1m (of which 86k is 1x blob)
45
50
  // Total used for emptier block from above test: 429k (of which 84k is 1x blob)
@@ -60,14 +65,13 @@ export class SequencerPublisher {
60
65
  this.governanceLog = createLogger('sequencer:publisher:governance');
61
66
  this.slashingLog = createLogger('sequencer:publisher:slashing');
62
67
  this.lastActions = {};
68
+ this.isPayloadEmptyCache = new Map();
63
69
  this.requests = [];
64
70
  this.log = deps.log ?? createLogger('sequencer:publisher');
65
71
  this.ethereumSlotDuration = BigInt(config.ethereumSlotDuration);
66
72
  this.epochCache = deps.epochCache;
67
73
  this.lastActions = deps.lastActions;
68
- this.blobSinkClient = deps.blobSinkClient ?? createBlobSinkClient(config, {
69
- logger: createLogger('sequencer:blob-sink:client')
70
- });
74
+ this.blobClient = deps.blobClient;
71
75
  const telemetry = deps.telemetry ?? getTelemetryClient();
72
76
  this.metrics = deps.metrics ?? new SequencerPublisherMetrics(telemetry, 'SequencerPublisher');
73
77
  this.l1TxUtils = deps.l1TxUtils;
@@ -80,6 +84,10 @@ export class SequencerPublisher {
80
84
  this.slashingProposerContract = newSlashingProposer;
81
85
  });
82
86
  this.slashFactoryContract = deps.slashFactoryContract;
87
+ // Initialize L1 fee analyzer for fisherman mode
88
+ if (config.fishermanMode) {
89
+ this.l1FeeAnalyzer = new L1FeeAnalyzer(this.l1TxUtils.client, deps.dateProvider, createLogger('sequencer:publisher:fee-analyzer'));
90
+ }
83
91
  }
84
92
  getRollupContract() {
85
93
  return this.rollupContract;
@@ -88,6 +96,11 @@ export class SequencerPublisher {
88
96
  return this.l1TxUtils.getSenderAddress();
89
97
  }
90
98
  /**
99
+ * Gets the L1 fee analyzer instance (only available in fisherman mode)
100
+ */ getL1FeeAnalyzer() {
101
+ return this.l1FeeAnalyzer;
102
+ }
103
+ /**
91
104
  * Sets the proposer address to use for simulations in fisherman mode.
92
105
  * @param proposerAddress - The actual proposer's address to use for balance lookups in simulations
93
106
  */ setProposerAddressForSimulation(proposerAddress) {
@@ -109,6 +122,46 @@ export class SequencerPublisher {
109
122
  }
110
123
  }
111
124
  /**
125
+ * Analyzes L1 fees for the pending requests without sending them.
126
+ * This is used in fisherman mode to validate fee calculations.
127
+ * @param l2SlotNumber - The L2 slot number for this analysis
128
+ * @param onComplete - Optional callback to invoke when analysis completes (after block is mined)
129
+ * @returns The analysis result (incomplete until block mines), or undefined if no requests
130
+ */ async analyzeL1Fees(l2SlotNumber, onComplete) {
131
+ if (!this.l1FeeAnalyzer) {
132
+ this.log.warn('L1 fee analyzer not available (not in fisherman mode)');
133
+ return undefined;
134
+ }
135
+ const requestsToAnalyze = [
136
+ ...this.requests
137
+ ];
138
+ if (requestsToAnalyze.length === 0) {
139
+ this.log.debug('No requests to analyze for L1 fees');
140
+ return undefined;
141
+ }
142
+ // Extract blob config from requests (if any)
143
+ const blobConfigs = requestsToAnalyze.filter((request)=>request.blobConfig).map((request)=>request.blobConfig);
144
+ const blobConfig = blobConfigs[0];
145
+ // Get gas configs
146
+ const gasConfigs = requestsToAnalyze.filter((request)=>request.gasConfig).map((request)=>request.gasConfig);
147
+ const gasLimits = gasConfigs.map((g)=>g?.gasLimit).filter((g)=>g !== undefined);
148
+ const gasLimit = gasLimits.length > 0 ? gasLimits.reduce((sum, g)=>sum + g, 0n) : 0n;
149
+ // Get the transaction requests
150
+ const l1Requests = requestsToAnalyze.map((r)=>r.request);
151
+ // Start the analysis
152
+ const analysisId = await this.l1FeeAnalyzer.startAnalysis(l2SlotNumber, gasLimit > 0n ? gasLimit : SequencerPublisher.PROPOSE_GAS_GUESS, l1Requests, blobConfig, onComplete);
153
+ this.log.info('Started L1 fee analysis', {
154
+ analysisId,
155
+ l2SlotNumber: l2SlotNumber.toString(),
156
+ requestCount: requestsToAnalyze.length,
157
+ hasBlobConfig: !!blobConfig,
158
+ gasLimit: gasLimit.toString(),
159
+ actions: requestsToAnalyze.map((r)=>r.action)
160
+ });
161
+ // Return the analysis result (will be incomplete until block mines)
162
+ return this.l1FeeAnalyzer.getAnalysis(analysisId);
163
+ }
164
+ /**
112
165
  * Sends all requests that are still valid.
113
166
  * @returns one of:
114
167
  * - A receipt and stats if the tx succeeded
@@ -119,7 +172,7 @@ export class SequencerPublisher {
119
172
  ...this.requests
120
173
  ];
121
174
  this.requests = [];
122
- if (this.interrupted) {
175
+ if (this.interrupted || requestsToProcess.length === 0) {
123
176
  return undefined;
124
177
  }
125
178
  const currentL2Slot = this.getCurrentL2Slot();
@@ -229,7 +282,7 @@ export class SequencerPublisher {
229
282
  'InvalidArchive'
230
283
  ];
231
284
  return this.rollupContract.canProposeAtNextEthBlock(tipArchive.toBuffer(), msgSender.toString(), Number(this.ethereumSlotDuration), {
232
- forcePendingCheckpointNumber: opts.forcePendingBlockNumber
285
+ forcePendingCheckpointNumber: opts.forcePendingBlockNumber !== undefined ? CheckpointNumber.fromBlockNumber(opts.forcePendingBlockNumber) : undefined
233
286
  }).catch((err)=>{
234
287
  if (err instanceof FormattedViemError && ignoredErrors.find((e)=>err.message.includes(e))) {
235
288
  this.log.warn(`Failed canProposeAtTime check with ${ignoredErrors.find((e)=>err.message.includes(e))}`, {
@@ -261,7 +314,8 @@ export class SequencerPublisher {
261
314
  flags
262
315
  ];
263
316
  const ts = BigInt((await this.l1TxUtils.getBlock()).timestamp + this.ethereumSlotDuration);
264
- const stateOverrides = await this.rollupContract.makePendingCheckpointNumberOverride(opts?.forcePendingBlockNumber);
317
+ const optsForcePendingCheckpointNumber = opts?.forcePendingBlockNumber !== undefined ? CheckpointNumber.fromBlockNumber(opts.forcePendingBlockNumber) : undefined;
318
+ const stateOverrides = await this.rollupContract.makePendingCheckpointNumberOverride(optsForcePendingCheckpointNumber);
265
319
  let balance = 0n;
266
320
  if (this.config.fishermanMode) {
267
321
  // In fisherman mode, we can't know where the proposer is publishing from
@@ -324,7 +378,7 @@ export class SequencerPublisher {
324
378
  request,
325
379
  gasUsed,
326
380
  blockNumber,
327
- forcePendingBlockNumber: blockNumber - 1,
381
+ forcePendingBlockNumber: BlockNumber(blockNumber - 1),
328
382
  reason
329
383
  };
330
384
  } catch (err) {
@@ -369,42 +423,37 @@ export class SequencerPublisher {
369
423
  this.log.debug(`Simulating invalidate block ${block.blockNumber}`, logData);
370
424
  const attestationsAndSigners = new CommitteeAttestationsAndSigners(validationResult.attestations).getPackedAttestations();
371
425
  if (reason === 'invalid-attestation') {
372
- return this.rollupContract.buildInvalidateBadAttestationRequest(block.blockNumber, attestationsAndSigners, committee, validationResult.invalidIndex);
426
+ return this.rollupContract.buildInvalidateBadAttestationRequest(CheckpointNumber.fromBlockNumber(block.blockNumber), attestationsAndSigners, committee, validationResult.invalidIndex);
373
427
  } else if (reason === 'insufficient-attestations') {
374
- return this.rollupContract.buildInvalidateInsufficientAttestationsRequest(block.blockNumber, attestationsAndSigners, committee);
428
+ return this.rollupContract.buildInvalidateInsufficientAttestationsRequest(CheckpointNumber.fromBlockNumber(block.blockNumber), attestationsAndSigners, committee);
375
429
  } else {
376
430
  const _ = reason;
377
431
  throw new Error(`Unknown reason for invalidation`);
378
432
  }
379
433
  }
380
- /**
381
- * @notice Will simulate `propose` to make sure that the block is valid for submission
382
- *
383
- * @dev Throws if unable to propose
384
- *
385
- * @param block - The block to propose
386
- * @param attestationData - The block's attestation data
387
- *
388
- */ async validateBlockForSubmission(block, attestationsAndSigners, attestationsAndSignersSignature, options) {
434
+ /** Simulates `propose` to make sure that the checkpoint is valid for submission */ async validateCheckpointForSubmission(checkpoint, attestationsAndSigners, attestationsAndSignersSignature, options) {
389
435
  const ts = BigInt((await this.l1TxUtils.getBlock()).timestamp + this.ethereumSlotDuration);
436
+ // TODO(palla/mbps): This should not be needed, there's no flow where we propose with zero attestations. Or is there?
390
437
  // If we have no attestations, we still need to provide the empty attestations
391
438
  // so that the committee is recalculated correctly
392
- const ignoreSignatures = attestationsAndSigners.attestations.length === 0;
393
- if (ignoreSignatures) {
394
- const { committee } = await this.epochCache.getCommittee(block.header.globalVariables.slotNumber);
395
- if (!committee) {
396
- this.log.warn(`No committee found for slot ${block.header.globalVariables.slotNumber}`);
397
- throw new Error(`No committee found for slot ${block.header.globalVariables.slotNumber}`);
398
- }
399
- attestationsAndSigners.attestations = committee.map((committeeMember)=>CommitteeAttestation.fromAddress(committeeMember));
400
- }
401
- const blobFields = block.getCheckpointBlobFields();
439
+ // const ignoreSignatures = attestationsAndSigners.attestations.length === 0;
440
+ // if (ignoreSignatures) {
441
+ // const { committee } = await this.epochCache.getCommittee(block.header.globalVariables.slotNumber);
442
+ // if (!committee) {
443
+ // this.log.warn(`No committee found for slot ${block.header.globalVariables.slotNumber}`);
444
+ // throw new Error(`No committee found for slot ${block.header.globalVariables.slotNumber}`);
445
+ // }
446
+ // attestationsAndSigners.attestations = committee.map(committeeMember =>
447
+ // CommitteeAttestation.fromAddress(committeeMember),
448
+ // );
449
+ // }
450
+ const blobFields = checkpoint.toBlobFields();
402
451
  const blobs = getBlobsPerL1Block(blobFields);
403
452
  const blobInput = getPrefixedEthBlobCommitments(blobs);
404
453
  const args = [
405
454
  {
406
- header: block.getCheckpointHeader().toViem(),
407
- archive: toHex(block.archive.root.toBuffer()),
455
+ header: checkpoint.header.toViem(),
456
+ archive: toHex(checkpoint.archive.root.toBuffer()),
408
457
  oracleInput: {
409
458
  feeAssetPriceModifier: 0n
410
459
  }
@@ -431,9 +480,16 @@ export class SequencerPublisher {
431
480
  }
432
481
  const round = await base.computeRound(slotNumber);
433
482
  const roundInfo = await base.getRoundInfo(this.rollupContract.address, round);
483
+ if (roundInfo.quorumReached) {
484
+ return false;
485
+ }
434
486
  if (roundInfo.lastSignalSlot >= slotNumber) {
435
487
  return false;
436
488
  }
489
+ if (await this.isPayloadEmpty(payload)) {
490
+ this.log.warn(`Skipping vote cast for payload with empty code`);
491
+ return false;
492
+ }
437
493
  const cachedLastVote = this.lastActions[signalType];
438
494
  this.lastActions[signalType] = slotNumber;
439
495
  const action = signalType;
@@ -472,17 +528,27 @@ export class SequencerPublisher {
472
528
  payload: payload.toString()
473
529
  };
474
530
  if (!success) {
475
- this.log.error(`Signaling in [${action}] for ${payload} at slot ${slotNumber} in round ${round} failed`, logData);
531
+ this.log.error(`Signaling in ${action} for ${payload} at slot ${slotNumber} in round ${round} failed`, logData);
476
532
  this.lastActions[signalType] = cachedLastVote;
477
533
  return false;
478
534
  } else {
479
- this.log.info(`Signaling in [${action}] for ${payload} at slot ${slotNumber} in round ${round} succeeded`, logData);
535
+ this.log.info(`Signaling in ${action} for ${payload} at slot ${slotNumber} in round ${round} succeeded`, logData);
480
536
  return true;
481
537
  }
482
538
  }
483
539
  });
484
540
  return true;
485
541
  }
542
+ async isPayloadEmpty(payload) {
543
+ const key = payload.toString();
544
+ const cached = this.isPayloadEmptyCache.get(key);
545
+ if (cached) {
546
+ return cached;
547
+ }
548
+ const isEmpty = !await this.l1TxUtils.getCode(payload);
549
+ this.isPayloadEmptyCache.set(key, isEmpty);
550
+ return isEmpty;
551
+ }
486
552
  /**
487
553
  * Enqueues a governance castSignal transaction to cast a signal for a given slot number.
488
554
  * @param slotNumber - The slot number to cast a signal for.
@@ -578,19 +644,13 @@ export class SequencerPublisher {
578
644
  }
579
645
  return true;
580
646
  }
581
- /**
582
- * Proposes a L2 block on L1.
583
- *
584
- * @param block - L2 block to propose.
585
- * @returns True if the tx has been enqueued, throws otherwise. See #9315
586
- */ async enqueueProposeL2Block(block, attestationsAndSigners, attestationsAndSignersSignature, opts = {}) {
587
- const checkpointHeader = block.getCheckpointHeader();
588
- const blobFields = block.getCheckpointBlobFields();
647
+ /** Simulates and enqueues a proposal for a checkpoint on L1 */ async enqueueProposeCheckpoint(checkpoint, attestationsAndSigners, attestationsAndSignersSignature, opts = {}) {
648
+ const checkpointHeader = checkpoint.header;
649
+ const blobFields = checkpoint.toBlobFields();
589
650
  const blobs = getBlobsPerL1Block(blobFields);
590
651
  const proposeTxArgs = {
591
652
  header: checkpointHeader,
592
- archive: block.archive.root.toBuffer(),
593
- body: block.body.toBuffer(),
653
+ archive: checkpoint.archive.root.toBuffer(),
594
654
  blobs,
595
655
  attestationsAndSigners,
596
656
  attestationsAndSignersSignature
@@ -602,21 +662,20 @@ export class SequencerPublisher {
602
662
  // By simulation issue, I mean the fact that the block.timestamp is equal to the last block, not the next, which
603
663
  // make time consistency checks break.
604
664
  // TODO(palla): Check whether we're validating twice, once here and once within addProposeTx, since we call simulateProposeTx in both places.
605
- ts = await this.validateBlockForSubmission(block, attestationsAndSigners, attestationsAndSignersSignature, opts);
665
+ ts = await this.validateCheckpointForSubmission(checkpoint, attestationsAndSigners, attestationsAndSignersSignature, opts);
606
666
  } catch (err) {
607
- this.log.error(`Block validation failed. ${err instanceof Error ? err.message : 'No error message'}`, err, {
608
- ...block.getStats(),
609
- slotNumber: block.header.globalVariables.slotNumber,
667
+ this.log.error(`Checkpoint validation failed. ${err instanceof Error ? err.message : 'No error message'}`, err, {
668
+ ...checkpoint.getStats(),
669
+ slotNumber: checkpoint.header.slotNumber,
610
670
  forcePendingBlockNumber: opts.forcePendingBlockNumber
611
671
  });
612
672
  throw err;
613
673
  }
614
- this.log.verbose(`Enqueuing block propose transaction`, {
615
- ...block.toBlockInfo(),
674
+ this.log.verbose(`Enqueuing checkpoint propose transaction`, {
675
+ ...checkpoint.toCheckpointInfo(),
616
676
  ...opts
617
677
  });
618
- await this.addProposeTx(block, proposeTxArgs, opts, ts);
619
- return true;
678
+ await this.addProposeTx(checkpoint, proposeTxArgs, opts, ts);
620
679
  }
621
680
  enqueueInvalidateBlock(request, opts = {}) {
622
681
  if (!request) {
@@ -797,8 +856,9 @@ export class SequencerPublisher {
797
856
  functionName: 'propose',
798
857
  args
799
858
  });
800
- // override the pending block number if requested
801
- const forcePendingBlockNumberStateDiff = (options.forcePendingBlockNumber !== undefined ? await this.rollupContract.makePendingCheckpointNumberOverride(options.forcePendingBlockNumber) : []).flatMap((override)=>override.stateDiff ?? []);
859
+ // override the pending checkpoint number if requested
860
+ const optsForcePendingCheckpointNumber = options.forcePendingBlockNumber !== undefined ? CheckpointNumber.fromBlockNumber(options.forcePendingBlockNumber) : undefined;
861
+ const forcePendingCheckpointNumberStateDiff = (optsForcePendingCheckpointNumber !== undefined ? await this.rollupContract.makePendingCheckpointNumberOverride(optsForcePendingCheckpointNumber) : []).flatMap((override)=>override.stateDiff ?? []);
802
862
  const stateOverrides = [
803
863
  {
804
864
  address: this.rollupContract.address,
@@ -808,7 +868,7 @@ export class SequencerPublisher {
808
868
  slot: toPaddedHex(RollupContract.checkBlobStorageSlot, true),
809
869
  value: toPaddedHex(0n, true)
810
870
  },
811
- ...forcePendingBlockNumberStateDiff
871
+ ...forcePendingCheckpointNumberStateDiff
812
872
  ]
813
873
  }
814
874
  ];
@@ -853,24 +913,25 @@ export class SequencerPublisher {
853
913
  simulationResult
854
914
  };
855
915
  }
856
- async addProposeTx(block, encodedData, opts = {}, timestamp) {
916
+ async addProposeTx(checkpoint, encodedData, opts = {}, timestamp) {
917
+ const slot = checkpoint.header.slotNumber;
857
918
  const timer = new Timer();
858
919
  const kzg = Blob.getViemKzgInstance();
859
920
  const { rollupData, simulationResult, blobEvaluationGas } = await this.prepareProposeTx(encodedData, timestamp, opts);
860
921
  const startBlock = await this.l1TxUtils.getBlockNumber();
861
922
  const gasLimit = this.l1TxUtils.bumpGasLimit(BigInt(Math.ceil(Number(simulationResult.gasUsed) * 64 / 63)) + blobEvaluationGas + SequencerPublisher.MULTICALL_OVERHEAD_GAS_GUESS);
862
- // Send the blobs to the blob sink preemptively. This helps in tests where the sequencer mistakingly thinks that the propose
863
- // tx fails but it does get mined. We make sure that the blobs are sent to the blob sink regardless of the tx outcome.
864
- void this.blobSinkClient.sendBlobsToBlobSink(encodedData.blobs).catch((_err)=>{
865
- this.log.error('Failed to send blobs to blob sink');
866
- });
923
+ // Send the blobs to the blob client preemptively. This helps in tests where the sequencer mistakingly thinks that the propose
924
+ // tx fails but it does get mined. We make sure that the blobs are sent to the blob client regardless of the tx outcome.
925
+ void Promise.resolve().then(()=>this.blobClient.sendBlobsToFilestore(encodedData.blobs).catch((_err)=>{
926
+ this.log.error('Failed to send blobs to blob client');
927
+ }));
867
928
  return this.addRequest({
868
929
  action: 'propose',
869
930
  request: {
870
931
  to: this.rollupContract.address,
871
932
  data: rollupData
872
933
  },
873
- lastValidL2Slot: block.header.globalVariables.slotNumber,
934
+ lastValidL2Slot: checkpoint.header.slotNumber,
874
935
  gasConfig: {
875
936
  ...opts,
876
937
  gasLimit
@@ -898,25 +959,23 @@ export class SequencerPublisher {
898
959
  calldataGas,
899
960
  calldataSize,
900
961
  sender,
901
- ...block.getStats(),
962
+ ...checkpoint.getStats(),
902
963
  eventName: 'rollup-published-to-l1',
903
964
  blobCount: encodedData.blobs.length,
904
965
  inclusionBlocks
905
966
  };
906
- this.log.info(`Published L2 block to L1 rollup contract`, {
967
+ this.log.info(`Published checkpoint ${checkpoint.number} at slot ${slot} to rollup contract`, {
907
968
  ...stats,
908
- ...block.getStats(),
909
- ...receipt
969
+ ...checkpoint.getStats(),
970
+ ...pick(receipt, 'transactionHash', 'blockHash')
910
971
  });
911
972
  this.metrics.recordProcessBlockTx(timer.ms(), publishStats);
912
973
  return true;
913
974
  } else {
914
975
  this.metrics.recordFailedTx('process');
915
- this.log.error(`Rollup process tx failed: ${errorMsg ?? 'no error message'}`, undefined, {
916
- ...block.getStats(),
917
- receipt,
918
- txHash: receipt.transactionHash,
919
- slotNumber: block.header.globalVariables.slotNumber
976
+ this.log.error(`Publishing checkpoint at slot ${slot} failed with ${errorMsg ?? 'no error message'}`, undefined, {
977
+ ...checkpoint.getStats(),
978
+ ...receipt
920
979
  });
921
980
  return false;
922
981
  }
@@ -1,12 +1,11 @@
1
- import type { Fr } from '@aztec/foundation/fields';
1
+ import { BlockNumber } from '@aztec/foundation/branded-types';
2
+ import type { Fr } from '@aztec/foundation/curves/bn254';
2
3
  import { DateProvider } from '@aztec/foundation/timer';
3
4
  import { PublicProcessor } from '@aztec/simulator/server';
4
5
  import type { ContractDataSource } from '@aztec/stdlib/contract';
5
- import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
6
6
  import type { BuildBlockResult, FullNodeBlockBuilderConfig, IFullNodeBlockBuilder, MerkleTreeWriteOperations, PublicProcessorLimits, PublicProcessorValidator, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
7
7
  import { GlobalVariables, Tx } from '@aztec/stdlib/tx';
8
8
  import { type TelemetryClient } from '@aztec/telemetry-client';
9
- export declare function buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, l1ToL2Messages: Fr[], newGlobalVariables: GlobalVariables, opts: PublicProcessorLimits | undefined, worldStateFork: MerkleTreeWriteOperations, processor: PublicProcessor, validator: PublicProcessorValidator, l1Constants: Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration'>, dateProvider: DateProvider, telemetryClient?: TelemetryClient): Promise<BuildBlockResult>;
10
9
  export declare class FullNodeBlockBuilder implements IFullNodeBlockBuilder {
11
10
  private config;
12
11
  private worldState;
@@ -22,6 +21,6 @@ export declare class FullNodeBlockBuilder implements IFullNodeBlockBuilder {
22
21
  }>;
23
22
  private syncToPreviousBlock;
24
23
  buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, l1ToL2Messages: Fr[], globalVariables: GlobalVariables, opts: PublicProcessorLimits, suppliedFork?: MerkleTreeWriteOperations): Promise<BuildBlockResult>;
25
- getFork(blockNumber: number): Promise<MerkleTreeWriteOperations>;
24
+ getFork(blockNumber: BlockNumber): Promise<MerkleTreeWriteOperations>;
26
25
  }
27
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tfYnVpbGRlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9ibG9ja19idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBSW5ELE9BQU8sRUFBRSxZQUFZLEVBQWtCLE1BQU0seUJBQXlCLENBQUM7QUFHdkUsT0FBTyxFQUdMLGVBQWUsRUFFaEIsTUFBTSx5QkFBeUIsQ0FBQztBQUVqQyxPQUFPLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUF1QixNQUFNLDZCQUE2QixDQUFDO0FBRTFGLE9BQU8sS0FBSyxFQUNWLGdCQUFnQixFQUNoQiwwQkFBMEIsRUFDMUIscUJBQXFCLEVBQ3JCLHlCQUF5QixFQUN6QixxQkFBcUIsRUFDckIsd0JBQXdCLEVBQ3hCLHNCQUFzQixFQUN2QixNQUFNLGlDQUFpQyxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxlQUFlLEVBQUUsRUFBRSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkQsT0FBTyxFQUFFLEtBQUssZUFBZSxFQUFzQixNQUFNLHlCQUF5QixDQUFDO0FBTW5GLHdCQUFzQixVQUFVLENBQzlCLFVBQVUsRUFBRSxRQUFRLENBQUMsRUFBRSxDQUFDLEdBQUcsYUFBYSxDQUFDLEVBQUUsQ0FBQyxFQUM1QyxjQUFjLEVBQUUsRUFBRSxFQUFFLEVBQ3BCLGtCQUFrQixFQUFFLGVBQWUsRUFDbkMsSUFBSSxtQ0FBNEIsRUFDaEMsY0FBYyxFQUFFLHlCQUF5QixFQUN6QyxTQUFTLEVBQUUsZUFBZSxFQUMxQixTQUFTLEVBQUUsd0JBQXdCLEVBQ25DLFdBQVcsRUFBRSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsZUFBZSxHQUFHLGNBQWMsQ0FBQyxFQUN0RSxZQUFZLEVBQUUsWUFBWSxFQUMxQixlQUFlLEdBQUUsZUFBc0MsR0FDdEQsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBNEMzQjtBQVdELHFCQUFhLG9CQUFxQixZQUFXLHFCQUFxQjtJQUU5RCxPQUFPLENBQUMsTUFBTTtJQUNkLE9BQU8sQ0FBQyxVQUFVO0lBQ2xCLE9BQU8sQ0FBQyxrQkFBa0I7SUFDMUIsT0FBTyxDQUFDLFlBQVk7SUFDcEIsT0FBTyxDQUFDLGVBQWU7SUFMekIsWUFDVSxNQUFNLEVBQUUsMEJBQTBCLEVBQ2xDLFVBQVUsRUFBRSxzQkFBc0IsRUFDbEMsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQ3RDLFlBQVksRUFBRSxZQUFZLEVBQzFCLGVBQWUsR0FBRSxlQUFzQyxFQUM3RDtJQUVHLFNBQVMsSUFBSSwwQkFBMEIsQ0FFN0M7SUFFTSxZQUFZLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxRQUU5RDtJQUVZLG9CQUFvQixDQUFDLGVBQWUsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLHlCQUF5Qjs7O09BMENsRztZQUVhLG1CQUFtQjtJQVUzQixVQUFVLENBQ2QsVUFBVSxFQUFFLFFBQVEsQ0FBQyxFQUFFLENBQUMsR0FBRyxhQUFhLENBQUMsRUFBRSxDQUFDLEVBQzVDLGNBQWMsRUFBRSxFQUFFLEVBQUUsRUFDcEIsZUFBZSxFQUFFLGVBQWUsRUFDaEMsSUFBSSxFQUFFLHFCQUFxQixFQUMzQixZQUFZLENBQUMsRUFBRSx5QkFBeUIsR0FDdkMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBc0MzQjtJQUVELE9BQU8sQ0FBQyxXQUFXLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQyxDQUUvRDtDQUNGIn0=
26
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tfYnVpbGRlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9ibG9ja19idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUU5RCxPQUFPLEtBQUssRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUl6RCxPQUFPLEVBQUUsWUFBWSxFQUFrQixNQUFNLHlCQUF5QixDQUFDO0FBR3ZFLE9BQU8sRUFHTCxlQUFlLEVBRWhCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUdqRSxPQUFPLEtBQUssRUFDVixnQkFBZ0IsRUFDaEIsMEJBQTBCLEVBQzFCLHFCQUFxQixFQUNyQix5QkFBeUIsRUFDekIscUJBQXFCLEVBQ3JCLHdCQUF3QixFQUN4QixzQkFBc0IsRUFDdkIsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsZUFBZSxFQUFFLEVBQUUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxLQUFLLGVBQWUsRUFBc0IsTUFBTSx5QkFBeUIsQ0FBQztBQTJFbkYscUJBQWEsb0JBQXFCLFlBQVcscUJBQXFCO0lBRTlELE9BQU8sQ0FBQyxNQUFNO0lBQ2QsT0FBTyxDQUFDLFVBQVU7SUFDbEIsT0FBTyxDQUFDLGtCQUFrQjtJQUMxQixPQUFPLENBQUMsWUFBWTtJQUNwQixPQUFPLENBQUMsZUFBZTtJQUx6QixZQUNVLE1BQU0sRUFBRSwwQkFBMEIsRUFDbEMsVUFBVSxFQUFFLHNCQUFzQixFQUNsQyxrQkFBa0IsRUFBRSxrQkFBa0IsRUFDdEMsWUFBWSxFQUFFLFlBQVksRUFDMUIsZUFBZSxHQUFFLGVBQXNDLEVBQzdEO0lBRUcsU0FBUyxJQUFJLDBCQUEwQixDQUU3QztJQUVNLFlBQVksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLDBCQUEwQixDQUFDLFFBRTlEO0lBRVksb0JBQW9CLENBQUMsZUFBZSxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUseUJBQXlCOzs7T0FrQ2xHO1lBRWEsbUJBQW1CO0lBVTNCLFVBQVUsQ0FDZCxVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxFQUFFLENBQUMsRUFDNUMsY0FBYyxFQUFFLEVBQUUsRUFBRSxFQUNwQixlQUFlLEVBQUUsZUFBZSxFQUNoQyxJQUFJLEVBQUUscUJBQXFCLEVBQzNCLFlBQVksQ0FBQyxFQUFFLHlCQUF5QixHQUN2QyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FzQzNCO0lBRUQsT0FBTyxDQUFDLFdBQVcsRUFBRSxXQUFXLEdBQUcsT0FBTyxDQUFDLHlCQUF5QixDQUFDLENBRXBFO0NBQ0YifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"block_builder.d.ts","sourceRoot":"","sources":["../../src/sequencer/block_builder.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAInD,OAAO,EAAE,YAAY,EAAkB,MAAM,yBAAyB,CAAC;AAGvE,OAAO,EAGL,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,KAAK,iBAAiB,EAAuB,MAAM,6BAA6B,CAAC;AAE1F,OAAO,KAAK,EACV,gBAAgB,EAChB,0BAA0B,EAC1B,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAMnF,wBAAsB,UAAU,CAC9B,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,EAAE,CAAC,EAC5C,cAAc,EAAE,EAAE,EAAE,EACpB,kBAAkB,EAAE,eAAe,EACnC,IAAI,mCAA4B,EAChC,cAAc,EAAE,yBAAyB,EACzC,SAAS,EAAE,eAAe,EAC1B,SAAS,EAAE,wBAAwB,EACnC,WAAW,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,GAAG,cAAc,CAAC,EACtE,YAAY,EAAE,YAAY,EAC1B,eAAe,GAAE,eAAsC,GACtD,OAAO,CAAC,gBAAgB,CAAC,CA4C3B;AAWD,qBAAa,oBAAqB,YAAW,qBAAqB;IAE9D,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,eAAe;IALzB,YACU,MAAM,EAAE,0BAA0B,EAClC,UAAU,EAAE,sBAAsB,EAClC,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,EAC1B,eAAe,GAAE,eAAsC,EAC7D;IAEG,SAAS,IAAI,0BAA0B,CAE7C;IAEM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,0BAA0B,CAAC,QAE9D;IAEY,oBAAoB,CAAC,eAAe,EAAE,eAAe,EAAE,IAAI,EAAE,yBAAyB;;;OA0ClG;YAEa,mBAAmB;IAU3B,UAAU,CACd,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,EAAE,CAAC,EAC5C,cAAc,EAAE,EAAE,EAAE,EACpB,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,qBAAqB,EAC3B,YAAY,CAAC,EAAE,yBAAyB,GACvC,OAAO,CAAC,gBAAgB,CAAC,CAsC3B;IAED,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAE/D;CACF"}
1
+ {"version":3,"file":"block_builder.d.ts","sourceRoot":"","sources":["../../src/sequencer/block_builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAIzD,OAAO,EAAE,YAAY,EAAkB,MAAM,yBAAyB,CAAC;AAGvE,OAAO,EAGL,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,OAAO,KAAK,EACV,gBAAgB,EAChB,0BAA0B,EAC1B,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AA2EnF,qBAAa,oBAAqB,YAAW,qBAAqB;IAE9D,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,eAAe;IALzB,YACU,MAAM,EAAE,0BAA0B,EAClC,UAAU,EAAE,sBAAsB,EAClC,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,EAC1B,eAAe,GAAE,eAAsC,EAC7D;IAEG,SAAS,IAAI,0BAA0B,CAE7C;IAEM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,0BAA0B,CAAC,QAE9D;IAEY,oBAAoB,CAAC,eAAe,EAAE,eAAe,EAAE,IAAI,EAAE,yBAAyB;;;OAkClG;YAEa,mBAAmB;IAU3B,UAAU,CACd,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,EAAE,CAAC,EAC5C,cAAc,EAAE,EAAE,EAAE,EACpB,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,qBAAqB,EAC3B,YAAY,CAAC,EAAE,yBAAyB,GACvC,OAAO,CAAC,gBAAgB,CAAC,CAsC3B;IAED,OAAO,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAEpE;CACF"}
@@ -1,4 +1,5 @@
1
1
  import { MerkleTreeId } from '@aztec/aztec.js/trees';
2
+ import { BlockNumber } from '@aztec/foundation/branded-types';
2
3
  import { merge, pick } from '@aztec/foundation/collection';
3
4
  import { createLogger } from '@aztec/foundation/log';
4
5
  import { retryUntil } from '@aztec/foundation/retry';
@@ -6,14 +7,13 @@ import { bufferToHex } from '@aztec/foundation/string';
6
7
  import { Timer, elapsed } from '@aztec/foundation/timer';
7
8
  import { getDefaultAllowedSetupFunctions } from '@aztec/p2p/msg_validators';
8
9
  import { LightweightBlockFactory } from '@aztec/prover-client/block-factory';
9
- import { GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, TelemetryPublicTxSimulator } from '@aztec/simulator/server';
10
- import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
10
+ import { GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, createPublicTxSimulatorForBlockBuilding } from '@aztec/simulator/server';
11
11
  import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
12
12
  import { Gas } from '@aztec/stdlib/gas';
13
13
  import { getTelemetryClient } from '@aztec/telemetry-client';
14
14
  import { createValidatorForBlockBuilding } from '../tx_validator/tx_validator_factory.js';
15
15
  const log = createLogger('block-builder');
16
- export async function buildBlock(pendingTxs, l1ToL2Messages, newGlobalVariables, opts = {}, worldStateFork, processor, validator, l1Constants, dateProvider, telemetryClient = getTelemetryClient()) {
16
+ /** Builds a block out of pending txs */ async function buildBlock(pendingTxs, l1ToL2Messages, newGlobalVariables, opts = {}, worldStateFork, processor, validator, l1Constants, dateProvider, telemetryClient = getTelemetryClient()) {
17
17
  const blockBuildingTimer = new Timer();
18
18
  const blockNumber = newGlobalVariables.blockNumber;
19
19
  const slot = newGlobalVariables.slotNumber;
@@ -57,8 +57,10 @@ const FullNodeBlockBuilderConfigKeys = [
57
57
  'l1ChainId',
58
58
  'rollupVersion',
59
59
  'txPublicSetupAllowList',
60
- 'fakeProcessingDelayPerTxMs'
60
+ 'fakeProcessingDelayPerTxMs',
61
+ 'fakeThrowAfterProcessingTxCount'
61
62
  ];
63
+ // TODO(palla/mbps): Try killing this in favor of the CheckpointsBuilder
62
64
  export class FullNodeBlockBuilder {
63
65
  config;
64
66
  worldState;
@@ -82,14 +84,7 @@ export class FullNodeBlockBuilder {
82
84
  const txPublicSetupAllowList = this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
83
85
  const contractsDB = new PublicContractsDB(this.contractDataSource);
84
86
  const guardedFork = new GuardedMerkleTreeOperations(fork);
85
- const publicTxSimulator = new TelemetryPublicTxSimulator(guardedFork, contractsDB, globalVariables, this.telemetryClient, PublicSimulatorConfig.from({
86
- skipFeeEnforcement: false,
87
- collectDebugLogs: false,
88
- collectHints: false,
89
- maxDebugLogMemoryReads: 0,
90
- collectStatistics: false,
91
- collectCallMetadata: false
92
- }));
87
+ const publicTxSimulator = createPublicTxSimulatorForBlockBuilding(guardedFork, contractsDB, globalVariables, this.telemetryClient);
93
88
  const processor = new PublicProcessor(globalVariables, guardedFork, contractsDB, publicTxSimulator, this.dateProvider, this.telemetryClient, undefined, this.config);
94
89
  const validator = createValidatorForBlockBuilding(fork, this.contractDataSource, globalVariables, txPublicSetupAllowList);
95
90
  return {
@@ -102,7 +97,7 @@ export class FullNodeBlockBuilder {
102
97
  log.debug(`Synced to previous block ${parentBlockNumber}`);
103
98
  }
104
99
  async buildBlock(pendingTxs, l1ToL2Messages, globalVariables, opts, suppliedFork) {
105
- const parentBlockNumber = globalVariables.blockNumber - 1;
100
+ const parentBlockNumber = BlockNumber(globalVariables.blockNumber - 1);
106
101
  const syncTimeout = opts.deadline ? (opts.deadline.getTime() - this.dateProvider.now()) / 1000 : undefined;
107
102
  await this.syncToPreviousBlock(parentBlockNumber, syncTimeout);
108
103
  const fork = suppliedFork ?? await this.worldState.fork(parentBlockNumber);
@@ -0,0 +1,63 @@
1
+ import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
2
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
+ import { DateProvider, Timer } from '@aztec/foundation/timer';
4
+ import { LightweightCheckpointBuilder } from '@aztec/prover-client/light';
5
+ import { PublicProcessor } from '@aztec/simulator/server';
6
+ import { L2BlockNew } from '@aztec/stdlib/block';
7
+ import { Checkpoint } from '@aztec/stdlib/checkpoint';
8
+ import type { ContractDataSource } from '@aztec/stdlib/contract';
9
+ import { Gas } from '@aztec/stdlib/gas';
10
+ import { type FullNodeBlockBuilderConfig, type MerkleTreeWriteOperations, type PublicProcessorLimits } from '@aztec/stdlib/interfaces/server';
11
+ import { type CheckpointGlobalVariables, type FailedTx, GlobalVariables, Tx } from '@aztec/stdlib/tx';
12
+ import { type TelemetryClient } from '@aztec/telemetry-client';
13
+ export interface BuildBlockInCheckpointResult {
14
+ block: L2BlockNew;
15
+ publicGas: Gas;
16
+ publicProcessorDuration: number;
17
+ numTxs: number;
18
+ failedTxs: FailedTx[];
19
+ blockBuildingTimer: Timer;
20
+ usedTxs: Tx[];
21
+ }
22
+ /**
23
+ * Builder for a single checkpoint. Handles building blocks within the checkpoint
24
+ * and completing it.
25
+ */
26
+ export declare class CheckpointBuilder {
27
+ private checkpointBuilder;
28
+ private fork;
29
+ private config;
30
+ private contractDataSource;
31
+ private dateProvider;
32
+ private telemetryClient;
33
+ constructor(checkpointBuilder: LightweightCheckpointBuilder, fork: MerkleTreeWriteOperations, config: FullNodeBlockBuilderConfig, contractDataSource: ContractDataSource, dateProvider: DateProvider, telemetryClient: TelemetryClient);
34
+ getConstantData(): CheckpointGlobalVariables;
35
+ /**
36
+ * Builds a single block within this checkpoint.
37
+ */
38
+ buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, blockNumber: BlockNumber, timestamp: bigint, opts: PublicProcessorLimits): Promise<BuildBlockInCheckpointResult>;
39
+ /** Completes the checkpoint and returns it. */
40
+ completeCheckpoint(): Promise<Checkpoint>;
41
+ /** Gets the checkpoint currently in progress. */
42
+ getCheckpoint(): Promise<Checkpoint>;
43
+ protected makeBlockBuilderDeps(globalVariables: GlobalVariables, fork: MerkleTreeWriteOperations): Promise<{
44
+ processor: PublicProcessor;
45
+ validator: import("@aztec/stdlib/interfaces/server").PublicProcessorValidator;
46
+ }>;
47
+ }
48
+ /**
49
+ * Factory for creating checkpoint builders.
50
+ */
51
+ export declare class FullNodeCheckpointsBuilder {
52
+ private config;
53
+ private contractDataSource;
54
+ private dateProvider;
55
+ private telemetryClient;
56
+ constructor(config: FullNodeBlockBuilderConfig, contractDataSource: ContractDataSource, dateProvider: DateProvider, telemetryClient?: TelemetryClient);
57
+ updateConfig(config: Partial<FullNodeBlockBuilderConfig>): void;
58
+ /**
59
+ * Starts a new checkpoint and returns a CheckpointBuilder to build blocks within it.
60
+ */
61
+ startCheckpoint(checkpointNumber: CheckpointNumber, constants: CheckpointGlobalVariables, l1ToL2Messages: Fr[], fork: MerkleTreeWriteOperations): Promise<CheckpointBuilder>;
62
+ }
63
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludF9idWlsZGVyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VxdWVuY2VyL2NoZWNrcG9pbnRfYnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFaEYsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBR3BELE9BQU8sRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFXLE1BQU0seUJBQXlCLENBQUM7QUFFdkUsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDMUUsT0FBTyxFQUdMLGVBQWUsRUFFaEIsTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDakQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3RELE9BQU8sS0FBSyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDakUsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3hDLE9BQU8sRUFDTCxLQUFLLDBCQUEwQixFQUUvQixLQUFLLHlCQUF5QixFQUM5QixLQUFLLHFCQUFxQixFQUMzQixNQUFNLGlDQUFpQyxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxLQUFLLHlCQUF5QixFQUFFLEtBQUssUUFBUSxFQUFFLGVBQWUsRUFBRSxFQUFFLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN0RyxPQUFPLEVBQUUsS0FBSyxlQUFlLEVBQXNCLE1BQU0seUJBQXlCLENBQUM7QUFNbkYsTUFBTSxXQUFXLDRCQUE0QjtJQUMzQyxLQUFLLEVBQUUsVUFBVSxDQUFDO0lBQ2xCLFNBQVMsRUFBRSxHQUFHLENBQUM7SUFDZix1QkFBdUIsRUFBRSxNQUFNLENBQUM7SUFDaEMsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUNmLFNBQVMsRUFBRSxRQUFRLEVBQUUsQ0FBQztJQUN0QixrQkFBa0IsRUFBRSxLQUFLLENBQUM7SUFDMUIsT0FBTyxFQUFFLEVBQUUsRUFBRSxDQUFDO0NBQ2Y7QUFFRDs7O0dBR0c7QUFDSCxxQkFBYSxpQkFBaUI7SUFFMUIsT0FBTyxDQUFDLGlCQUFpQjtJQUN6QixPQUFPLENBQUMsSUFBSTtJQUNaLE9BQU8sQ0FBQyxNQUFNO0lBQ2QsT0FBTyxDQUFDLGtCQUFrQjtJQUMxQixPQUFPLENBQUMsWUFBWTtJQUNwQixPQUFPLENBQUMsZUFBZTtJQU56QixZQUNVLGlCQUFpQixFQUFFLDRCQUE0QixFQUMvQyxJQUFJLEVBQUUseUJBQXlCLEVBQy9CLE1BQU0sRUFBRSwwQkFBMEIsRUFDbEMsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQ3RDLFlBQVksRUFBRSxZQUFZLEVBQzFCLGVBQWUsRUFBRSxlQUFlLEVBQ3RDO0lBRUosZUFBZSxJQUFJLHlCQUF5QixDQUUzQztJQUVEOztPQUVHO0lBQ0csVUFBVSxDQUNkLFVBQVUsRUFBRSxRQUFRLENBQUMsRUFBRSxDQUFDLEdBQUcsYUFBYSxDQUFDLEVBQUUsQ0FBQyxFQUM1QyxXQUFXLEVBQUUsV0FBVyxFQUN4QixTQUFTLEVBQUUsTUFBTSxFQUNqQixJQUFJLEVBQUUscUJBQXFCLEdBQzFCLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBQyxDQXdDdkM7SUFFRCwrQ0FBK0M7SUFDekMsa0JBQWtCLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQVU5QztJQUVELGlEQUFpRDtJQUNqRCxhQUFhLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUVuQztJQUVELFVBQWdCLG9CQUFvQixDQUFDLGVBQWUsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLHlCQUF5Qjs7O09Ba0NyRztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxxQkFBYSwwQkFBMEI7SUFFbkMsT0FBTyxDQUFDLE1BQU07SUFDZCxPQUFPLENBQUMsa0JBQWtCO0lBQzFCLE9BQU8sQ0FBQyxZQUFZO0lBQ3BCLE9BQU8sQ0FBQyxlQUFlO0lBSnpCLFlBQ1UsTUFBTSxFQUFFLDBCQUEwQixFQUNsQyxrQkFBa0IsRUFBRSxrQkFBa0IsRUFDdEMsWUFBWSxFQUFFLFlBQVksRUFDMUIsZUFBZSxHQUFFLGVBQXNDLEVBQzdEO0lBRUcsWUFBWSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsMEJBQTBCLENBQUMsUUFFOUQ7SUFFRDs7T0FFRztJQUNHLGVBQWUsQ0FDbkIsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQ2xDLFNBQVMsRUFBRSx5QkFBeUIsRUFDcEMsY0FBYyxFQUFFLEVBQUUsRUFBRSxFQUNwQixJQUFJLEVBQUUseUJBQXlCLEdBQzlCLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQTJCNUI7Q0FDRiJ9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint_builder.d.ts","sourceRoot":"","sources":["../../src/sequencer/checkpoint_builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEhF,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAGpD,OAAO,EAAE,YAAY,EAAE,KAAK,EAAW,MAAM,yBAAyB,CAAC;AAEvE,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAGL,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACxC,OAAO,EACL,KAAK,0BAA0B,EAE/B,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,KAAK,yBAAyB,EAAE,KAAK,QAAQ,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtG,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAMnF,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,GAAG,CAAC;IACf,uBAAuB,EAAE,MAAM,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,kBAAkB,EAAE,KAAK,CAAC;IAC1B,OAAO,EAAE,EAAE,EAAE,CAAC;CACf;AAED;;;GAGG;AACH,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,iBAAiB;IACzB,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,eAAe;IANzB,YACU,iBAAiB,EAAE,4BAA4B,EAC/C,IAAI,EAAE,yBAAyB,EAC/B,MAAM,EAAE,0BAA0B,EAClC,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,EAC1B,eAAe,EAAE,eAAe,EACtC;IAEJ,eAAe,IAAI,yBAAyB,CAE3C;IAED;;OAEG;IACG,UAAU,CACd,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,EAAE,CAAC,EAC5C,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,4BAA4B,CAAC,CAwCvC;IAED,+CAA+C;IACzC,kBAAkB,IAAI,OAAO,CAAC,UAAU,CAAC,CAU9C;IAED,iDAAiD;IACjD,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CAEnC;IAED,UAAgB,oBAAoB,CAAC,eAAe,EAAE,eAAe,EAAE,IAAI,EAAE,yBAAyB;;;OAkCrG;CACF;AAED;;GAEG;AACH,qBAAa,0BAA0B;IAEnC,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,eAAe;IAJzB,YACU,MAAM,EAAE,0BAA0B,EAClC,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,EAC1B,eAAe,GAAE,eAAsC,EAC7D;IAEG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,0BAA0B,CAAC,QAE9D;IAED;;OAEG;IACG,eAAe,CACnB,gBAAgB,EAAE,gBAAgB,EAClC,SAAS,EAAE,yBAAyB,EACpC,cAAc,EAAE,EAAE,EAAE,EACpB,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,iBAAiB,CAAC,CA2B5B;CACF"}