@aztec/sequencer-client 0.0.1-commit.d3ec352c → 0.0.1-commit.fcb71a6

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 (93) 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 +18 -9
  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 +32 -25
  22. package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
  23. package/dest/publisher/sequencer-publisher.js +122 -65
  24. package/dest/sequencer/block_builder.d.ts +2 -4
  25. package/dest/sequencer/block_builder.d.ts.map +1 -1
  26. package/dest/sequencer/block_builder.js +6 -11
  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 +218 -574
  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.js +1 -1
  68. package/package.json +27 -27
  69. package/src/client/sequencer-client.ts +28 -38
  70. package/src/config.ts +73 -34
  71. package/src/global_variable_builder/global_builder.ts +52 -48
  72. package/src/index.ts +2 -0
  73. package/src/publisher/config.ts +12 -9
  74. package/src/publisher/sequencer-publisher-factory.ts +5 -4
  75. package/src/publisher/sequencer-publisher-metrics.ts +2 -2
  76. package/src/publisher/sequencer-publisher.ts +180 -84
  77. package/src/sequencer/README.md +531 -0
  78. package/src/sequencer/block_builder.ts +7 -12
  79. package/src/sequencer/checkpoint_builder.ts +217 -0
  80. package/src/sequencer/checkpoint_proposal_job.ts +706 -0
  81. package/src/sequencer/checkpoint_voter.ts +105 -0
  82. package/src/sequencer/config.ts +2 -1
  83. package/src/sequencer/events.ts +27 -0
  84. package/src/sequencer/index.ts +4 -0
  85. package/src/sequencer/metrics.ts +203 -1
  86. package/src/sequencer/sequencer.ts +322 -779
  87. package/src/sequencer/timetable.ts +173 -79
  88. package/src/sequencer/types.ts +6 -0
  89. package/src/sequencer/utils.ts +18 -9
  90. package/src/test/index.ts +3 -1
  91. package/src/test/mock_checkpoint_builder.ts +247 -0
  92. package/src/test/utils.ts +137 -0
  93. package/src/tx_validator/tx_validator_factory.ts +1 -1
@@ -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
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();
@@ -378,34 +431,29 @@ export class SequencerPublisher {
378
431
  throw new Error(`Unknown reason for invalidation`);
379
432
  }
380
433
  }
381
- /**
382
- * @notice Will simulate `propose` to make sure that the block is valid for submission
383
- *
384
- * @dev Throws if unable to propose
385
- *
386
- * @param block - The block to propose
387
- * @param attestationData - The block's attestation data
388
- *
389
- */ 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) {
390
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?
391
437
  // If we have no attestations, we still need to provide the empty attestations
392
438
  // so that the committee is recalculated correctly
393
- const ignoreSignatures = attestationsAndSigners.attestations.length === 0;
394
- if (ignoreSignatures) {
395
- const { committee } = await this.epochCache.getCommittee(block.header.globalVariables.slotNumber);
396
- if (!committee) {
397
- this.log.warn(`No committee found for slot ${block.header.globalVariables.slotNumber}`);
398
- throw new Error(`No committee found for slot ${block.header.globalVariables.slotNumber}`);
399
- }
400
- attestationsAndSigners.attestations = committee.map((committeeMember)=>CommitteeAttestation.fromAddress(committeeMember));
401
- }
402
- 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();
403
451
  const blobs = getBlobsPerL1Block(blobFields);
404
452
  const blobInput = getPrefixedEthBlobCommitments(blobs);
405
453
  const args = [
406
454
  {
407
- header: block.getCheckpointHeader().toViem(),
408
- archive: toHex(block.archive.root.toBuffer()),
455
+ header: checkpoint.header.toViem(),
456
+ archive: toHex(checkpoint.archive.root.toBuffer()),
409
457
  oracleInput: {
410
458
  feeAssetPriceModifier: 0n
411
459
  }
@@ -432,9 +480,16 @@ export class SequencerPublisher {
432
480
  }
433
481
  const round = await base.computeRound(slotNumber);
434
482
  const roundInfo = await base.getRoundInfo(this.rollupContract.address, round);
483
+ if (roundInfo.quorumReached) {
484
+ return false;
485
+ }
435
486
  if (roundInfo.lastSignalSlot >= slotNumber) {
436
487
  return false;
437
488
  }
489
+ if (await this.isPayloadEmpty(payload)) {
490
+ this.log.warn(`Skipping vote cast for payload with empty code`);
491
+ return false;
492
+ }
438
493
  const cachedLastVote = this.lastActions[signalType];
439
494
  this.lastActions[signalType] = slotNumber;
440
495
  const action = signalType;
@@ -473,17 +528,27 @@ export class SequencerPublisher {
473
528
  payload: payload.toString()
474
529
  };
475
530
  if (!success) {
476
- 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);
477
532
  this.lastActions[signalType] = cachedLastVote;
478
533
  return false;
479
534
  } else {
480
- 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);
481
536
  return true;
482
537
  }
483
538
  }
484
539
  });
485
540
  return true;
486
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
+ }
487
552
  /**
488
553
  * Enqueues a governance castSignal transaction to cast a signal for a given slot number.
489
554
  * @param slotNumber - The slot number to cast a signal for.
@@ -579,19 +644,13 @@ export class SequencerPublisher {
579
644
  }
580
645
  return true;
581
646
  }
582
- /**
583
- * Proposes a L2 block on L1.
584
- *
585
- * @param block - L2 block to propose.
586
- * @returns True if the tx has been enqueued, throws otherwise. See #9315
587
- */ async enqueueProposeL2Block(block, attestationsAndSigners, attestationsAndSignersSignature, opts = {}) {
588
- const checkpointHeader = block.getCheckpointHeader();
589
- 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();
590
650
  const blobs = getBlobsPerL1Block(blobFields);
591
651
  const proposeTxArgs = {
592
652
  header: checkpointHeader,
593
- archive: block.archive.root.toBuffer(),
594
- body: block.body.toBuffer(),
653
+ archive: checkpoint.archive.root.toBuffer(),
595
654
  blobs,
596
655
  attestationsAndSigners,
597
656
  attestationsAndSignersSignature
@@ -603,21 +662,20 @@ export class SequencerPublisher {
603
662
  // By simulation issue, I mean the fact that the block.timestamp is equal to the last block, not the next, which
604
663
  // make time consistency checks break.
605
664
  // TODO(palla): Check whether we're validating twice, once here and once within addProposeTx, since we call simulateProposeTx in both places.
606
- ts = await this.validateBlockForSubmission(block, attestationsAndSigners, attestationsAndSignersSignature, opts);
665
+ ts = await this.validateCheckpointForSubmission(checkpoint, attestationsAndSigners, attestationsAndSignersSignature, opts);
607
666
  } catch (err) {
608
- this.log.error(`Block validation failed. ${err instanceof Error ? err.message : 'No error message'}`, err, {
609
- ...block.getStats(),
610
- 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,
611
670
  forcePendingBlockNumber: opts.forcePendingBlockNumber
612
671
  });
613
672
  throw err;
614
673
  }
615
- this.log.verbose(`Enqueuing block propose transaction`, {
616
- ...block.toBlockInfo(),
674
+ this.log.verbose(`Enqueuing checkpoint propose transaction`, {
675
+ ...checkpoint.toCheckpointInfo(),
617
676
  ...opts
618
677
  });
619
- await this.addProposeTx(block, proposeTxArgs, opts, ts);
620
- return true;
678
+ await this.addProposeTx(checkpoint, proposeTxArgs, opts, ts);
621
679
  }
622
680
  enqueueInvalidateBlock(request, opts = {}) {
623
681
  if (!request) {
@@ -855,24 +913,25 @@ export class SequencerPublisher {
855
913
  simulationResult
856
914
  };
857
915
  }
858
- async addProposeTx(block, encodedData, opts = {}, timestamp) {
916
+ async addProposeTx(checkpoint, encodedData, opts = {}, timestamp) {
917
+ const slot = checkpoint.header.slotNumber;
859
918
  const timer = new Timer();
860
919
  const kzg = Blob.getViemKzgInstance();
861
920
  const { rollupData, simulationResult, blobEvaluationGas } = await this.prepareProposeTx(encodedData, timestamp, opts);
862
921
  const startBlock = await this.l1TxUtils.getBlockNumber();
863
922
  const gasLimit = this.l1TxUtils.bumpGasLimit(BigInt(Math.ceil(Number(simulationResult.gasUsed) * 64 / 63)) + blobEvaluationGas + SequencerPublisher.MULTICALL_OVERHEAD_GAS_GUESS);
864
- // Send the blobs to the blob sink preemptively. This helps in tests where the sequencer mistakingly thinks that the propose
865
- // tx fails but it does get mined. We make sure that the blobs are sent to the blob sink regardless of the tx outcome.
866
- void this.blobSinkClient.sendBlobsToBlobSink(encodedData.blobs).catch((_err)=>{
867
- this.log.error('Failed to send blobs to blob sink');
868
- });
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
+ }));
869
928
  return this.addRequest({
870
929
  action: 'propose',
871
930
  request: {
872
931
  to: this.rollupContract.address,
873
932
  data: rollupData
874
933
  },
875
- lastValidL2Slot: block.header.globalVariables.slotNumber,
934
+ lastValidL2Slot: checkpoint.header.slotNumber,
876
935
  gasConfig: {
877
936
  ...opts,
878
937
  gasLimit
@@ -900,25 +959,23 @@ export class SequencerPublisher {
900
959
  calldataGas,
901
960
  calldataSize,
902
961
  sender,
903
- ...block.getStats(),
962
+ ...checkpoint.getStats(),
904
963
  eventName: 'rollup-published-to-l1',
905
964
  blobCount: encodedData.blobs.length,
906
965
  inclusionBlocks
907
966
  };
908
- this.log.info(`Published L2 block to L1 rollup contract`, {
967
+ this.log.info(`Published checkpoint ${checkpoint.number} at slot ${slot} to rollup contract`, {
909
968
  ...stats,
910
- ...block.getStats(),
911
- ...receipt
969
+ ...checkpoint.getStats(),
970
+ ...pick(receipt, 'transactionHash', 'blockHash')
912
971
  });
913
972
  this.metrics.recordProcessBlockTx(timer.ms(), publishStats);
914
973
  return true;
915
974
  } else {
916
975
  this.metrics.recordFailedTx('process');
917
- this.log.error(`Rollup process tx failed: ${errorMsg ?? 'no error message'}`, undefined, {
918
- ...block.getStats(),
919
- receipt,
920
- txHash: receipt.transactionHash,
921
- 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
922
979
  });
923
980
  return false;
924
981
  }
@@ -1,13 +1,11 @@
1
1
  import { BlockNumber } from '@aztec/foundation/branded-types';
2
- import type { Fr } from '@aztec/foundation/fields';
2
+ import type { Fr } from '@aztec/foundation/curves/bn254';
3
3
  import { DateProvider } from '@aztec/foundation/timer';
4
4
  import { PublicProcessor } from '@aztec/simulator/server';
5
5
  import type { ContractDataSource } from '@aztec/stdlib/contract';
6
- import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
7
6
  import type { BuildBlockResult, FullNodeBlockBuilderConfig, IFullNodeBlockBuilder, MerkleTreeWriteOperations, PublicProcessorLimits, PublicProcessorValidator, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
8
7
  import { GlobalVariables, Tx } from '@aztec/stdlib/tx';
9
8
  import { type TelemetryClient } from '@aztec/telemetry-client';
10
- 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>;
11
9
  export declare class FullNodeBlockBuilder implements IFullNodeBlockBuilder {
12
10
  private config;
13
11
  private worldState;
@@ -25,4 +23,4 @@ export declare class FullNodeBlockBuilder implements IFullNodeBlockBuilder {
25
23
  buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, l1ToL2Messages: Fr[], globalVariables: GlobalVariables, opts: PublicProcessorLimits, suppliedFork?: MerkleTreeWriteOperations): Promise<BuildBlockResult>;
26
24
  getFork(blockNumber: BlockNumber): Promise<MerkleTreeWriteOperations>;
27
25
  }
28
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tfYnVpbGRlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9ibG9ja19idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUU5RCxPQUFPLEtBQUssRUFBRSxFQUFFLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUluRCxPQUFPLEVBQUUsWUFBWSxFQUFrQixNQUFNLHlCQUF5QixDQUFDO0FBR3ZFLE9BQU8sRUFHTCxlQUFlLEVBRWhCLE1BQU0seUJBQXlCLENBQUM7QUFFakMsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNqRSxPQUFPLEVBQUUsS0FBSyxpQkFBaUIsRUFBdUIsTUFBTSw2QkFBNkIsQ0FBQztBQUUxRixPQUFPLEtBQUssRUFDVixnQkFBZ0IsRUFDaEIsMEJBQTBCLEVBQzFCLHFCQUFxQixFQUNyQix5QkFBeUIsRUFDekIscUJBQXFCLEVBQ3JCLHdCQUF3QixFQUN4QixzQkFBc0IsRUFDdkIsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsZUFBZSxFQUFFLEVBQUUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxLQUFLLGVBQWUsRUFBc0IsTUFBTSx5QkFBeUIsQ0FBQztBQU1uRix3QkFBc0IsVUFBVSxDQUM5QixVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxFQUFFLENBQUMsRUFDNUMsY0FBYyxFQUFFLEVBQUUsRUFBRSxFQUNwQixrQkFBa0IsRUFBRSxlQUFlLEVBQ25DLElBQUksbUNBQTRCLEVBQ2hDLGNBQWMsRUFBRSx5QkFBeUIsRUFDekMsU0FBUyxFQUFFLGVBQWUsRUFDMUIsU0FBUyxFQUFFLHdCQUF3QixFQUNuQyxXQUFXLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixFQUFFLGVBQWUsR0FBRyxjQUFjLENBQUMsRUFDdEUsWUFBWSxFQUFFLFlBQVksRUFDMUIsZUFBZSxHQUFFLGVBQXNDLEdBQ3RELE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQTRDM0I7QUFXRCxxQkFBYSxvQkFBcUIsWUFBVyxxQkFBcUI7SUFFOUQsT0FBTyxDQUFDLE1BQU07SUFDZCxPQUFPLENBQUMsVUFBVTtJQUNsQixPQUFPLENBQUMsa0JBQWtCO0lBQzFCLE9BQU8sQ0FBQyxZQUFZO0lBQ3BCLE9BQU8sQ0FBQyxlQUFlO0lBTHpCLFlBQ1UsTUFBTSxFQUFFLDBCQUEwQixFQUNsQyxVQUFVLEVBQUUsc0JBQXNCLEVBQ2xDLGtCQUFrQixFQUFFLGtCQUFrQixFQUN0QyxZQUFZLEVBQUUsWUFBWSxFQUMxQixlQUFlLEdBQUUsZUFBc0MsRUFDN0Q7SUFFRyxTQUFTLElBQUksMEJBQTBCLENBRTdDO0lBRU0sWUFBWSxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsMEJBQTBCLENBQUMsUUFFOUQ7SUFFWSxvQkFBb0IsQ0FBQyxlQUFlLEVBQUUsZUFBZSxFQUFFLElBQUksRUFBRSx5QkFBeUI7OztPQXlDbEc7WUFFYSxtQkFBbUI7SUFVM0IsVUFBVSxDQUNkLFVBQVUsRUFBRSxRQUFRLENBQUMsRUFBRSxDQUFDLEdBQUcsYUFBYSxDQUFDLEVBQUUsQ0FBQyxFQUM1QyxjQUFjLEVBQUUsRUFBRSxFQUFFLEVBQ3BCLGVBQWUsRUFBRSxlQUFlLEVBQ2hDLElBQUksRUFBRSxxQkFBcUIsRUFDM0IsWUFBWSxDQUFDLEVBQUUseUJBQXlCLEdBQ3ZDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQXNDM0I7SUFFRCxPQUFPLENBQUMsV0FBVyxFQUFFLFdBQVcsR0FBRyxPQUFPLENBQUMseUJBQXlCLENBQUMsQ0FFcEU7Q0FDRiJ9
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":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,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;;;OAyClG;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
+ {"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"}
@@ -7,14 +7,13 @@ import { bufferToHex } from '@aztec/foundation/string';
7
7
  import { Timer, elapsed } from '@aztec/foundation/timer';
8
8
  import { getDefaultAllowedSetupFunctions } from '@aztec/p2p/msg_validators';
9
9
  import { LightweightBlockFactory } from '@aztec/prover-client/block-factory';
10
- import { GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, TelemetryCppPublicTxSimulator } from '@aztec/simulator/server';
11
- import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
10
+ import { GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, createPublicTxSimulatorForBlockBuilding } from '@aztec/simulator/server';
12
11
  import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
13
12
  import { Gas } from '@aztec/stdlib/gas';
14
13
  import { getTelemetryClient } from '@aztec/telemetry-client';
15
14
  import { createValidatorForBlockBuilding } from '../tx_validator/tx_validator_factory.js';
16
15
  const log = createLogger('block-builder');
17
- 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()) {
18
17
  const blockBuildingTimer = new Timer();
19
18
  const blockNumber = newGlobalVariables.blockNumber;
20
19
  const slot = newGlobalVariables.slotNumber;
@@ -58,8 +57,10 @@ const FullNodeBlockBuilderConfigKeys = [
58
57
  'l1ChainId',
59
58
  'rollupVersion',
60
59
  'txPublicSetupAllowList',
61
- 'fakeProcessingDelayPerTxMs'
60
+ 'fakeProcessingDelayPerTxMs',
61
+ 'fakeThrowAfterProcessingTxCount'
62
62
  ];
63
+ // TODO(palla/mbps): Try killing this in favor of the CheckpointsBuilder
63
64
  export class FullNodeBlockBuilder {
64
65
  config;
65
66
  worldState;
@@ -83,13 +84,7 @@ export class FullNodeBlockBuilder {
83
84
  const txPublicSetupAllowList = this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
84
85
  const contractsDB = new PublicContractsDB(this.contractDataSource);
85
86
  const guardedFork = new GuardedMerkleTreeOperations(fork);
86
- const publicTxSimulator = new TelemetryCppPublicTxSimulator(guardedFork, contractsDB, globalVariables, this.telemetryClient, PublicSimulatorConfig.from({
87
- skipFeeEnforcement: false,
88
- collectDebugLogs: false,
89
- collectHints: false,
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 {
@@ -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"}
@@ -0,0 +1,131 @@
1
+ import { MerkleTreeId } from '@aztec/aztec.js/trees';
2
+ import { merge, pick } from '@aztec/foundation/collection';
3
+ import { createLogger } from '@aztec/foundation/log';
4
+ import { bufferToHex } from '@aztec/foundation/string';
5
+ import { Timer, elapsed } from '@aztec/foundation/timer';
6
+ import { getDefaultAllowedSetupFunctions } from '@aztec/p2p/msg_validators';
7
+ import { LightweightCheckpointBuilder } from '@aztec/prover-client/light';
8
+ import { GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, createPublicTxSimulatorForBlockBuilding } from '@aztec/simulator/server';
9
+ import { Gas } from '@aztec/stdlib/gas';
10
+ import { FullNodeBlockBuilderConfigKeys } from '@aztec/stdlib/interfaces/server';
11
+ import { GlobalVariables } from '@aztec/stdlib/tx';
12
+ import { getTelemetryClient } from '@aztec/telemetry-client';
13
+ import { createValidatorForBlockBuilding } from '../tx_validator/tx_validator_factory.js';
14
+ const log = createLogger('checkpoint-builder');
15
+ /**
16
+ * Builder for a single checkpoint. Handles building blocks within the checkpoint
17
+ * and completing it.
18
+ */ export class CheckpointBuilder {
19
+ checkpointBuilder;
20
+ fork;
21
+ config;
22
+ contractDataSource;
23
+ dateProvider;
24
+ telemetryClient;
25
+ constructor(checkpointBuilder, fork, config, contractDataSource, dateProvider, telemetryClient){
26
+ this.checkpointBuilder = checkpointBuilder;
27
+ this.fork = fork;
28
+ this.config = config;
29
+ this.contractDataSource = contractDataSource;
30
+ this.dateProvider = dateProvider;
31
+ this.telemetryClient = telemetryClient;
32
+ }
33
+ getConstantData() {
34
+ return this.checkpointBuilder.constants;
35
+ }
36
+ /**
37
+ * Builds a single block within this checkpoint.
38
+ */ async buildBlock(pendingTxs, blockNumber, timestamp, opts) {
39
+ const blockBuildingTimer = new Timer();
40
+ const slot = this.checkpointBuilder.constants.slotNumber;
41
+ log.verbose(`Building block ${blockNumber} for slot ${slot} within checkpoint`, {
42
+ slot,
43
+ blockNumber,
44
+ ...opts
45
+ });
46
+ const constants = this.checkpointBuilder.constants;
47
+ const globalVariables = GlobalVariables.from({
48
+ chainId: constants.chainId,
49
+ version: constants.version,
50
+ blockNumber,
51
+ slotNumber: constants.slotNumber,
52
+ timestamp,
53
+ coinbase: constants.coinbase,
54
+ feeRecipient: constants.feeRecipient,
55
+ gasFees: constants.gasFees
56
+ });
57
+ const { processor, validator } = await this.makeBlockBuilderDeps(globalVariables, this.fork);
58
+ const [publicProcessorDuration, [processedTxs, failedTxs, usedTxs]] = await elapsed(()=>processor.process(pendingTxs, opts, validator));
59
+ // Add block to checkpoint
60
+ const block = await this.checkpointBuilder.addBlock(globalVariables, processedTxs);
61
+ // How much public gas was processed
62
+ const publicGas = processedTxs.reduce((acc, tx)=>acc.add(tx.gasUsed.publicGas), Gas.empty());
63
+ const res = {
64
+ block,
65
+ publicGas,
66
+ publicProcessorDuration,
67
+ numTxs: processedTxs.length,
68
+ failedTxs,
69
+ blockBuildingTimer,
70
+ usedTxs
71
+ };
72
+ log.debug('Built block within checkpoint', res.block.header);
73
+ return res;
74
+ }
75
+ /** Completes the checkpoint and returns it. */ async completeCheckpoint() {
76
+ const checkpoint = await this.checkpointBuilder.completeCheckpoint();
77
+ log.verbose(`Completed checkpoint ${checkpoint.number}`, {
78
+ checkpointNumber: checkpoint.number,
79
+ numBlocks: checkpoint.blocks.length,
80
+ archiveRoot: checkpoint.archive.root.toString()
81
+ });
82
+ return checkpoint;
83
+ }
84
+ /** Gets the checkpoint currently in progress. */ getCheckpoint() {
85
+ return this.checkpointBuilder.clone().completeCheckpoint();
86
+ }
87
+ async makeBlockBuilderDeps(globalVariables, fork) {
88
+ const txPublicSetupAllowList = this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
89
+ const contractsDB = new PublicContractsDB(this.contractDataSource);
90
+ const guardedFork = new GuardedMerkleTreeOperations(fork);
91
+ const publicTxSimulator = createPublicTxSimulatorForBlockBuilding(guardedFork, contractsDB, globalVariables, this.telemetryClient);
92
+ const processor = new PublicProcessor(globalVariables, guardedFork, contractsDB, publicTxSimulator, this.dateProvider, this.telemetryClient, undefined, this.config);
93
+ const validator = createValidatorForBlockBuilding(fork, this.contractDataSource, globalVariables, txPublicSetupAllowList);
94
+ return {
95
+ processor,
96
+ validator
97
+ };
98
+ }
99
+ }
100
+ /**
101
+ * Factory for creating checkpoint builders.
102
+ */ export class FullNodeCheckpointsBuilder {
103
+ config;
104
+ contractDataSource;
105
+ dateProvider;
106
+ telemetryClient;
107
+ constructor(config, contractDataSource, dateProvider, telemetryClient = getTelemetryClient()){
108
+ this.config = config;
109
+ this.contractDataSource = contractDataSource;
110
+ this.dateProvider = dateProvider;
111
+ this.telemetryClient = telemetryClient;
112
+ }
113
+ updateConfig(config) {
114
+ this.config = merge(this.config, pick(config, ...FullNodeBlockBuilderConfigKeys));
115
+ }
116
+ /**
117
+ * Starts a new checkpoint and returns a CheckpointBuilder to build blocks within it.
118
+ */ async startCheckpoint(checkpointNumber, constants, l1ToL2Messages, fork) {
119
+ const stateReference = await fork.getStateReference();
120
+ const archiveTree = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
121
+ log.verbose(`Building checkpoint ${checkpointNumber}`, {
122
+ checkpointNumber,
123
+ msgCount: l1ToL2Messages.length,
124
+ initialStateReference: stateReference.toInspect(),
125
+ initialArchiveRoot: bufferToHex(archiveTree.root),
126
+ constants
127
+ });
128
+ const lightweightBuilder = await LightweightCheckpointBuilder.startNewCheckpoint(checkpointNumber, constants, l1ToL2Messages, fork);
129
+ return new CheckpointBuilder(lightweightBuilder, fork, this.config, this.contractDataSource, this.dateProvider, this.telemetryClient);
130
+ }
131
+ }