@aztec/sequencer-client 0.0.1-commit.b655e406 → 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 (102) hide show
  1. package/dest/client/index.d.ts +1 -1
  2. package/dest/client/sequencer-client.d.ts +10 -9
  3. package/dest/client/sequencer-client.d.ts.map +1 -1
  4. package/dest/client/sequencer-client.js +32 -24
  5. package/dest/config.d.ts +12 -5
  6. package/dest/config.d.ts.map +1 -1
  7. package/dest/config.js +75 -28
  8. package/dest/global_variable_builder/global_builder.d.ts +19 -13
  9. package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
  10. package/dest/global_variable_builder/global_builder.js +41 -28
  11. package/dest/global_variable_builder/index.d.ts +1 -1
  12. package/dest/index.d.ts +2 -2
  13. package/dest/index.d.ts.map +1 -1
  14. package/dest/index.js +1 -1
  15. package/dest/publisher/config.d.ts +9 -4
  16. package/dest/publisher/config.d.ts.map +1 -1
  17. package/dest/publisher/config.js +14 -3
  18. package/dest/publisher/index.d.ts +1 -1
  19. package/dest/publisher/sequencer-publisher-factory.d.ts +5 -4
  20. package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
  21. package/dest/publisher/sequencer-publisher-factory.js +1 -1
  22. package/dest/publisher/sequencer-publisher-metrics.d.ts +3 -3
  23. package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
  24. package/dest/publisher/sequencer-publisher.d.ts +66 -53
  25. package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
  26. package/dest/publisher/sequencer-publisher.js +230 -120
  27. package/dest/sequencer/block_builder.d.ts +4 -5
  28. package/dest/sequencer/block_builder.d.ts.map +1 -1
  29. package/dest/sequencer/block_builder.js +9 -10
  30. package/dest/sequencer/checkpoint_builder.d.ts +63 -0
  31. package/dest/sequencer/checkpoint_builder.d.ts.map +1 -0
  32. package/dest/sequencer/checkpoint_builder.js +131 -0
  33. package/dest/sequencer/checkpoint_proposal_job.d.ts +74 -0
  34. package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -0
  35. package/dest/sequencer/checkpoint_proposal_job.js +642 -0
  36. package/dest/sequencer/checkpoint_voter.d.ts +34 -0
  37. package/dest/sequencer/checkpoint_voter.d.ts.map +1 -0
  38. package/dest/sequencer/checkpoint_voter.js +85 -0
  39. package/dest/sequencer/config.d.ts +3 -2
  40. package/dest/sequencer/config.d.ts.map +1 -1
  41. package/dest/sequencer/errors.d.ts +1 -1
  42. package/dest/sequencer/errors.d.ts.map +1 -1
  43. package/dest/sequencer/events.d.ts +46 -0
  44. package/dest/sequencer/events.d.ts.map +1 -0
  45. package/dest/sequencer/events.js +1 -0
  46. package/dest/sequencer/index.d.ts +5 -1
  47. package/dest/sequencer/index.d.ts.map +1 -1
  48. package/dest/sequencer/index.js +4 -0
  49. package/dest/sequencer/metrics.d.ts +32 -3
  50. package/dest/sequencer/metrics.d.ts.map +1 -1
  51. package/dest/sequencer/metrics.js +192 -0
  52. package/dest/sequencer/sequencer.d.ts +96 -138
  53. package/dest/sequencer/sequencer.d.ts.map +1 -1
  54. package/dest/sequencer/sequencer.js +247 -479
  55. package/dest/sequencer/timetable.d.ts +54 -14
  56. package/dest/sequencer/timetable.d.ts.map +1 -1
  57. package/dest/sequencer/timetable.js +148 -59
  58. package/dest/sequencer/types.d.ts +3 -0
  59. package/dest/sequencer/types.d.ts.map +1 -0
  60. package/dest/sequencer/types.js +1 -0
  61. package/dest/sequencer/utils.d.ts +14 -8
  62. package/dest/sequencer/utils.d.ts.map +1 -1
  63. package/dest/sequencer/utils.js +7 -4
  64. package/dest/test/index.d.ts +4 -2
  65. package/dest/test/index.d.ts.map +1 -1
  66. package/dest/test/mock_checkpoint_builder.d.ts +83 -0
  67. package/dest/test/mock_checkpoint_builder.d.ts.map +1 -0
  68. package/dest/test/mock_checkpoint_builder.js +179 -0
  69. package/dest/test/utils.d.ts +49 -0
  70. package/dest/test/utils.d.ts.map +1 -0
  71. package/dest/test/utils.js +94 -0
  72. package/dest/tx_validator/nullifier_cache.d.ts +1 -1
  73. package/dest/tx_validator/nullifier_cache.d.ts.map +1 -1
  74. package/dest/tx_validator/tx_validator_factory.d.ts +4 -3
  75. package/dest/tx_validator/tx_validator_factory.d.ts.map +1 -1
  76. package/dest/tx_validator/tx_validator_factory.js +1 -1
  77. package/package.json +31 -30
  78. package/src/client/sequencer-client.ts +28 -38
  79. package/src/config.ts +81 -32
  80. package/src/global_variable_builder/global_builder.ts +56 -48
  81. package/src/index.ts +2 -0
  82. package/src/publisher/config.ts +20 -9
  83. package/src/publisher/sequencer-publisher-factory.ts +7 -5
  84. package/src/publisher/sequencer-publisher-metrics.ts +2 -2
  85. package/src/publisher/sequencer-publisher.ts +328 -161
  86. package/src/sequencer/README.md +531 -0
  87. package/src/sequencer/block_builder.ts +12 -13
  88. package/src/sequencer/checkpoint_builder.ts +217 -0
  89. package/src/sequencer/checkpoint_proposal_job.ts +706 -0
  90. package/src/sequencer/checkpoint_voter.ts +105 -0
  91. package/src/sequencer/config.ts +2 -1
  92. package/src/sequencer/events.ts +27 -0
  93. package/src/sequencer/index.ts +4 -0
  94. package/src/sequencer/metrics.ts +254 -3
  95. package/src/sequencer/sequencer.ts +360 -674
  96. package/src/sequencer/timetable.ts +173 -79
  97. package/src/sequencer/types.ts +6 -0
  98. package/src/sequencer/utils.ts +18 -9
  99. package/src/test/index.ts +3 -1
  100. package/src/test/mock_checkpoint_builder.ts +247 -0
  101. package/src/test/utils.ts +137 -0
  102. package/src/tx_validator/tx_validator_factory.ts +3 -2
@@ -1,8 +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, 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';
8
+ import { BlockNumber, CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
9
+ import { pick } from '@aztec/foundation/collection';
6
10
  import { EthAddress } from '@aztec/foundation/eth-address';
7
11
  import { Signature } from '@aztec/foundation/eth-signature';
8
12
  import { createLogger } from '@aztec/foundation/log';
@@ -10,7 +14,7 @@ import { bufferToHex } from '@aztec/foundation/string';
10
14
  import { Timer } from '@aztec/foundation/timer';
11
15
  import { EmpireBaseAbi, ErrorsAbi, RollupAbi } from '@aztec/l1-artifacts';
12
16
  import { encodeSlashConsensusVotes } from '@aztec/slasher';
13
- import { CommitteeAttestation, CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
17
+ import { CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
14
18
  import { getTelemetryClient } from '@aztec/telemetry-client';
15
19
  import { encodeFunctionData, toHex } from 'viem';
16
20
  import { SequencerPublisherMetrics } from './sequencer-publisher-metrics.js';
@@ -35,9 +39,12 @@ export class SequencerPublisher {
35
39
  governanceLog;
36
40
  slashingLog;
37
41
  lastActions;
42
+ isPayloadEmptyCache;
38
43
  log;
39
44
  ethereumSlotDuration;
40
- blobSinkClient;
45
+ blobClient;
46
+ /** Address to use for simulations in fisherman mode (actual proposer's address) */ proposerAddressForSimulation;
47
+ /** L1 fee analyzer for fisherman mode */ l1FeeAnalyzer;
41
48
  // @note - with blobs, the below estimate seems too large.
42
49
  // Total used for full block from int_l1_pub e2e test: 1m (of which 86k is 1x blob)
43
50
  // Total used for emptier block from above test: 429k (of which 84k is 1x blob)
@@ -58,14 +65,13 @@ export class SequencerPublisher {
58
65
  this.governanceLog = createLogger('sequencer:publisher:governance');
59
66
  this.slashingLog = createLogger('sequencer:publisher:slashing');
60
67
  this.lastActions = {};
68
+ this.isPayloadEmptyCache = new Map();
61
69
  this.requests = [];
62
70
  this.log = deps.log ?? createLogger('sequencer:publisher');
63
71
  this.ethereumSlotDuration = BigInt(config.ethereumSlotDuration);
64
72
  this.epochCache = deps.epochCache;
65
73
  this.lastActions = deps.lastActions;
66
- this.blobSinkClient = deps.blobSinkClient ?? createBlobSinkClient(config, {
67
- logger: createLogger('sequencer:blob-sink:client')
68
- });
74
+ this.blobClient = deps.blobClient;
69
75
  const telemetry = deps.telemetry ?? getTelemetryClient();
70
76
  this.metrics = deps.metrics ?? new SequencerPublisherMetrics(telemetry, 'SequencerPublisher');
71
77
  this.l1TxUtils = deps.l1TxUtils;
@@ -78,6 +84,10 @@ export class SequencerPublisher {
78
84
  this.slashingProposerContract = newSlashingProposer;
79
85
  });
80
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
+ }
81
91
  }
82
92
  getRollupContract() {
83
93
  return this.rollupContract;
@@ -85,6 +95,17 @@ export class SequencerPublisher {
85
95
  getSenderAddress() {
86
96
  return this.l1TxUtils.getSenderAddress();
87
97
  }
98
+ /**
99
+ * Gets the L1 fee analyzer instance (only available in fisherman mode)
100
+ */ getL1FeeAnalyzer() {
101
+ return this.l1FeeAnalyzer;
102
+ }
103
+ /**
104
+ * Sets the proposer address to use for simulations in fisherman mode.
105
+ * @param proposerAddress - The actual proposer's address to use for balance lookups in simulations
106
+ */ setProposerAddressForSimulation(proposerAddress) {
107
+ this.proposerAddressForSimulation = proposerAddress;
108
+ }
88
109
  addRequest(request) {
89
110
  this.requests.push(request);
90
111
  }
@@ -92,6 +113,55 @@ export class SequencerPublisher {
92
113
  return this.epochCache.getEpochAndSlotNow().slot;
93
114
  }
94
115
  /**
116
+ * Clears all pending requests without sending them.
117
+ */ clearPendingRequests() {
118
+ const count = this.requests.length;
119
+ this.requests = [];
120
+ if (count > 0) {
121
+ this.log.debug(`Cleared ${count} pending request(s)`);
122
+ }
123
+ }
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
+ /**
95
165
  * Sends all requests that are still valid.
96
166
  * @returns one of:
97
167
  * - A receipt and stats if the tx succeeded
@@ -102,7 +172,7 @@ export class SequencerPublisher {
102
172
  ...this.requests
103
173
  ];
104
174
  this.requests = [];
105
- if (this.interrupted) {
175
+ if (this.interrupted || requestsToProcess.length === 0) {
106
176
  return undefined;
107
177
  }
108
178
  const currentL2Slot = this.getCurrentL2Slot();
@@ -211,7 +281,9 @@ export class SequencerPublisher {
211
281
  'InvalidProposer',
212
282
  'InvalidArchive'
213
283
  ];
214
- return this.rollupContract.canProposeAtNextEthBlock(tipArchive.toBuffer(), msgSender.toString(), this.ethereumSlotDuration, opts).catch((err)=>{
284
+ return this.rollupContract.canProposeAtNextEthBlock(tipArchive.toBuffer(), msgSender.toString(), Number(this.ethereumSlotDuration), {
285
+ forcePendingCheckpointNumber: opts.forcePendingBlockNumber !== undefined ? CheckpointNumber.fromBlockNumber(opts.forcePendingBlockNumber) : undefined
286
+ }).catch((err)=>{
215
287
  if (err instanceof FormattedViemError && ignoredErrors.find((e)=>err.message.includes(e))) {
216
288
  this.log.warn(`Failed canProposeAtTime check with ${ignoredErrors.find((e)=>err.message.includes(e))}`, {
217
289
  error: err.message
@@ -242,9 +314,20 @@ export class SequencerPublisher {
242
314
  flags
243
315
  ];
244
316
  const ts = BigInt((await this.l1TxUtils.getBlock()).timestamp + this.ethereumSlotDuration);
245
- // use sender balance to simulate
246
- const balance = await this.l1TxUtils.getSenderBalance();
247
- this.log.debug(`Simulating validateHeader with balance: ${balance}`);
317
+ const optsForcePendingCheckpointNumber = opts?.forcePendingBlockNumber !== undefined ? CheckpointNumber.fromBlockNumber(opts.forcePendingBlockNumber) : undefined;
318
+ const stateOverrides = await this.rollupContract.makePendingCheckpointNumberOverride(optsForcePendingCheckpointNumber);
319
+ let balance = 0n;
320
+ if (this.config.fishermanMode) {
321
+ // In fisherman mode, we can't know where the proposer is publishing from
322
+ // so we just add sufficient balance to the multicall3 address
323
+ balance = 10n * WEI_CONST * WEI_CONST; // 10 ETH
324
+ } else {
325
+ balance = await this.l1TxUtils.getSenderBalance();
326
+ }
327
+ stateOverrides.push({
328
+ address: MULTI_CALL_3_ADDRESS,
329
+ balance
330
+ });
248
331
  await this.l1TxUtils.simulate({
249
332
  to: this.rollupContract.address,
250
333
  data: encodeFunctionData({
@@ -255,13 +338,7 @@ export class SequencerPublisher {
255
338
  from: MULTI_CALL_3_ADDRESS
256
339
  }, {
257
340
  time: ts + 1n
258
- }, [
259
- {
260
- address: MULTI_CALL_3_ADDRESS,
261
- balance
262
- },
263
- ...await this.rollupContract.makePendingBlockNumberOverride(opts?.forcePendingBlockNumber)
264
- ]);
341
+ }, stateOverrides);
265
342
  this.log.debug(`Simulated validateHeader`);
266
343
  }
267
344
  /**
@@ -277,7 +354,7 @@ export class SequencerPublisher {
277
354
  ...block,
278
355
  reason
279
356
  };
280
- const currentBlockNumber = await this.rollupContract.getBlockNumber();
357
+ const currentBlockNumber = await this.rollupContract.getCheckpointNumber();
281
358
  if (currentBlockNumber < validationResult.block.blockNumber) {
282
359
  this.log.verbose(`Skipping block ${blockNumber} invalidation since it has already been removed from the pending chain`, {
283
360
  currentBlockNumber,
@@ -301,7 +378,7 @@ export class SequencerPublisher {
301
378
  request,
302
379
  gasUsed,
303
380
  blockNumber,
304
- forcePendingBlockNumber: blockNumber - 1,
381
+ forcePendingBlockNumber: BlockNumber(blockNumber - 1),
305
382
  reason
306
383
  };
307
384
  } catch (err) {
@@ -314,7 +391,7 @@ export class SequencerPublisher {
314
391
  request,
315
392
  error: viemError.message
316
393
  });
317
- const latestPendingBlockNumber = await this.rollupContract.getBlockNumber();
394
+ const latestPendingBlockNumber = await this.rollupContract.getCheckpointNumber();
318
395
  if (latestPendingBlockNumber < blockNumber) {
319
396
  this.log.verbose(`Block number ${blockNumber} has already been invalidated`, {
320
397
  ...logData
@@ -346,43 +423,37 @@ export class SequencerPublisher {
346
423
  this.log.debug(`Simulating invalidate block ${block.blockNumber}`, logData);
347
424
  const attestationsAndSigners = new CommitteeAttestationsAndSigners(validationResult.attestations).getPackedAttestations();
348
425
  if (reason === 'invalid-attestation') {
349
- return this.rollupContract.buildInvalidateBadAttestationRequest(block.blockNumber, attestationsAndSigners, committee, validationResult.invalidIndex);
426
+ return this.rollupContract.buildInvalidateBadAttestationRequest(CheckpointNumber.fromBlockNumber(block.blockNumber), attestationsAndSigners, committee, validationResult.invalidIndex);
350
427
  } else if (reason === 'insufficient-attestations') {
351
- return this.rollupContract.buildInvalidateInsufficientAttestationsRequest(block.blockNumber, attestationsAndSigners, committee);
428
+ return this.rollupContract.buildInvalidateInsufficientAttestationsRequest(CheckpointNumber.fromBlockNumber(block.blockNumber), attestationsAndSigners, committee);
352
429
  } else {
353
430
  const _ = reason;
354
431
  throw new Error(`Unknown reason for invalidation`);
355
432
  }
356
433
  }
357
- /**
358
- * @notice Will simulate `propose` to make sure that the block is valid for submission
359
- *
360
- * @dev Throws if unable to propose
361
- *
362
- * @param block - The block to propose
363
- * @param attestationData - The block's attestation data
364
- *
365
- */ 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) {
366
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?
367
437
  // If we have no attestations, we still need to provide the empty attestations
368
438
  // so that the committee is recalculated correctly
369
- const ignoreSignatures = attestationsAndSigners.attestations.length === 0;
370
- if (ignoreSignatures) {
371
- const { committee } = await this.epochCache.getCommittee(block.header.globalVariables.slotNumber.toBigInt());
372
- if (!committee) {
373
- this.log.warn(`No committee found for slot ${block.header.globalVariables.slotNumber.toBigInt()}`);
374
- throw new Error(`No committee found for slot ${block.header.globalVariables.slotNumber.toBigInt()}`);
375
- }
376
- attestationsAndSigners.attestations = committee.map((committeeMember)=>CommitteeAttestation.fromAddress(committeeMember));
377
- }
378
- 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();
379
451
  const blobs = getBlobsPerL1Block(blobFields);
380
452
  const blobInput = getPrefixedEthBlobCommitments(blobs);
381
453
  const args = [
382
454
  {
383
- header: block.getCheckpointHeader().toViem(),
384
- archive: toHex(block.archive.root.toBuffer()),
385
- stateReference: block.header.state.toViem(),
455
+ header: checkpoint.header.toViem(),
456
+ archive: toHex(checkpoint.archive.root.toBuffer()),
386
457
  oracleInput: {
387
458
  feeAssetPriceModifier: 0n
388
459
  }
@@ -409,9 +480,16 @@ export class SequencerPublisher {
409
480
  }
410
481
  const round = await base.computeRound(slotNumber);
411
482
  const roundInfo = await base.getRoundInfo(this.rollupContract.address, round);
483
+ if (roundInfo.quorumReached) {
484
+ return false;
485
+ }
412
486
  if (roundInfo.lastSignalSlot >= slotNumber) {
413
487
  return false;
414
488
  }
489
+ if (await this.isPayloadEmpty(payload)) {
490
+ this.log.warn(`Skipping vote cast for payload with empty code`);
491
+ return false;
492
+ }
415
493
  const cachedLastVote = this.lastActions[signalType];
416
494
  this.lastActions[signalType] = slotNumber;
417
495
  const action = signalType;
@@ -450,17 +528,27 @@ export class SequencerPublisher {
450
528
  payload: payload.toString()
451
529
  };
452
530
  if (!success) {
453
- 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);
454
532
  this.lastActions[signalType] = cachedLastVote;
455
533
  return false;
456
534
  } else {
457
- 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);
458
536
  return true;
459
537
  }
460
538
  }
461
539
  });
462
540
  return true;
463
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
+ }
464
552
  /**
465
553
  * Enqueues a governance castSignal transaction to cast a signal for a given slot number.
466
554
  * @param slotNumber - The slot number to cast a signal for.
@@ -556,20 +644,13 @@ export class SequencerPublisher {
556
644
  }
557
645
  return true;
558
646
  }
559
- /**
560
- * Proposes a L2 block on L1.
561
- *
562
- * @param block - L2 block to propose.
563
- * @returns True if the tx has been enqueued, throws otherwise. See #9315
564
- */ async enqueueProposeL2Block(block, attestationsAndSigners, attestationsAndSignersSignature, opts = {}) {
565
- const checkpointHeader = block.getCheckpointHeader();
566
- 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();
567
650
  const blobs = getBlobsPerL1Block(blobFields);
568
651
  const proposeTxArgs = {
569
652
  header: checkpointHeader,
570
- archive: block.archive.root.toBuffer(),
571
- stateReference: block.header.state,
572
- body: block.body.toBuffer(),
653
+ archive: checkpoint.archive.root.toBuffer(),
573
654
  blobs,
574
655
  attestationsAndSigners,
575
656
  attestationsAndSignersSignature
@@ -581,21 +662,20 @@ export class SequencerPublisher {
581
662
  // By simulation issue, I mean the fact that the block.timestamp is equal to the last block, not the next, which
582
663
  // make time consistency checks break.
583
664
  // TODO(palla): Check whether we're validating twice, once here and once within addProposeTx, since we call simulateProposeTx in both places.
584
- ts = await this.validateBlockForSubmission(block, attestationsAndSigners, attestationsAndSignersSignature, opts);
665
+ ts = await this.validateCheckpointForSubmission(checkpoint, attestationsAndSigners, attestationsAndSignersSignature, opts);
585
666
  } catch (err) {
586
- this.log.error(`Block validation failed. ${err instanceof Error ? err.message : 'No error message'}`, err, {
587
- ...block.getStats(),
588
- slotNumber: block.header.globalVariables.slotNumber.toBigInt(),
667
+ this.log.error(`Checkpoint validation failed. ${err instanceof Error ? err.message : 'No error message'}`, err, {
668
+ ...checkpoint.getStats(),
669
+ slotNumber: checkpoint.header.slotNumber,
589
670
  forcePendingBlockNumber: opts.forcePendingBlockNumber
590
671
  });
591
672
  throw err;
592
673
  }
593
- this.log.verbose(`Enqueuing block propose transaction`, {
594
- ...block.toBlockInfo(),
674
+ this.log.verbose(`Enqueuing checkpoint propose transaction`, {
675
+ ...checkpoint.toCheckpointInfo(),
595
676
  ...opts
596
677
  });
597
- await this.addProposeTx(block, proposeTxArgs, opts, ts);
598
- return true;
678
+ await this.addProposeTx(checkpoint, proposeTxArgs, opts, ts);
599
679
  }
600
680
  enqueueInvalidateBlock(request, opts = {}) {
601
681
  if (!request) {
@@ -618,9 +698,9 @@ export class SequencerPublisher {
618
698
  gasLimit,
619
699
  txTimeoutAt: opts.txTimeoutAt
620
700
  },
621
- lastValidL2Slot: this.getCurrentL2Slot() + 2n,
701
+ lastValidL2Slot: SlotNumber(this.getCurrentL2Slot() + 2),
622
702
  checkSuccess: (_req, result)=>{
623
- const success = result && result.receipt && result.receipt.status === 'success' && tryExtractEvent(result.receipt.logs, this.rollupContract.address, RollupAbi, 'BlockInvalidated');
703
+ const success = result && result.receipt && result.receipt.status === 'success' && tryExtractEvent(result.receipt.logs, this.rollupContract.address, RollupAbi, 'CheckpointInvalidated');
624
704
  if (!success) {
625
705
  this.log.warn(`Invalidate block ${request.blockNumber} failed`, {
626
706
  ...result,
@@ -713,31 +793,40 @@ export class SequencerPublisher {
713
793
  this.log.debug('Validating blob input', {
714
794
  blobInput
715
795
  });
716
- const blobEvaluationGas = await this.l1TxUtils.estimateGas(this.getSenderAddress().toString(), {
717
- to: this.rollupContract.address,
718
- data: encodeFunctionData({
719
- abi: RollupAbi,
720
- functionName: 'validateBlobs',
721
- args: [
722
- blobInput
723
- ]
724
- })
725
- }, {}, {
726
- blobs: encodedData.blobs.map((b)=>b.data),
727
- kzg
728
- }).catch((err)=>{
729
- const { message, metaMessages } = formatViemError(err);
730
- this.log.error(`Failed to validate blobs`, message, {
731
- metaMessages
796
+ // Get blob evaluation gas
797
+ let blobEvaluationGas;
798
+ if (this.config.fishermanMode) {
799
+ // In fisherman mode, we can't estimate blob gas because estimateGas doesn't support state overrides
800
+ // Use a fixed estimate.
801
+ blobEvaluationGas = BigInt(encodedData.blobs.length) * 21_000n;
802
+ this.log.debug(`Using fixed blob evaluation gas estimate in fisherman mode: ${blobEvaluationGas}`);
803
+ } else {
804
+ // Normal mode - use estimateGas with blob inputs
805
+ blobEvaluationGas = await this.l1TxUtils.estimateGas(this.getSenderAddress().toString(), {
806
+ to: this.rollupContract.address,
807
+ data: encodeFunctionData({
808
+ abi: RollupAbi,
809
+ functionName: 'validateBlobs',
810
+ args: [
811
+ blobInput
812
+ ]
813
+ })
814
+ }, {}, {
815
+ blobs: encodedData.blobs.map((b)=>b.data),
816
+ kzg
817
+ }).catch((err)=>{
818
+ const { message, metaMessages } = formatViemError(err);
819
+ this.log.error(`Failed to validate blobs`, message, {
820
+ metaMessages
821
+ });
822
+ throw new Error('Failed to validate blobs');
732
823
  });
733
- throw new Error('Failed to validate blobs');
734
- });
824
+ }
735
825
  const signers = encodedData.attestationsAndSigners.getSigners().map((signer)=>signer.toString());
736
826
  const args = [
737
827
  {
738
828
  header: encodedData.header.toViem(),
739
829
  archive: toHex(encodedData.archive),
740
- stateReference: encodedData.stateReference.toViem(),
741
830
  oracleInput: {
742
831
  // We are currently not modifying these. See #9963
743
832
  feeAssetPriceModifier: 0n
@@ -767,18 +856,10 @@ export class SequencerPublisher {
767
856
  functionName: 'propose',
768
857
  args
769
858
  });
770
- // override the pending block number if requested
771
- const forcePendingBlockNumberStateDiff = (options.forcePendingBlockNumber !== undefined ? await this.rollupContract.makePendingBlockNumberOverride(options.forcePendingBlockNumber) : []).flatMap((override)=>override.stateDiff ?? []);
772
- const simulationResult = await this.l1TxUtils.simulate({
773
- to: this.rollupContract.address,
774
- data: rollupData,
775
- gas: SequencerPublisher.PROPOSE_GAS_GUESS
776
- }, {
777
- // @note we add 1n to the timestamp because geth implementation doesn't like simulation timestamp to be equal to the current block timestamp
778
- time: timestamp + 1n,
779
- // @note reth should have a 30m gas limit per block but throws errors that this tx is beyond limit so we increase here
780
- gasLimit: SequencerPublisher.PROPOSE_GAS_GUESS * 2n
781
- }, [
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 ?? []);
862
+ const stateOverrides = [
782
863
  {
783
864
  address: this.rollupContract.address,
784
865
  // @note we override checkBlob to false since blobs are not part simulate()
@@ -787,14 +868,44 @@ export class SequencerPublisher {
787
868
  slot: toPaddedHex(RollupContract.checkBlobStorageSlot, true),
788
869
  value: toPaddedHex(0n, true)
789
870
  },
790
- ...forcePendingBlockNumberStateDiff
871
+ ...forcePendingCheckpointNumberStateDiff
791
872
  ]
792
873
  }
793
- ], RollupAbi, {
874
+ ];
875
+ // In fisherman mode, simulate as the proposer but with sufficient balance
876
+ if (this.proposerAddressForSimulation) {
877
+ stateOverrides.push({
878
+ address: this.proposerAddressForSimulation.toString(),
879
+ balance: 10n * WEI_CONST * WEI_CONST
880
+ });
881
+ }
882
+ const simulationResult = await this.l1TxUtils.simulate({
883
+ to: this.rollupContract.address,
884
+ data: rollupData,
885
+ gas: SequencerPublisher.PROPOSE_GAS_GUESS,
886
+ ...this.proposerAddressForSimulation && {
887
+ from: this.proposerAddressForSimulation.toString()
888
+ }
889
+ }, {
890
+ // @note we add 1n to the timestamp because geth implementation doesn't like simulation timestamp to be equal to the current block timestamp
891
+ time: timestamp + 1n,
892
+ // @note reth should have a 30m gas limit per block but throws errors that this tx is beyond limit so we increase here
893
+ gasLimit: SequencerPublisher.PROPOSE_GAS_GUESS * 2n
894
+ }, stateOverrides, RollupAbi, {
794
895
  // @note fallback gas estimate to use if the node doesn't support simulation API
795
896
  fallbackGasEstimate: SequencerPublisher.PROPOSE_GAS_GUESS
796
897
  }).catch((err)=>{
797
- this.log.error(`Failed to simulate propose tx`, err);
898
+ // In fisherman mode, we expect ValidatorSelection__MissingProposerSignature since fisherman doesn't have proposer signature
899
+ const viemError = formatViemError(err);
900
+ if (this.config.fishermanMode && viemError.message?.includes('ValidatorSelection__MissingProposerSignature')) {
901
+ this.log.debug(`Ignoring expected ValidatorSelection__MissingProposerSignature error in fisherman mode`);
902
+ // Return a minimal simulation result with the fallback gas estimate
903
+ return {
904
+ gasUsed: SequencerPublisher.PROPOSE_GAS_GUESS,
905
+ logs: []
906
+ };
907
+ }
908
+ this.log.error(`Failed to simulate propose tx`, viemError);
798
909
  throw err;
799
910
  });
800
911
  return {
@@ -802,24 +913,25 @@ export class SequencerPublisher {
802
913
  simulationResult
803
914
  };
804
915
  }
805
- async addProposeTx(block, encodedData, opts = {}, timestamp) {
916
+ async addProposeTx(checkpoint, encodedData, opts = {}, timestamp) {
917
+ const slot = checkpoint.header.slotNumber;
806
918
  const timer = new Timer();
807
919
  const kzg = Blob.getViemKzgInstance();
808
920
  const { rollupData, simulationResult, blobEvaluationGas } = await this.prepareProposeTx(encodedData, timestamp, opts);
809
921
  const startBlock = await this.l1TxUtils.getBlockNumber();
810
922
  const gasLimit = this.l1TxUtils.bumpGasLimit(BigInt(Math.ceil(Number(simulationResult.gasUsed) * 64 / 63)) + blobEvaluationGas + SequencerPublisher.MULTICALL_OVERHEAD_GAS_GUESS);
811
- // Send the blobs to the blob sink preemptively. This helps in tests where the sequencer mistakingly thinks that the propose
812
- // tx fails but it does get mined. We make sure that the blobs are sent to the blob sink regardless of the tx outcome.
813
- void this.blobSinkClient.sendBlobsToBlobSink(encodedData.blobs).catch((_err)=>{
814
- this.log.error('Failed to send blobs to blob sink');
815
- });
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
+ }));
816
928
  return this.addRequest({
817
929
  action: 'propose',
818
930
  request: {
819
931
  to: this.rollupContract.address,
820
932
  data: rollupData
821
933
  },
822
- lastValidL2Slot: block.header.globalVariables.slotNumber.toBigInt(),
934
+ lastValidL2Slot: checkpoint.header.slotNumber,
823
935
  gasConfig: {
824
936
  ...opts,
825
937
  gasLimit
@@ -833,7 +945,7 @@ export class SequencerPublisher {
833
945
  return false;
834
946
  }
835
947
  const { receipt, stats, errorMsg } = result;
836
- const success = receipt && receipt.status === 'success' && tryExtractEvent(receipt.logs, this.rollupContract.address, RollupAbi, 'L2BlockProposed');
948
+ const success = receipt && receipt.status === 'success' && tryExtractEvent(receipt.logs, this.rollupContract.address, RollupAbi, 'CheckpointProposed');
837
949
  if (success) {
838
950
  const endBlock = receipt.blockNumber;
839
951
  const inclusionBlocks = Number(endBlock - startBlock);
@@ -847,25 +959,23 @@ export class SequencerPublisher {
847
959
  calldataGas,
848
960
  calldataSize,
849
961
  sender,
850
- ...block.getStats(),
962
+ ...checkpoint.getStats(),
851
963
  eventName: 'rollup-published-to-l1',
852
964
  blobCount: encodedData.blobs.length,
853
965
  inclusionBlocks
854
966
  };
855
- this.log.info(`Published L2 block to L1 rollup contract`, {
967
+ this.log.info(`Published checkpoint ${checkpoint.number} at slot ${slot} to rollup contract`, {
856
968
  ...stats,
857
- ...block.getStats(),
858
- ...receipt
969
+ ...checkpoint.getStats(),
970
+ ...pick(receipt, 'transactionHash', 'blockHash')
859
971
  });
860
972
  this.metrics.recordProcessBlockTx(timer.ms(), publishStats);
861
973
  return true;
862
974
  } else {
863
975
  this.metrics.recordFailedTx('process');
864
- this.log.error(`Rollup process tx failed: ${errorMsg ?? 'no error message'}`, undefined, {
865
- ...block.getStats(),
866
- receipt,
867
- txHash: receipt.transactionHash,
868
- slotNumber: block.header.globalVariables.slotNumber.toBigInt()
976
+ this.log.error(`Publishing checkpoint at slot ${slot} failed with ${errorMsg ?? 'no error message'}`, undefined, {
977
+ ...checkpoint.getStats(),
978
+ ...receipt
869
979
  });
870
980
  return false;
871
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=block_builder.d.ts.map
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;AACjC,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,EAAE,qBAAqB,YAAK,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;gBAJf,MAAM,EAAE,0BAA0B,EAClC,UAAU,EAAE,sBAAsB,EAClC,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,EAC1B,eAAe,GAAE,eAAsC;IAG1D,SAAS,IAAI,0BAA0B;IAIvC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,0BAA0B,CAAC;IAIlD,oBAAoB,CAAC,eAAe,EAAE,eAAe,EAAE,IAAI,EAAE,yBAAyB;;;;YAyCrF,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;IAwC5B,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;CAGjE"}
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"}