@aztec/sequencer-client 0.0.0-test.0 → 0.0.1-commit.001888fc

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 (151) hide show
  1. package/dest/client/index.d.ts +1 -1
  2. package/dest/client/sequencer-client.d.ts +50 -33
  3. package/dest/client/sequencer-client.d.ts.map +1 -1
  4. package/dest/client/sequencer-client.js +164 -57
  5. package/dest/config.d.ts +35 -17
  6. package/dest/config.d.ts.map +1 -1
  7. package/dest/config.js +150 -81
  8. package/dest/global_variable_builder/global_builder.d.ts +24 -15
  9. package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
  10. package/dest/global_variable_builder/global_builder.js +63 -44
  11. package/dest/global_variable_builder/index.d.ts +1 -1
  12. package/dest/index.d.ts +2 -4
  13. package/dest/index.d.ts.map +1 -1
  14. package/dest/index.js +1 -3
  15. package/dest/publisher/config.d.ts +48 -27
  16. package/dest/publisher/config.d.ts.map +1 -1
  17. package/dest/publisher/config.js +109 -32
  18. package/dest/publisher/index.d.ts +4 -1
  19. package/dest/publisher/index.d.ts.map +1 -1
  20. package/dest/publisher/index.js +3 -0
  21. package/dest/publisher/l1_tx_failed_store/factory.d.ts +11 -0
  22. package/dest/publisher/l1_tx_failed_store/factory.d.ts.map +1 -0
  23. package/dest/publisher/l1_tx_failed_store/factory.js +22 -0
  24. package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts +59 -0
  25. package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts.map +1 -0
  26. package/dest/publisher/l1_tx_failed_store/failed_tx_store.js +1 -0
  27. package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.d.ts +15 -0
  28. package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.d.ts.map +1 -0
  29. package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.js +34 -0
  30. package/dest/publisher/l1_tx_failed_store/index.d.ts +4 -0
  31. package/dest/publisher/l1_tx_failed_store/index.d.ts.map +1 -0
  32. package/dest/publisher/l1_tx_failed_store/index.js +2 -0
  33. package/dest/publisher/sequencer-publisher-factory.d.ts +52 -0
  34. package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -0
  35. package/dest/publisher/sequencer-publisher-factory.js +76 -0
  36. package/dest/publisher/sequencer-publisher-metrics.d.ts +5 -4
  37. package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
  38. package/dest/publisher/sequencer-publisher-metrics.js +34 -62
  39. package/dest/publisher/sequencer-publisher.d.ts +158 -93
  40. package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
  41. package/dest/publisher/sequencer-publisher.js +1452 -255
  42. package/dest/sequencer/checkpoint_proposal_job.d.ts +100 -0
  43. package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -0
  44. package/dest/sequencer/checkpoint_proposal_job.js +1240 -0
  45. package/dest/sequencer/checkpoint_voter.d.ts +35 -0
  46. package/dest/sequencer/checkpoint_voter.d.ts.map +1 -0
  47. package/dest/sequencer/checkpoint_voter.js +109 -0
  48. package/dest/sequencer/config.d.ts +7 -1
  49. package/dest/sequencer/config.d.ts.map +1 -1
  50. package/dest/sequencer/errors.d.ts +11 -0
  51. package/dest/sequencer/errors.d.ts.map +1 -0
  52. package/dest/sequencer/errors.js +15 -0
  53. package/dest/sequencer/events.d.ts +46 -0
  54. package/dest/sequencer/events.d.ts.map +1 -0
  55. package/dest/sequencer/events.js +1 -0
  56. package/dest/sequencer/index.d.ts +4 -2
  57. package/dest/sequencer/index.d.ts.map +1 -1
  58. package/dest/sequencer/index.js +3 -1
  59. package/dest/sequencer/metrics.d.ts +60 -12
  60. package/dest/sequencer/metrics.d.ts.map +1 -1
  61. package/dest/sequencer/metrics.js +283 -67
  62. package/dest/sequencer/sequencer.d.ts +157 -135
  63. package/dest/sequencer/sequencer.d.ts.map +1 -1
  64. package/dest/sequencer/sequencer.js +966 -523
  65. package/dest/sequencer/timetable.d.ts +75 -25
  66. package/dest/sequencer/timetable.d.ts.map +1 -1
  67. package/dest/sequencer/timetable.js +174 -62
  68. package/dest/sequencer/types.d.ts +3 -0
  69. package/dest/sequencer/types.d.ts.map +1 -0
  70. package/dest/sequencer/types.js +1 -0
  71. package/dest/sequencer/utils.d.ts +20 -38
  72. package/dest/sequencer/utils.d.ts.map +1 -1
  73. package/dest/sequencer/utils.js +12 -47
  74. package/dest/test/index.d.ts +9 -3
  75. package/dest/test/index.d.ts.map +1 -1
  76. package/dest/test/index.js +0 -4
  77. package/dest/test/mock_checkpoint_builder.d.ts +99 -0
  78. package/dest/test/mock_checkpoint_builder.d.ts.map +1 -0
  79. package/dest/test/mock_checkpoint_builder.js +231 -0
  80. package/dest/test/utils.d.ts +53 -0
  81. package/dest/test/utils.d.ts.map +1 -0
  82. package/dest/test/utils.js +104 -0
  83. package/package.json +46 -45
  84. package/src/client/sequencer-client.ts +220 -104
  85. package/src/config.ts +172 -96
  86. package/src/global_variable_builder/global_builder.ts +85 -55
  87. package/src/index.ts +1 -3
  88. package/src/publisher/config.ts +150 -59
  89. package/src/publisher/index.ts +7 -0
  90. package/src/publisher/l1_tx_failed_store/factory.ts +32 -0
  91. package/src/publisher/l1_tx_failed_store/failed_tx_store.ts +55 -0
  92. package/src/publisher/l1_tx_failed_store/file_store_failed_tx_store.ts +46 -0
  93. package/src/publisher/l1_tx_failed_store/index.ts +3 -0
  94. package/src/publisher/sequencer-publisher-factory.ts +124 -0
  95. package/src/publisher/sequencer-publisher-metrics.ts +33 -63
  96. package/src/publisher/sequencer-publisher.ts +1266 -311
  97. package/src/sequencer/README.md +531 -0
  98. package/src/sequencer/checkpoint_proposal_job.ts +967 -0
  99. package/src/sequencer/checkpoint_voter.ts +130 -0
  100. package/src/sequencer/config.ts +8 -0
  101. package/src/sequencer/errors.ts +21 -0
  102. package/src/sequencer/events.ts +27 -0
  103. package/src/sequencer/index.ts +3 -1
  104. package/src/sequencer/metrics.ts +362 -73
  105. package/src/sequencer/sequencer.ts +712 -586
  106. package/src/sequencer/timetable.ts +224 -64
  107. package/src/sequencer/types.ts +6 -0
  108. package/src/sequencer/utils.ts +28 -60
  109. package/src/test/index.ts +11 -5
  110. package/src/test/mock_checkpoint_builder.ts +323 -0
  111. package/src/test/utils.ts +167 -0
  112. package/dest/sequencer/allowed.d.ts +0 -3
  113. package/dest/sequencer/allowed.d.ts.map +0 -1
  114. package/dest/sequencer/allowed.js +0 -27
  115. package/dest/slasher/factory.d.ts +0 -7
  116. package/dest/slasher/factory.d.ts.map +0 -1
  117. package/dest/slasher/factory.js +0 -8
  118. package/dest/slasher/index.d.ts +0 -3
  119. package/dest/slasher/index.d.ts.map +0 -1
  120. package/dest/slasher/index.js +0 -2
  121. package/dest/slasher/slasher_client.d.ts +0 -75
  122. package/dest/slasher/slasher_client.d.ts.map +0 -1
  123. package/dest/slasher/slasher_client.js +0 -132
  124. package/dest/tx_validator/archive_cache.d.ts +0 -14
  125. package/dest/tx_validator/archive_cache.d.ts.map +0 -1
  126. package/dest/tx_validator/archive_cache.js +0 -22
  127. package/dest/tx_validator/gas_validator.d.ts +0 -14
  128. package/dest/tx_validator/gas_validator.d.ts.map +0 -1
  129. package/dest/tx_validator/gas_validator.js +0 -78
  130. package/dest/tx_validator/nullifier_cache.d.ts +0 -16
  131. package/dest/tx_validator/nullifier_cache.d.ts.map +0 -1
  132. package/dest/tx_validator/nullifier_cache.js +0 -24
  133. package/dest/tx_validator/phases_validator.d.ts +0 -12
  134. package/dest/tx_validator/phases_validator.d.ts.map +0 -1
  135. package/dest/tx_validator/phases_validator.js +0 -80
  136. package/dest/tx_validator/test_utils.d.ts +0 -23
  137. package/dest/tx_validator/test_utils.d.ts.map +0 -1
  138. package/dest/tx_validator/test_utils.js +0 -26
  139. package/dest/tx_validator/tx_validator_factory.d.ts +0 -18
  140. package/dest/tx_validator/tx_validator_factory.d.ts.map +0 -1
  141. package/dest/tx_validator/tx_validator_factory.js +0 -50
  142. package/src/sequencer/allowed.ts +0 -36
  143. package/src/slasher/factory.ts +0 -15
  144. package/src/slasher/index.ts +0 -2
  145. package/src/slasher/slasher_client.ts +0 -193
  146. package/src/tx_validator/archive_cache.ts +0 -28
  147. package/src/tx_validator/gas_validator.ts +0 -101
  148. package/src/tx_validator/nullifier_cache.ts +0 -30
  149. package/src/tx_validator/phases_validator.ts +0 -98
  150. package/src/tx_validator/test_utils.ts +0 -48
  151. package/src/tx_validator/tx_validator_factory.ts +0 -120
@@ -1,43 +1,49 @@
1
- import type { BlobSinkClientInterface } from '@aztec/blob-sink/client';
1
+ import type { BlobClientInterface } from '@aztec/blob-client/client';
2
+ import { MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT } from '@aztec/constants';
2
3
  import { EpochCache } from '@aztec/epoch-cache';
3
- import {
4
- ForwarderContract,
5
- GovernanceProposerContract,
6
- RollupContract,
7
- SlashingProposerContract,
8
- createEthereumChain,
9
- createL1Clients,
10
- isAnvilTestChain,
11
- } from '@aztec/ethereum';
12
- import { L1TxUtilsWithBlobs } from '@aztec/ethereum/l1-tx-utils-with-blobs';
4
+ import { isAnvilTestChain } from '@aztec/ethereum/chain';
5
+ import { getPublicClient } from '@aztec/ethereum/client';
6
+ import { GovernanceProposerContract, RollupContract } from '@aztec/ethereum/contracts';
7
+ import { type Delayer, L1TxUtils } from '@aztec/ethereum/l1-tx-utils';
8
+ import { PublisherManager } from '@aztec/ethereum/publisher-manager';
13
9
  import { EthAddress } from '@aztec/foundation/eth-address';
14
10
  import { createLogger } from '@aztec/foundation/log';
15
11
  import type { DateProvider } from '@aztec/foundation/timer';
12
+ import type { KeystoreManager } from '@aztec/node-keystore';
16
13
  import type { P2P } from '@aztec/p2p';
17
- import { LightweightBlockBuilderFactory } from '@aztec/prover-client/block-builder';
18
- import { PublicProcessorFactory } from '@aztec/simulator/server';
19
- import type { AztecAddress } from '@aztec/stdlib/aztec-address';
20
- import type { L2BlockSource } from '@aztec/stdlib/block';
21
- import type { ContractDataSource } from '@aztec/stdlib/contract';
22
- import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
14
+ import type { SlasherClientInterface } from '@aztec/slasher';
15
+ import type { L2BlockSink, L2BlockSource } from '@aztec/stdlib/block';
16
+ import type { ValidatorClientFullConfig, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
17
+ import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
23
18
  import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
24
- import type { TelemetryClient } from '@aztec/telemetry-client';
25
- import type { ValidatorClient } from '@aztec/validator-client';
19
+ import { L1Metrics, type TelemetryClient } from '@aztec/telemetry-client';
20
+ import { FullNodeCheckpointsBuilder, NodeKeystoreAdapter, type ValidatorClient } from '@aztec/validator-client';
26
21
 
27
- import type { SequencerClientConfig } from '../config.js';
22
+ import {
23
+ DefaultSequencerConfig,
24
+ type SequencerClientConfig,
25
+ getPublisherConfigFromSequencerConfig,
26
+ } from '../config.js';
28
27
  import { GlobalVariableBuilder } from '../global_variable_builder/index.js';
29
- import { SequencerPublisher } from '../publisher/index.js';
28
+ import { SequencerPublisherFactory } from '../publisher/sequencer-publisher-factory.js';
30
29
  import { Sequencer, type SequencerConfig } from '../sequencer/index.js';
31
- import type { SlasherClient } from '../slasher/index.js';
30
+ import { SequencerTimetable } from '../sequencer/timetable.js';
32
31
 
33
32
  /**
34
33
  * Encapsulates the full sequencer and publisher.
35
34
  */
36
35
  export class SequencerClient {
37
- constructor(protected sequencer: Sequencer) {}
36
+ constructor(
37
+ protected publisherManager: PublisherManager<L1TxUtils>,
38
+ protected sequencer: Sequencer,
39
+ protected checkpointsBuilder: FullNodeCheckpointsBuilder,
40
+ protected validatorClient?: ValidatorClient,
41
+ private l1Metrics?: L1Metrics,
42
+ private delayer_?: Delayer,
43
+ ) {}
38
44
 
39
45
  /**
40
- * Initializes and starts a new instance.
46
+ * Initializes a new instance.
41
47
  * @param config - Configuration for the sequencer, publisher, and L1 tx sender.
42
48
  * @param p2pClient - P2P client that provides the txs to be sequenced.
43
49
  * @param validatorClient - Validator client performs attestation duties when rotating proposers.
@@ -46,25 +52,25 @@ export class SequencerClient {
46
52
  * @param l2BlockSource - Provides information about the previously published blocks.
47
53
  * @param l1ToL2MessageSource - Provides access to L1 to L2 messages.
48
54
  * @param prover - An instance of a block prover
49
- * @param simulationProvider - An instance of a simulation provider
50
55
  * @returns A new running instance.
51
56
  */
52
57
  public static async new(
53
58
  config: SequencerClientConfig,
54
59
  deps: {
55
- validatorClient: ValidatorClient | undefined; // allowed to be undefined while we migrate
60
+ validatorClient: ValidatorClient;
56
61
  p2pClient: P2P;
57
62
  worldStateSynchronizer: WorldStateSynchronizer;
58
- slasherClient: SlasherClient;
59
- contractDataSource: ContractDataSource;
60
- l2BlockSource: L2BlockSource;
63
+ slasherClient: SlasherClientInterface | undefined;
64
+ checkpointsBuilder: FullNodeCheckpointsBuilder;
65
+ l2BlockSource: L2BlockSource & L2BlockSink;
61
66
  l1ToL2MessageSource: L1ToL2MessageSource;
62
67
  telemetry: TelemetryClient;
63
- publisher?: SequencerPublisher;
64
- blobSinkClient?: BlobSinkClientInterface;
68
+ publisherFactory?: SequencerPublisherFactory;
69
+ blobClient: BlobClientInterface;
65
70
  dateProvider: DateProvider;
66
71
  epochCache?: EpochCache;
67
- l1TxUtils?: L1TxUtilsWithBlobs;
72
+ l1TxUtils: L1TxUtils[];
73
+ nodeKeyStore: KeystoreManager;
68
74
  },
69
75
  ) {
70
76
  const {
@@ -72,42 +78,37 @@ export class SequencerClient {
72
78
  p2pClient,
73
79
  worldStateSynchronizer,
74
80
  slasherClient,
75
- contractDataSource,
81
+ checkpointsBuilder,
76
82
  l2BlockSource,
77
83
  l1ToL2MessageSource,
78
84
  telemetry: telemetryClient,
79
85
  } = deps;
80
- const { l1RpcUrls: rpcUrls, l1ChainId: chainId, publisherPrivateKey } = config;
81
- const chain = createEthereumChain(rpcUrls, chainId);
82
- const log = createLogger('sequencer-client');
83
- const { publicClient, walletClient } = createL1Clients(rpcUrls, publisherPrivateKey, chain.chainInfo);
84
- const l1TxUtils = deps.l1TxUtils ?? new L1TxUtilsWithBlobs(publicClient, walletClient, log, config);
86
+ const { l1RpcUrls: rpcUrls, l1ChainId: chainId } = config;
87
+ const log = createLogger('sequencer');
88
+ const publicClient = getPublicClient(config);
89
+ const l1TxUtils = deps.l1TxUtils;
90
+ const l1Metrics = new L1Metrics(
91
+ telemetryClient.getMeter('L1PublisherMetrics'),
92
+ publicClient,
93
+ l1TxUtils.map(x => x.getSenderAddress()),
94
+ );
95
+ const publisherManager = new PublisherManager(
96
+ l1TxUtils,
97
+ getPublisherConfigFromSequencerConfig(config),
98
+ log.getBindings(),
99
+ );
85
100
  const rollupContract = new RollupContract(publicClient, config.l1Contracts.rollupAddress.toString());
86
- const [l1GenesisTime, slotDuration] = await Promise.all([
101
+ const [l1GenesisTime, slotDuration, rollupVersion, rollupManaLimit] = await Promise.all([
87
102
  rollupContract.getL1GenesisTime(),
88
103
  rollupContract.getSlotDuration(),
104
+ rollupContract.getVersion(),
105
+ rollupContract.getManaLimit().then(Number),
89
106
  ] as const);
90
- const forwarderContract =
91
- config.customForwarderContractAddress && config.customForwarderContractAddress !== EthAddress.ZERO
92
- ? new ForwarderContract(
93
- publicClient,
94
- config.customForwarderContractAddress.toString(),
95
- config.l1Contracts.rollupAddress.toString(),
96
- )
97
- : await ForwarderContract.create(
98
- walletClient.account.address,
99
- walletClient,
100
- publicClient,
101
- log,
102
- config.l1Contracts.rollupAddress.toString(),
103
- );
104
107
 
105
108
  const governanceProposerContract = new GovernanceProposerContract(
106
109
  publicClient,
107
110
  config.l1Contracts.governanceProposerAddress.toString(),
108
111
  );
109
- const slashingProposerAddress = await rollupContract.getSlashingProposerAddress();
110
- const slashingProposerContract = new SlashingProposerContract(publicClient, slashingProposerAddress.toString());
111
112
  const epochCache =
112
113
  deps.epochCache ??
113
114
  (await EpochCache.create(
@@ -116,74 +117,101 @@ export class SequencerClient {
116
117
  l1RpcUrls: rpcUrls,
117
118
  l1ChainId: chainId,
118
119
  viemPollingIntervalMS: config.viemPollingIntervalMS,
119
- aztecSlotDuration: config.aztecSlotDuration,
120
120
  ethereumSlotDuration: config.ethereumSlotDuration,
121
- aztecEpochDuration: config.aztecEpochDuration,
122
121
  },
123
122
  { dateProvider: deps.dateProvider },
124
123
  ));
125
124
 
126
- const publisher =
127
- deps.publisher ??
128
- new SequencerPublisher(config, {
129
- l1TxUtils,
125
+ const slashFactoryContract = new SlashFactoryContract(
126
+ publicClient,
127
+ config.l1Contracts.slashFactoryAddress?.toString() ?? EthAddress.ZERO.toString(),
128
+ );
129
+
130
+ const publisherFactory =
131
+ deps.publisherFactory ??
132
+ new SequencerPublisherFactory(config, {
130
133
  telemetry: telemetryClient,
131
- blobSinkClient: deps.blobSinkClient,
132
- rollupContract,
134
+ blobClient: deps.blobClient,
133
135
  epochCache,
134
- forwarderContract,
135
136
  governanceProposerContract,
136
- slashingProposerContract,
137
+ slashFactoryContract,
138
+ rollupContract,
139
+ dateProvider: deps.dateProvider,
140
+ publisherManager,
141
+ nodeKeyStore: NodeKeystoreAdapter.fromKeyStoreManager(deps.nodeKeyStore),
142
+ logger: log,
137
143
  });
138
- const globalsBuilder = new GlobalVariableBuilder(config);
139
-
140
- const publicProcessorFactory = new PublicProcessorFactory(contractDataSource, deps.dateProvider, telemetryClient);
141
144
 
142
145
  const ethereumSlotDuration = config.ethereumSlotDuration;
143
146
 
144
- // When running in anvil, assume we can post a tx up until the very last second of an L1 slot.
145
- // Otherwise, assume we must have broadcasted the tx before the slot started (we use a default
146
- // maxL1TxInclusionTimeIntoSlot of zero) to get the tx into that L1 slot.
147
- // In theory, the L1 slot has an initial 4s phase where the block is propagated, so we could
148
- // make it with a propagation time into slot equal to 4s. However, we prefer being conservative.
149
- // See https://www.blocknative.com/blog/anatomy-of-a-slot#7 for more info.
150
- const maxL1TxInclusionTimeIntoSlot =
151
- config.maxL1TxInclusionTimeIntoSlot ?? isAnvilTestChain(config.l1ChainId) ? ethereumSlotDuration : 0;
152
-
153
- const l1Constants = {
147
+ const globalsBuilder = new GlobalVariableBuilder({
148
+ ...config,
154
149
  l1GenesisTime,
155
150
  slotDuration: Number(slotDuration),
156
151
  ethereumSlotDuration,
157
- };
152
+ rollupVersion,
153
+ });
154
+
155
+ // When running in anvil, assume we can post a tx up until one second before the end of an L1 slot.
156
+ // Otherwise, we need the full L1 slot duration for publishing to ensure inclusion.
157
+ // In theory, the L1 slot has an initial 4s phase where the block is propagated, so we could
158
+ // reduce the publishing time allowance. However, we prefer being conservative.
159
+ // See https://www.blocknative.com/blog/anatomy-of-a-slot#7 for more info.
160
+ const l1PublishingTimeBasedOnChain = isAnvilTestChain(config.l1ChainId) ? 1 : ethereumSlotDuration;
161
+ const l1PublishingTime = config.l1PublishingTime ?? l1PublishingTimeBasedOnChain;
162
+
163
+ const { maxL2BlockGas, maxDABlockGas, maxTxsPerBlock, maxBlocksPerCheckpoint } = computeBlockLimits(
164
+ config,
165
+ rollupManaLimit,
166
+ l1PublishingTime,
167
+ log,
168
+ );
169
+
170
+ const l1Constants = { l1GenesisTime, slotDuration: Number(slotDuration), ethereumSlotDuration, rollupManaLimit };
158
171
 
159
172
  const sequencer = new Sequencer(
160
- publisher,
173
+ publisherFactory,
161
174
  validatorClient,
162
175
  globalsBuilder,
163
176
  p2pClient,
164
177
  worldStateSynchronizer,
165
178
  slasherClient,
166
- new LightweightBlockBuilderFactory(telemetryClient),
167
179
  l2BlockSource,
168
180
  l1ToL2MessageSource,
169
- publicProcessorFactory,
170
- contractDataSource,
181
+ checkpointsBuilder,
171
182
  l1Constants,
172
183
  deps.dateProvider,
173
- { ...config, maxL1TxInclusionTimeIntoSlot },
184
+ epochCache,
185
+ rollupContract,
186
+ { ...config, l1PublishingTime, maxL2BlockGas, maxDABlockGas, maxTxsPerBlock, maxBlocksPerCheckpoint },
174
187
  telemetryClient,
188
+ log,
175
189
  );
176
- await validatorClient?.start();
177
- await sequencer.start();
178
- return new SequencerClient(sequencer);
190
+
191
+ sequencer.init();
192
+
193
+ // Extract the shared delayer from the first L1TxUtils instance (all instances share the same delayer)
194
+ const delayer = l1TxUtils[0]?.delayer;
195
+
196
+ return new SequencerClient(publisherManager, sequencer, checkpointsBuilder, validatorClient, l1Metrics, delayer);
179
197
  }
180
198
 
181
199
  /**
182
- * Updates sequencer config.
200
+ * Updates sequencer and validator client config.
183
201
  * @param config - New parameters.
184
202
  */
185
- public updateSequencerConfig(config: SequencerConfig) {
186
- return this.sequencer.updateConfig(config);
203
+ public updateConfig(config: SequencerConfig & Partial<ValidatorClientFullConfig>) {
204
+ this.sequencer.updateConfig(config);
205
+ this.checkpointsBuilder.updateConfig(config);
206
+ this.validatorClient?.updateConfig(config);
207
+ }
208
+
209
+ /** Starts the sequencer. */
210
+ public async start() {
211
+ await this.validatorClient?.start();
212
+ this.sequencer.start();
213
+ this.l1Metrics?.start();
214
+ await this.publisherManager.loadState();
187
215
  }
188
216
 
189
217
  /**
@@ -191,29 +219,117 @@ export class SequencerClient {
191
219
  */
192
220
  public async stop() {
193
221
  await this.sequencer.stop();
222
+ await this.validatorClient?.stop();
223
+ this.publisherManager.interrupt();
224
+ this.l1Metrics?.stop();
194
225
  }
195
226
 
196
- /** Forces the sequencer to bypass all time and tx count checks for the next block and build anyway. */
197
- public flush() {
198
- this.sequencer.flush();
227
+ public getSequencer(): Sequencer {
228
+ return this.sequencer;
199
229
  }
200
230
 
201
- /**
202
- * Restarts the sequencer after being stopped.
203
- */
204
- public restart() {
205
- this.sequencer.restart();
231
+ /** Updates the publisher factory's node keystore adapter after a keystore reload. */
232
+ public updatePublisherNodeKeyStore(adapter: NodeKeystoreAdapter): void {
233
+ this.sequencer.updatePublisherNodeKeyStore(adapter);
234
+ }
235
+
236
+ /** Returns the shared tx delayer for sequencer L1 txs, if enabled. Test-only. */
237
+ getDelayer(): Delayer | undefined {
238
+ return this.delayer_;
239
+ }
240
+
241
+ get validatorAddresses(): EthAddress[] | undefined {
242
+ return this.sequencer.getValidatorAddresses();
206
243
  }
207
244
 
208
- get coinbase(): EthAddress {
209
- return this.sequencer.coinbase;
245
+ get maxL2BlockGas(): number | undefined {
246
+ return this.sequencer.maxL2BlockGas;
210
247
  }
248
+ }
249
+
250
+ /**
251
+ * Computes per-block L2 gas, DA gas, and TX count budgets based on the L1 rollup limits and the timetable.
252
+ * If the user explicitly set a limit, it is capped at the corresponding checkpoint limit.
253
+ * Otherwise, derives it as (checkpointLimit / maxBlocks) * multiplier, capped at the checkpoint limit.
254
+ */
255
+ export function computeBlockLimits(
256
+ config: SequencerClientConfig,
257
+ rollupManaLimit: number,
258
+ l1PublishingTime: number,
259
+ log: ReturnType<typeof createLogger>,
260
+ ): { maxL2BlockGas: number; maxDABlockGas: number; maxTxsPerBlock: number; maxBlocksPerCheckpoint: number } {
261
+ const maxNumberOfBlocks = new SequencerTimetable({
262
+ ethereumSlotDuration: config.ethereumSlotDuration,
263
+ aztecSlotDuration: config.aztecSlotDuration,
264
+ l1PublishingTime,
265
+ p2pPropagationTime: config.attestationPropagationTime,
266
+ blockDurationMs: config.blockDurationMs,
267
+ enforce: config.enforceTimeTable ?? DefaultSequencerConfig.enforceTimeTable,
268
+ }).maxNumberOfBlocks;
269
+
270
+ const multiplier = config.perBlockAllocationMultiplier ?? DefaultSequencerConfig.perBlockAllocationMultiplier;
211
271
 
212
- get feeRecipient(): AztecAddress {
213
- return this.sequencer.feeRecipient;
272
+ // Compute maxL2BlockGas
273
+ let maxL2BlockGas: number;
274
+ if (config.maxL2BlockGas !== undefined) {
275
+ if (config.maxL2BlockGas > rollupManaLimit) {
276
+ log.warn(
277
+ `Provided MAX_L2_BLOCK_GAS ${config.maxL2BlockGas} exceeds L1 rollup mana limit ${rollupManaLimit} (capping)`,
278
+ );
279
+ maxL2BlockGas = rollupManaLimit;
280
+ } else {
281
+ maxL2BlockGas = config.maxL2BlockGas;
282
+ }
283
+ } else {
284
+ maxL2BlockGas = Math.min(rollupManaLimit, Math.ceil((rollupManaLimit / maxNumberOfBlocks) * multiplier));
214
285
  }
215
286
 
216
- get forwarderAddress(): EthAddress {
217
- return this.sequencer.getForwarderAddress();
287
+ // Compute maxDABlockGas
288
+ const daCheckpointLimit = MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT;
289
+ let maxDABlockGas: number;
290
+ if (config.maxDABlockGas !== undefined) {
291
+ if (config.maxDABlockGas > daCheckpointLimit) {
292
+ log.warn(
293
+ `Provided MAX_DA_BLOCK_GAS ${config.maxDABlockGas} exceeds DA checkpoint limit ${daCheckpointLimit} (capping)`,
294
+ );
295
+ maxDABlockGas = daCheckpointLimit;
296
+ } else {
297
+ maxDABlockGas = config.maxDABlockGas;
298
+ }
299
+ } else {
300
+ maxDABlockGas = Math.min(daCheckpointLimit, Math.ceil((daCheckpointLimit / maxNumberOfBlocks) * multiplier));
218
301
  }
302
+
303
+ // Compute maxTxsPerBlock
304
+ const defaultMaxTxsPerBlock = 32;
305
+ let maxTxsPerBlock: number;
306
+ if (config.maxTxsPerBlock !== undefined) {
307
+ if (config.maxTxsPerCheckpoint !== undefined && config.maxTxsPerBlock > config.maxTxsPerCheckpoint) {
308
+ log.warn(
309
+ `Provided MAX_TX_PER_BLOCK ${config.maxTxsPerBlock} exceeds MAX_TX_PER_CHECKPOINT ${config.maxTxsPerCheckpoint} (capping)`,
310
+ );
311
+ maxTxsPerBlock = config.maxTxsPerCheckpoint;
312
+ } else {
313
+ maxTxsPerBlock = config.maxTxsPerBlock;
314
+ }
315
+ } else if (config.maxTxsPerCheckpoint !== undefined) {
316
+ maxTxsPerBlock = Math.min(
317
+ config.maxTxsPerCheckpoint,
318
+ Math.ceil((config.maxTxsPerCheckpoint / maxNumberOfBlocks) * multiplier),
319
+ );
320
+ } else {
321
+ maxTxsPerBlock = defaultMaxTxsPerBlock;
322
+ }
323
+
324
+ log.info(`Computed block limits L2=${maxL2BlockGas} DA=${maxDABlockGas} maxTxs=${maxTxsPerBlock}`, {
325
+ maxL2BlockGas,
326
+ maxDABlockGas,
327
+ maxTxsPerBlock,
328
+ rollupManaLimit,
329
+ daCheckpointLimit,
330
+ maxNumberOfBlocks,
331
+ multiplier,
332
+ });
333
+
334
+ return { maxL2BlockGas, maxDABlockGas, maxTxsPerBlock, maxBlocksPerCheckpoint: maxNumberOfBlocks };
219
335
  }