@aztec/sequencer-client 0.0.1-commit.b64cb54f6 → 0.0.1-commit.b6e433891

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 (35) hide show
  1. package/dest/client/sequencer-client.d.ts +1 -12
  2. package/dest/client/sequencer-client.d.ts.map +1 -1
  3. package/dest/client/sequencer-client.js +19 -63
  4. package/dest/config.d.ts +4 -3
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +9 -2
  7. package/dest/global_variable_builder/global_builder.d.ts +1 -1
  8. package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
  9. package/dest/global_variable_builder/global_builder.js +5 -4
  10. package/dest/publisher/sequencer-publisher.d.ts +6 -4
  11. package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
  12. package/dest/publisher/sequencer-publisher.js +24 -8
  13. package/dest/sequencer/checkpoint_proposal_job.d.ts +12 -4
  14. package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
  15. package/dest/sequencer/checkpoint_proposal_job.js +137 -93
  16. package/dest/sequencer/events.d.ts +2 -1
  17. package/dest/sequencer/events.d.ts.map +1 -1
  18. package/dest/sequencer/metrics.d.ts +5 -1
  19. package/dest/sequencer/metrics.d.ts.map +1 -1
  20. package/dest/sequencer/metrics.js +11 -0
  21. package/dest/sequencer/sequencer.d.ts +6 -4
  22. package/dest/sequencer/sequencer.d.ts.map +1 -1
  23. package/dest/sequencer/sequencer.js +57 -45
  24. package/dest/test/mock_checkpoint_builder.d.ts +4 -4
  25. package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
  26. package/package.json +27 -28
  27. package/src/client/sequencer-client.ts +26 -84
  28. package/src/config.ts +12 -1
  29. package/src/global_variable_builder/global_builder.ts +3 -2
  30. package/src/publisher/sequencer-publisher.ts +28 -10
  31. package/src/sequencer/checkpoint_proposal_job.ts +186 -96
  32. package/src/sequencer/events.ts +1 -1
  33. package/src/sequencer/metrics.ts +14 -0
  34. package/src/sequencer/sequencer.ts +82 -51
  35. package/src/test/mock_checkpoint_builder.ts +3 -3
package/src/config.ts CHANGED
@@ -13,8 +13,10 @@ import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p/config';
13
13
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
14
14
  import {
15
15
  type ChainConfig,
16
+ type PipelineConfig,
16
17
  type SequencerConfig,
17
18
  chainConfigMappings,
19
+ pipelineConfigMappings,
18
20
  sharedSequencerConfigMappings,
19
21
  } from '@aztec/stdlib/config';
20
22
  import type { ResolvedSequencerConfig } from '@aztec/stdlib/interfaces/server';
@@ -40,7 +42,8 @@ export const DefaultSequencerConfig = {
40
42
  minTxsPerBlock: 1,
41
43
  buildCheckpointIfEmpty: false,
42
44
  publishTxsWithProposals: false,
43
- perBlockAllocationMultiplier: 2,
45
+ perBlockAllocationMultiplier: 1.2,
46
+ redistributeCheckpointBudget: true,
44
47
  enforceTimeTable: true,
45
48
  attestationPropagationTime: DEFAULT_P2P_PROPAGATION_TIME,
46
49
  secondsBeforeInvalidatingBlockAsCommitteeMember: 144, // 12 L1 blocks
@@ -67,6 +70,7 @@ export type SequencerClientConfig = SequencerPublisherConfig &
67
70
  SequencerConfig &
68
71
  L1ReaderConfig &
69
72
  ChainConfig &
73
+ PipelineConfig &
70
74
  Pick<P2PConfig, 'txPublicSetupAllowListExtend'> &
71
75
  Pick<L1ContractsConfig, 'ethereumSlotDuration' | 'aztecSlotDuration' | 'aztecEpochDuration'>;
72
76
 
@@ -112,6 +116,12 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
112
116
  ' Values greater than one allow early blocks to use more than their even share, relying on checkpoint-level capping for later blocks.',
113
117
  ...numberConfigHelper(DefaultSequencerConfig.perBlockAllocationMultiplier),
114
118
  },
119
+ redistributeCheckpointBudget: {
120
+ env: 'SEQ_REDISTRIBUTE_CHECKPOINT_BUDGET',
121
+ description:
122
+ 'Redistribute remaining checkpoint budget evenly across remaining blocks instead of allowing a single block to consume the entire remaining budget.',
123
+ ...booleanConfigHelper(DefaultSequencerConfig.redistributeCheckpointBudget),
124
+ },
115
125
  coinbase: {
116
126
  env: 'COINBASE',
117
127
  parseEnv: (val: string) => (val ? EthAddress.fromString(val) : undefined),
@@ -234,6 +244,7 @@ export const sequencerClientConfigMappings: ConfigMappingsType<SequencerClientCo
234
244
  ...sequencerTxSenderConfigMappings,
235
245
  ...sequencerPublisherConfigMappings,
236
246
  ...chainConfigMappings,
247
+ ...pipelineConfigMappings,
237
248
  ...pickConfigMappings(l1ContractsConfigMappings, ['ethereumSlotDuration', 'aztecSlotDuration', 'aztecEpochDuration']),
238
249
  };
239
250
 
@@ -1,4 +1,5 @@
1
1
  import { createEthereumChain } from '@aztec/ethereum/chain';
2
+ import { makeL1HttpTransport } from '@aztec/ethereum/client';
2
3
  import type { L1ContractsConfig } from '@aztec/ethereum/config';
3
4
  import { RollupContract } from '@aztec/ethereum/contracts';
4
5
  import type { L1ReaderConfig } from '@aztec/ethereum/l1-reader';
@@ -16,7 +17,7 @@ import type {
16
17
  } from '@aztec/stdlib/tx';
17
18
  import { GlobalVariables } from '@aztec/stdlib/tx';
18
19
 
19
- import { createPublicClient, fallback, http } from 'viem';
20
+ import { createPublicClient } from 'viem';
20
21
 
21
22
  /**
22
23
  * Simple global variables builder.
@@ -53,7 +54,7 @@ export class GlobalVariableBuilder implements GlobalVariableBuilderInterface {
53
54
 
54
55
  this.publicClient = createPublicClient({
55
56
  chain: chain.chainInfo,
56
- transport: fallback(chain.rpcUrls.map(url => http(url, { batch: false }))),
57
+ transport: makeL1HttpTransport(chain.rpcUrls, { timeout: config.l1HttpTimeoutMS }),
57
58
  pollingInterval: config.viemPollingIntervalMS,
58
59
  });
59
60
 
@@ -28,6 +28,7 @@ import { FormattedViemError, formatViemError, mergeAbis, tryExtractEvent } from
28
28
  import { sumBigint } from '@aztec/foundation/bigint';
29
29
  import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
30
30
  import { CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
31
+ import { trimmedBytesLength } from '@aztec/foundation/buffer';
31
32
  import { pick } from '@aztec/foundation/collection';
32
33
  import type { Fr } from '@aztec/foundation/curves/bn254';
33
34
  import { TimeoutError } from '@aztec/foundation/error';
@@ -132,6 +133,7 @@ export class SequencerPublisher {
132
133
 
133
134
  protected log: Logger;
134
135
  protected ethereumSlotDuration: bigint;
136
+ protected aztecSlotDuration: bigint;
135
137
 
136
138
  private blobClient: BlobClientInterface;
137
139
 
@@ -165,7 +167,7 @@ export class SequencerPublisher {
165
167
 
166
168
  constructor(
167
169
  private config: Pick<SequencerPublisherConfig, 'fishermanMode' | 'l1TxFailedStore'> &
168
- Pick<L1ContractsConfig, 'ethereumSlotDuration'> & { l1ChainId: number },
170
+ Pick<L1ContractsConfig, 'ethereumSlotDuration' | 'aztecSlotDuration'> & { l1ChainId: number },
169
171
  deps: {
170
172
  telemetry?: TelemetryClient;
171
173
  blobClient: BlobClientInterface;
@@ -184,6 +186,7 @@ export class SequencerPublisher {
184
186
  ) {
185
187
  this.log = deps.log ?? createLogger('sequencer:publisher');
186
188
  this.ethereumSlotDuration = BigInt(config.ethereumSlotDuration);
189
+ this.aztecSlotDuration = BigInt(config.aztecSlotDuration);
187
190
  this.epochCache = deps.epochCache;
188
191
  this.lastActions = deps.lastActions;
189
192
 
@@ -285,7 +288,7 @@ export class SequencerPublisher {
285
288
  }
286
289
 
287
290
  public getCurrentL2Slot(): SlotNumber {
288
- return this.epochCache.getEpochAndSlotNow().slot;
291
+ return this.epochCache.getSlotNow();
289
292
  }
290
293
 
291
294
  /**
@@ -398,8 +401,8 @@ export class SequencerPublisher {
398
401
  // @note - we can only have one blob config per bundle
399
402
  // find requests with gas and blob configs
400
403
  // See https://github.com/AztecProtocol/aztec-packages/issues/11513
401
- const gasConfigs = requestsToProcess.filter(request => request.gasConfig).map(request => request.gasConfig);
402
- const blobConfigs = requestsToProcess.filter(request => request.blobConfig).map(request => request.blobConfig);
404
+ const gasConfigs = validRequests.filter(request => request.gasConfig).map(request => request.gasConfig);
405
+ const blobConfigs = validRequests.filter(request => request.blobConfig).map(request => request.blobConfig);
403
406
 
404
407
  if (blobConfigs.length > 1) {
405
408
  throw new Error('Multiple blob configs found');
@@ -547,7 +550,16 @@ export class SequencerPublisher {
547
550
  });
548
551
  return { failedActions: requests.map(r => r.action) };
549
552
  } else {
550
- this.log.verbose(`Published bundled transactions (${actionsListStr})`, { result, requests });
553
+ this.log.verbose(`Published bundled transactions (${actionsListStr})`, {
554
+ result,
555
+ requests: requests.map(r => ({
556
+ ...r,
557
+ // Avoid logging large blob data
558
+ blobConfig: r.blobConfig
559
+ ? { ...r.blobConfig, blobs: r.blobConfig.blobs.map(b => ({ size: trimmedBytesLength(b) })) }
560
+ : undefined,
561
+ })),
562
+ });
551
563
  const successfulActions: Action[] = [];
552
564
  const failedActions: Action[] = [];
553
565
  for (const request of requests) {
@@ -586,20 +598,23 @@ export class SequencerPublisher {
586
598
  }
587
599
 
588
600
  /**
589
- * @notice Will call `canProposeAtNextEthBlock` to make sure that it is possible to propose
601
+ * @notice Will call `canProposeAt` to make sure that it is possible to propose
590
602
  * @param tipArchive - The archive to check
591
603
  * @returns The slot and block number if it is possible to propose, undefined otherwise
592
604
  */
593
- public canProposeAtNextEthBlock(
605
+ public canProposeAt(
594
606
  tipArchive: Fr,
595
607
  msgSender: EthAddress,
596
- opts: { forcePendingCheckpointNumber?: CheckpointNumber } = {},
608
+ opts: { forcePendingCheckpointNumber?: CheckpointNumber; pipelined?: boolean } = {},
597
609
  ) {
598
610
  // TODO: #14291 - should loop through multiple keys to check if any of them can propose
599
611
  const ignoredErrors = ['SlotAlreadyInChain', 'InvalidProposer', 'InvalidArchive'];
600
612
 
613
+ const pipelined = opts.pipelined ?? this.epochCache.isProposerPipeliningEnabled();
614
+ const slotOffset = pipelined ? this.aztecSlotDuration : 0n;
615
+
601
616
  return this.rollupContract
602
- .canProposeAtNextEthBlock(tipArchive.toBuffer(), msgSender.toString(), Number(this.ethereumSlotDuration), {
617
+ .canProposeAt(tipArchive.toBuffer(), msgSender.toString(), this.ethereumSlotDuration, slotOffset, {
603
618
  forcePendingCheckpointNumber: opts.forcePendingCheckpointNumber,
604
619
  })
605
620
  .catch(err => {
@@ -613,6 +628,7 @@ export class SequencerPublisher {
613
628
  return undefined;
614
629
  });
615
630
  }
631
+
616
632
  /**
617
633
  * @notice Will simulate `validateHeader` to make sure that the block header is valid
618
634
  * @dev This is a convenience function that can be used by the sequencer to validate a "partial" header.
@@ -801,7 +817,9 @@ export class SequencerPublisher {
801
817
  attestationsAndSignersSignature: Signature,
802
818
  options: { forcePendingCheckpointNumber?: CheckpointNumber },
803
819
  ): Promise<bigint> {
804
- const ts = BigInt((await this.l1TxUtils.getBlock()).timestamp + this.ethereumSlotDuration);
820
+ // Anchor the simulation timestamp to the checkpoint's own slot start time
821
+ // rather than the current L1 block timestamp, which may overshoot into the next slot if the build ran late.
822
+ const ts = checkpoint.header.timestamp;
805
823
  const blobFields = checkpoint.toBlobFields();
806
824
  const blobs = await getBlobsPerL1Block(blobFields);
807
825
  const blobInput = getPrefixedEthBlobCommitments(blobs);