@aztec/sequencer-client 0.0.0-test.1 → 0.0.1-commit.b655e406

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 (110) hide show
  1. package/dest/client/sequencer-client.d.ts +25 -25
  2. package/dest/client/sequencer-client.d.ts.map +1 -1
  3. package/dest/client/sequencer-client.js +65 -51
  4. package/dest/config.d.ts +6 -14
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +50 -54
  7. package/dest/global_variable_builder/global_builder.d.ts +11 -6
  8. package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
  9. package/dest/global_variable_builder/global_builder.js +39 -34
  10. package/dest/index.d.ts +1 -2
  11. package/dest/index.d.ts.map +1 -1
  12. package/dest/index.js +1 -2
  13. package/dest/publisher/config.d.ts +6 -8
  14. package/dest/publisher/config.d.ts.map +1 -1
  15. package/dest/publisher/config.js +19 -17
  16. package/dest/publisher/index.d.ts +2 -0
  17. package/dest/publisher/index.d.ts.map +1 -1
  18. package/dest/publisher/index.js +3 -0
  19. package/dest/publisher/sequencer-publisher-factory.d.ts +43 -0
  20. package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -0
  21. package/dest/publisher/sequencer-publisher-factory.js +51 -0
  22. package/dest/publisher/sequencer-publisher-metrics.d.ts +2 -1
  23. package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
  24. package/dest/publisher/sequencer-publisher-metrics.js +37 -2
  25. package/dest/publisher/sequencer-publisher.d.ts +102 -69
  26. package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
  27. package/dest/publisher/sequencer-publisher.js +606 -212
  28. package/dest/sequencer/block_builder.d.ts +27 -0
  29. package/dest/sequencer/block_builder.d.ts.map +1 -0
  30. package/dest/sequencer/block_builder.js +130 -0
  31. package/dest/sequencer/config.d.ts +5 -0
  32. package/dest/sequencer/config.d.ts.map +1 -1
  33. package/dest/sequencer/errors.d.ts +11 -0
  34. package/dest/sequencer/errors.d.ts.map +1 -0
  35. package/dest/sequencer/errors.js +15 -0
  36. package/dest/sequencer/index.d.ts +1 -1
  37. package/dest/sequencer/index.d.ts.map +1 -1
  38. package/dest/sequencer/index.js +1 -1
  39. package/dest/sequencer/metrics.d.ts +18 -11
  40. package/dest/sequencer/metrics.d.ts.map +1 -1
  41. package/dest/sequencer/metrics.js +84 -50
  42. package/dest/sequencer/sequencer.d.ts +120 -81
  43. package/dest/sequencer/sequencer.d.ts.map +1 -1
  44. package/dest/sequencer/sequencer.js +589 -359
  45. package/dest/sequencer/timetable.d.ts +32 -20
  46. package/dest/sequencer/timetable.d.ts.map +1 -1
  47. package/dest/sequencer/timetable.js +57 -30
  48. package/dest/sequencer/utils.d.ts +11 -35
  49. package/dest/sequencer/utils.d.ts.map +1 -1
  50. package/dest/sequencer/utils.js +9 -47
  51. package/dest/test/index.d.ts +7 -0
  52. package/dest/test/index.d.ts.map +1 -1
  53. package/dest/test/index.js +0 -4
  54. package/dest/tx_validator/nullifier_cache.d.ts +0 -2
  55. package/dest/tx_validator/nullifier_cache.d.ts.map +1 -1
  56. package/dest/tx_validator/tx_validator_factory.d.ts +9 -10
  57. package/dest/tx_validator/tx_validator_factory.d.ts.map +1 -1
  58. package/dest/tx_validator/tx_validator_factory.js +27 -24
  59. package/package.json +42 -43
  60. package/src/client/sequencer-client.ts +94 -84
  61. package/src/config.ts +57 -61
  62. package/src/global_variable_builder/global_builder.ts +44 -23
  63. package/src/index.ts +6 -2
  64. package/src/publisher/config.ts +26 -24
  65. package/src/publisher/index.ts +4 -0
  66. package/src/publisher/sequencer-publisher-factory.ts +90 -0
  67. package/src/publisher/sequencer-publisher-metrics.ts +24 -2
  68. package/src/publisher/sequencer-publisher.ts +729 -235
  69. package/src/sequencer/block_builder.ts +218 -0
  70. package/src/sequencer/config.ts +7 -0
  71. package/src/sequencer/errors.ts +21 -0
  72. package/src/sequencer/index.ts +1 -1
  73. package/src/sequencer/metrics.ts +109 -55
  74. package/src/sequencer/sequencer.ts +766 -415
  75. package/src/sequencer/timetable.ts +98 -33
  76. package/src/sequencer/utils.ts +17 -58
  77. package/src/test/index.ts +11 -4
  78. package/src/tx_validator/tx_validator_factory.ts +44 -32
  79. package/dest/sequencer/allowed.d.ts +0 -3
  80. package/dest/sequencer/allowed.d.ts.map +0 -1
  81. package/dest/sequencer/allowed.js +0 -27
  82. package/dest/slasher/factory.d.ts +0 -7
  83. package/dest/slasher/factory.d.ts.map +0 -1
  84. package/dest/slasher/factory.js +0 -8
  85. package/dest/slasher/index.d.ts +0 -3
  86. package/dest/slasher/index.d.ts.map +0 -1
  87. package/dest/slasher/index.js +0 -2
  88. package/dest/slasher/slasher_client.d.ts +0 -75
  89. package/dest/slasher/slasher_client.d.ts.map +0 -1
  90. package/dest/slasher/slasher_client.js +0 -132
  91. package/dest/tx_validator/archive_cache.d.ts +0 -14
  92. package/dest/tx_validator/archive_cache.d.ts.map +0 -1
  93. package/dest/tx_validator/archive_cache.js +0 -22
  94. package/dest/tx_validator/gas_validator.d.ts +0 -14
  95. package/dest/tx_validator/gas_validator.d.ts.map +0 -1
  96. package/dest/tx_validator/gas_validator.js +0 -78
  97. package/dest/tx_validator/phases_validator.d.ts +0 -12
  98. package/dest/tx_validator/phases_validator.d.ts.map +0 -1
  99. package/dest/tx_validator/phases_validator.js +0 -80
  100. package/dest/tx_validator/test_utils.d.ts +0 -23
  101. package/dest/tx_validator/test_utils.d.ts.map +0 -1
  102. package/dest/tx_validator/test_utils.js +0 -26
  103. package/src/sequencer/allowed.ts +0 -36
  104. package/src/slasher/factory.ts +0 -15
  105. package/src/slasher/index.ts +0 -2
  106. package/src/slasher/slasher_client.ts +0 -193
  107. package/src/tx_validator/archive_cache.ts +0 -28
  108. package/src/tx_validator/gas_validator.ts +0 -101
  109. package/src/tx_validator/phases_validator.ts +0 -98
  110. package/src/tx_validator/test_utils.ts +0 -48
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/sequencer-client",
3
- "version": "0.0.0-test.1",
3
+ "version": "0.0.1-commit.b655e406",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -21,60 +21,55 @@
21
21
  "build": "yarn clean && tsc -b",
22
22
  "build:dev": "tsc -b --watch",
23
23
  "clean": "rm -rf ./dest .tsbuildinfo",
24
- "formatting": "run -T prettier --check ./src && run -T eslint ./src",
25
- "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src",
26
24
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}",
27
25
  "test:integration": "concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"",
28
26
  "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json"
29
27
  },
30
28
  "dependencies": {
31
- "@aztec/aztec.js": "0.0.0-test.1",
32
- "@aztec/bb-prover": "0.0.0-test.1",
33
- "@aztec/blob-lib": "0.0.0-test.1",
34
- "@aztec/blob-sink": "0.0.0-test.1",
35
- "@aztec/constants": "0.0.0-test.1",
36
- "@aztec/epoch-cache": "0.0.0-test.1",
37
- "@aztec/ethereum": "0.0.0-test.1",
38
- "@aztec/foundation": "0.0.0-test.1",
39
- "@aztec/l1-artifacts": "0.0.0-test.1",
40
- "@aztec/merkle-tree": "0.0.0-test.1",
41
- "@aztec/noir-contracts.js": "0.0.0-test.1",
42
- "@aztec/noir-protocol-circuits-types": "0.0.0-test.1",
43
- "@aztec/p2p": "0.0.0-test.1",
44
- "@aztec/protocol-contracts": "0.0.0-test.1",
45
- "@aztec/prover-client": "0.0.0-test.1",
46
- "@aztec/simulator": "0.0.0-test.1",
47
- "@aztec/stdlib": "0.0.0-test.1",
48
- "@aztec/telemetry-client": "0.0.0-test.1",
49
- "@aztec/validator-client": "0.0.0-test.1",
50
- "@aztec/world-state": "0.0.0-test.1",
29
+ "@aztec/aztec.js": "0.0.1-commit.b655e406",
30
+ "@aztec/bb-prover": "0.0.1-commit.b655e406",
31
+ "@aztec/blob-lib": "0.0.1-commit.b655e406",
32
+ "@aztec/blob-sink": "0.0.1-commit.b655e406",
33
+ "@aztec/constants": "0.0.1-commit.b655e406",
34
+ "@aztec/epoch-cache": "0.0.1-commit.b655e406",
35
+ "@aztec/ethereum": "0.0.1-commit.b655e406",
36
+ "@aztec/foundation": "0.0.1-commit.b655e406",
37
+ "@aztec/l1-artifacts": "0.0.1-commit.b655e406",
38
+ "@aztec/merkle-tree": "0.0.1-commit.b655e406",
39
+ "@aztec/node-keystore": "0.0.1-commit.b655e406",
40
+ "@aztec/noir-acvm_js": "0.0.1-commit.b655e406",
41
+ "@aztec/noir-contracts.js": "0.0.1-commit.b655e406",
42
+ "@aztec/noir-protocol-circuits-types": "0.0.1-commit.b655e406",
43
+ "@aztec/noir-types": "0.0.1-commit.b655e406",
44
+ "@aztec/p2p": "0.0.1-commit.b655e406",
45
+ "@aztec/protocol-contracts": "0.0.1-commit.b655e406",
46
+ "@aztec/prover-client": "0.0.1-commit.b655e406",
47
+ "@aztec/simulator": "0.0.1-commit.b655e406",
48
+ "@aztec/slasher": "0.0.1-commit.b655e406",
49
+ "@aztec/stdlib": "0.0.1-commit.b655e406",
50
+ "@aztec/telemetry-client": "0.0.1-commit.b655e406",
51
+ "@aztec/validator-client": "0.0.1-commit.b655e406",
52
+ "@aztec/world-state": "0.0.1-commit.b655e406",
51
53
  "lodash.chunk": "^4.2.0",
52
- "lodash.pick": "^4.4.0",
53
54
  "tslib": "^2.4.0",
54
- "viem": "2.22.8",
55
- "@aztec/noir-acvm_js": "0.0.0-test.1",
56
- "@aztec/noir-types": "0.0.0-test.1"
55
+ "viem": "npm:@spalladino/viem@2.38.2-eip7594.0"
57
56
  },
58
57
  "devDependencies": {
59
- "@aztec/archiver": "0.0.0-test.1",
60
- "@aztec/kv-store": "0.0.0-test.1",
61
- "@jest/globals": "^29.5.0",
62
- "@types/jest": "^29.5.0",
63
- "@types/levelup": "^5.1.2",
58
+ "@aztec/archiver": "0.0.1-commit.b655e406",
59
+ "@aztec/kv-store": "0.0.1-commit.b655e406",
60
+ "@jest/globals": "^30.0.0",
61
+ "@types/jest": "^30.0.0",
64
62
  "@types/lodash.chunk": "^4.2.7",
65
63
  "@types/lodash.pick": "^4.4.7",
66
- "@types/memdown": "^3.0.0",
67
- "@types/node": "^18.7.23",
64
+ "@types/node": "^22.15.17",
68
65
  "concurrently": "^7.6.0",
69
- "eslint": "^8.37.0",
70
- "express": "^4.21.1",
71
- "jest": "^29.5.0",
72
- "jest-mock-extended": "^3.0.3",
73
- "levelup": "^5.1.1",
74
- "memdown": "^6.1.1",
75
- "prettier": "^2.8.7",
66
+ "eslint": "^9.26.0",
67
+ "express": "^4.21.2",
68
+ "jest": "^30.0.0",
69
+ "jest-mock-extended": "^4.0.0",
70
+ "prettier": "^3.5.3",
76
71
  "ts-node": "^10.9.1",
77
- "typescript": "^5.0.4"
72
+ "typescript": "^5.3.3"
78
73
  },
79
74
  "files": [
80
75
  "dest",
@@ -83,7 +78,7 @@
83
78
  ],
84
79
  "types": "./dest/index.d.ts",
85
80
  "engines": {
86
- "node": ">=18"
81
+ "node": ">=20.10"
87
82
  },
88
83
  "jest": {
89
84
  "extensionsToTreatAsEsm": [
@@ -116,6 +111,10 @@
116
111
  "testTimeout": 120000,
117
112
  "setupFiles": [
118
113
  "../../foundation/src/jest/setup.mjs"
114
+ ],
115
+ "testEnvironment": "../../foundation/src/jest/env.mjs",
116
+ "setupFilesAfterEnv": [
117
+ "../../foundation/src/jest/setupAfterEnv.mjs"
119
118
  ]
120
119
  }
121
120
  }
@@ -1,43 +1,49 @@
1
1
  import type { BlobSinkClientInterface } from '@aztec/blob-sink/client';
2
2
  import { EpochCache } from '@aztec/epoch-cache';
3
3
  import {
4
- ForwarderContract,
5
4
  GovernanceProposerContract,
5
+ PublisherManager,
6
6
  RollupContract,
7
- SlashingProposerContract,
8
- createEthereumChain,
9
- createL1Clients,
7
+ getPublicClient,
10
8
  isAnvilTestChain,
11
9
  } from '@aztec/ethereum';
12
10
  import { L1TxUtilsWithBlobs } from '@aztec/ethereum/l1-tx-utils-with-blobs';
13
11
  import { EthAddress } from '@aztec/foundation/eth-address';
14
12
  import { createLogger } from '@aztec/foundation/log';
15
13
  import type { DateProvider } from '@aztec/foundation/timer';
14
+ import type { KeystoreManager } from '@aztec/node-keystore';
16
15
  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';
16
+ import type { SlasherClientInterface } from '@aztec/slasher';
20
17
  import type { L2BlockSource } from '@aztec/stdlib/block';
21
- import type { ContractDataSource } from '@aztec/stdlib/contract';
22
- import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
18
+ import type {
19
+ IFullNodeBlockBuilder,
20
+ ValidatorClientFullConfig,
21
+ WorldStateSynchronizer,
22
+ } from '@aztec/stdlib/interfaces/server';
23
+ import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
23
24
  import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
24
- import type { TelemetryClient } from '@aztec/telemetry-client';
25
- import type { ValidatorClient } from '@aztec/validator-client';
25
+ import { L1Metrics, type TelemetryClient } from '@aztec/telemetry-client';
26
+ import { NodeKeystoreAdapter, type ValidatorClient } from '@aztec/validator-client';
26
27
 
27
28
  import type { SequencerClientConfig } from '../config.js';
28
29
  import { GlobalVariableBuilder } from '../global_variable_builder/index.js';
29
- import { SequencerPublisher } from '../publisher/index.js';
30
+ import { SequencerPublisherFactory } from '../publisher/sequencer-publisher-factory.js';
30
31
  import { Sequencer, type SequencerConfig } from '../sequencer/index.js';
31
- import type { SlasherClient } from '../slasher/index.js';
32
32
 
33
33
  /**
34
34
  * Encapsulates the full sequencer and publisher.
35
35
  */
36
36
  export class SequencerClient {
37
- constructor(protected sequencer: Sequencer) {}
37
+ constructor(
38
+ protected publisherManager: PublisherManager<L1TxUtilsWithBlobs>,
39
+ protected sequencer: Sequencer,
40
+ protected blockBuilder: IFullNodeBlockBuilder,
41
+ protected validatorClient?: ValidatorClient,
42
+ private l1Metrics?: L1Metrics,
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,7 +52,6 @@ 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(
@@ -55,16 +60,17 @@ export class SequencerClient {
55
60
  validatorClient: ValidatorClient | undefined; // allowed to be undefined while we migrate
56
61
  p2pClient: P2P;
57
62
  worldStateSynchronizer: WorldStateSynchronizer;
58
- slasherClient: SlasherClient;
59
- contractDataSource: ContractDataSource;
63
+ slasherClient: SlasherClientInterface | undefined;
64
+ blockBuilder: IFullNodeBlockBuilder;
60
65
  l2BlockSource: L2BlockSource;
61
66
  l1ToL2MessageSource: L1ToL2MessageSource;
62
67
  telemetry: TelemetryClient;
63
- publisher?: SequencerPublisher;
68
+ publisherFactory?: SequencerPublisherFactory;
64
69
  blobSinkClient?: BlobSinkClientInterface;
65
70
  dateProvider: DateProvider;
66
71
  epochCache?: EpochCache;
67
- l1TxUtils?: L1TxUtilsWithBlobs;
72
+ l1TxUtils: L1TxUtilsWithBlobs[];
73
+ nodeKeyStore: KeystoreManager;
68
74
  },
69
75
  ) {
70
76
  const {
@@ -72,42 +78,31 @@ export class SequencerClient {
72
78
  p2pClient,
73
79
  worldStateSynchronizer,
74
80
  slasherClient,
75
- contractDataSource,
81
+ blockBuilder,
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(l1TxUtils, config);
85
96
  const rollupContract = new RollupContract(publicClient, config.l1Contracts.rollupAddress.toString());
86
97
  const [l1GenesisTime, slotDuration] = await Promise.all([
87
98
  rollupContract.getL1GenesisTime(),
88
99
  rollupContract.getSlotDuration(),
89
100
  ] 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
101
 
105
102
  const governanceProposerContract = new GovernanceProposerContract(
106
103
  publicClient,
107
104
  config.l1Contracts.governanceProposerAddress.toString(),
108
105
  );
109
- const slashingProposerAddress = await rollupContract.getSlashingProposerAddress();
110
- const slashingProposerContract = new SlashingProposerContract(publicClient, slashingProposerAddress.toString());
111
106
  const epochCache =
112
107
  deps.epochCache ??
113
108
  (await EpochCache.create(
@@ -116,39 +111,51 @@ export class SequencerClient {
116
111
  l1RpcUrls: rpcUrls,
117
112
  l1ChainId: chainId,
118
113
  viemPollingIntervalMS: config.viemPollingIntervalMS,
119
- aztecSlotDuration: config.aztecSlotDuration,
120
114
  ethereumSlotDuration: config.ethereumSlotDuration,
121
- aztecEpochDuration: config.aztecEpochDuration,
122
115
  },
123
116
  { dateProvider: deps.dateProvider },
124
117
  ));
125
118
 
126
- const publisher =
127
- deps.publisher ??
128
- new SequencerPublisher(config, {
129
- l1TxUtils,
119
+ const slashFactoryContract = new SlashFactoryContract(
120
+ publicClient,
121
+ config.l1Contracts.slashFactoryAddress?.toString() ?? EthAddress.ZERO.toString(),
122
+ );
123
+
124
+ const publisherFactory =
125
+ deps.publisherFactory ??
126
+ new SequencerPublisherFactory(config, {
130
127
  telemetry: telemetryClient,
131
128
  blobSinkClient: deps.blobSinkClient,
132
- rollupContract,
133
129
  epochCache,
134
- forwarderContract,
135
130
  governanceProposerContract,
136
- slashingProposerContract,
131
+ slashFactoryContract,
132
+ rollupContract,
133
+ dateProvider: deps.dateProvider,
134
+ publisherManager,
135
+ nodeKeyStore: NodeKeystoreAdapter.fromKeyStoreManager(deps.nodeKeyStore),
136
+ logger: log,
137
137
  });
138
138
  const globalsBuilder = new GlobalVariableBuilder(config);
139
139
 
140
- const publicProcessorFactory = new PublicProcessorFactory(contractDataSource, deps.dateProvider, telemetryClient);
141
-
142
140
  const ethereumSlotDuration = config.ethereumSlotDuration;
143
141
 
144
- // When running in anvil, assume we can post a tx up until the very last second of an L1 slot.
142
+ const rollupManaLimit = Number(await rollupContract.getManaLimit());
143
+ let sequencerManaLimit = config.maxL2BlockGas ?? rollupManaLimit;
144
+ if (sequencerManaLimit > rollupManaLimit) {
145
+ log.warn(
146
+ `Provided maxL2BlockGas of ${sequencerManaLimit} is greater than the maximum allowed by the L1 (${rollupManaLimit}), setting limit to ${rollupManaLimit}`,
147
+ );
148
+ sequencerManaLimit = rollupManaLimit;
149
+ }
150
+
151
+ // When running in anvil, assume we can post a tx up until one second before the end of an L1 slot.
145
152
  // Otherwise, assume we must have broadcasted the tx before the slot started (we use a default
146
153
  // maxL1TxInclusionTimeIntoSlot of zero) to get the tx into that L1 slot.
147
154
  // In theory, the L1 slot has an initial 4s phase where the block is propagated, so we could
148
155
  // make it with a propagation time into slot equal to 4s. However, we prefer being conservative.
149
156
  // See https://www.blocknative.com/blog/anatomy-of-a-slot#7 for more info.
150
157
  const maxL1TxInclusionTimeIntoSlot =
151
- config.maxL1TxInclusionTimeIntoSlot ?? isAnvilTestChain(config.l1ChainId) ? ethereumSlotDuration : 0;
158
+ (config.maxL1TxInclusionTimeIntoSlot ?? isAnvilTestChain(config.l1ChainId)) ? ethereumSlotDuration - 1 : 0;
152
159
 
153
160
  const l1Constants = {
154
161
  l1GenesisTime,
@@ -157,33 +164,45 @@ export class SequencerClient {
157
164
  };
158
165
 
159
166
  const sequencer = new Sequencer(
160
- publisher,
167
+ publisherFactory,
161
168
  validatorClient,
162
169
  globalsBuilder,
163
170
  p2pClient,
164
171
  worldStateSynchronizer,
165
172
  slasherClient,
166
- new LightweightBlockBuilderFactory(telemetryClient),
167
173
  l2BlockSource,
168
174
  l1ToL2MessageSource,
169
- publicProcessorFactory,
170
- contractDataSource,
175
+ blockBuilder,
171
176
  l1Constants,
172
177
  deps.dateProvider,
173
- { ...config, maxL1TxInclusionTimeIntoSlot },
178
+ epochCache,
179
+ rollupContract,
180
+ { ...config, maxL1TxInclusionTimeIntoSlot, maxL2BlockGas: sequencerManaLimit },
174
181
  telemetryClient,
182
+ log,
175
183
  );
176
- await validatorClient?.start();
177
- await sequencer.start();
178
- return new SequencerClient(sequencer);
184
+
185
+ await sequencer.init();
186
+
187
+ return new SequencerClient(publisherManager, sequencer, blockBuilder, validatorClient, l1Metrics);
179
188
  }
180
189
 
181
190
  /**
182
- * Updates sequencer config.
191
+ * Updates sequencer and validator client config.
183
192
  * @param config - New parameters.
184
193
  */
185
- public updateSequencerConfig(config: SequencerConfig) {
186
- return this.sequencer.updateConfig(config);
194
+ public updateConfig(config: SequencerConfig & Partial<ValidatorClientFullConfig>) {
195
+ this.sequencer.updateConfig(config);
196
+ this.blockBuilder.updateConfig(config);
197
+ this.validatorClient?.updateConfig(config);
198
+ }
199
+
200
+ /** Starts the sequencer. */
201
+ public async start() {
202
+ await this.validatorClient?.start();
203
+ this.sequencer.start();
204
+ this.l1Metrics?.start();
205
+ await this.publisherManager.loadState();
187
206
  }
188
207
 
189
208
  /**
@@ -191,29 +210,20 @@ export class SequencerClient {
191
210
  */
192
211
  public async stop() {
193
212
  await this.sequencer.stop();
213
+ await this.validatorClient?.stop();
214
+ this.publisherManager.interrupt();
215
+ this.l1Metrics?.stop();
194
216
  }
195
217
 
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();
199
- }
200
-
201
- /**
202
- * Restarts the sequencer after being stopped.
203
- */
204
- public restart() {
205
- this.sequencer.restart();
206
- }
207
-
208
- get coinbase(): EthAddress {
209
- return this.sequencer.coinbase;
218
+ public getSequencer(): Sequencer {
219
+ return this.sequencer;
210
220
  }
211
221
 
212
- get feeRecipient(): AztecAddress {
213
- return this.sequencer.feeRecipient;
222
+ get validatorAddresses(): EthAddress[] | undefined {
223
+ return this.sequencer.getValidatorAddresses();
214
224
  }
215
225
 
216
- get forwarderAddress(): EthAddress {
217
- return this.sequencer.getForwarderAddress();
226
+ get maxL2BlockGas(): number | undefined {
227
+ return this.sequencer.maxL2BlockGas;
218
228
  }
219
229
  }
package/src/config.ts CHANGED
@@ -12,10 +12,11 @@ import {
12
12
  pickConfigMappings,
13
13
  } from '@aztec/foundation/config';
14
14
  import { EthAddress } from '@aztec/foundation/eth-address';
15
- import { Fr } from '@aztec/foundation/fields';
16
- import { FunctionSelector } from '@aztec/stdlib/abi';
15
+ import { type KeyStoreConfig, keyStoreConfigMappings } from '@aztec/node-keystore';
16
+ import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p';
17
17
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
18
- import { type AllowedElement, type ChainConfig, type SequencerConfig, chainConfigMappings } from '@aztec/stdlib/config';
18
+ import { type ChainConfig, type SequencerConfig, chainConfigMappings } from '@aztec/stdlib/config';
19
+ import { type ValidatorClientConfig, validatorClientConfigMappings } from '@aztec/validator-client';
19
20
 
20
21
  import {
21
22
  type PublisherConfig,
@@ -27,14 +28,19 @@ import {
27
28
  export * from './publisher/config.js';
28
29
  export type { SequencerConfig };
29
30
 
31
+ export const DEFAULT_ATTESTATION_PROPAGATION_TIME = 2;
32
+
30
33
  /**
31
34
  * Configuration settings for the SequencerClient.
32
35
  */
33
36
  export type SequencerClientConfig = PublisherConfig &
37
+ KeyStoreConfig &
38
+ ValidatorClientConfig &
34
39
  TxSenderConfig &
35
40
  SequencerConfig &
36
41
  L1ReaderConfig &
37
42
  ChainConfig &
43
+ Pick<P2PConfig, 'txPublicSetupAllowList'> &
38
44
  Pick<L1ContractsConfig, 'ethereumSlotDuration' | 'aztecSlotDuration' | 'aztecEpochDuration'>;
39
45
 
40
46
  export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
@@ -53,6 +59,11 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
53
59
  description: 'The minimum number of txs to include in a block.',
54
60
  ...numberConfigHelper(1),
55
61
  },
62
+ publishTxsWithProposals: {
63
+ env: 'SEQ_PUBLISH_TXS_WITH_PROPOSALS',
64
+ description: 'Whether to publish txs with proposals.',
65
+ ...booleanConfigHelper(false),
66
+ },
56
67
  maxL2BlockGas: {
57
68
  env: 'SEQ_MAX_L2_BLOCK_GAS',
58
69
  description: 'The maximum L2 block gas.',
@@ -81,13 +92,6 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
81
92
  env: 'ACVM_BINARY_PATH',
82
93
  description: 'The path to the ACVM binary',
83
94
  },
84
- allowedInSetup: {
85
- env: 'SEQ_ALLOWED_SETUP_FN',
86
- parseEnv: (val: string) => parseSequencerAllowList(val),
87
- description: 'The list of functions calls allowed to run in setup',
88
- printDefault: () =>
89
- 'AuthRegistry, FeeJuice.increase_public_balance, Token.increase_public_balance, FPC.prepare_fee',
90
- },
91
95
  maxBlockSizeInBytes: {
92
96
  env: 'SEQ_MAX_BLOCK_SIZE_IN_BYTES',
93
97
  description: 'Max block size',
@@ -97,7 +101,7 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
97
101
  env: 'SEQ_ENFORCE_TIME_TABLE',
98
102
  description: 'Whether to enforce the time table when building blocks',
99
103
  ...booleanConfigHelper(),
100
- defaultValue: false,
104
+ defaultValue: true,
101
105
  },
102
106
  governanceProposerPayload: {
103
107
  env: 'GOVERNANCE_PROPOSER_PAYLOAD_ADDRESS',
@@ -110,10 +114,52 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
110
114
  description: 'How many seconds into an L1 slot we can still send a tx and get it mined.',
111
115
  parseEnv: (val: string) => (val ? parseInt(val, 10) : undefined),
112
116
  },
117
+ attestationPropagationTime: {
118
+ env: 'SEQ_ATTESTATION_PROPAGATION_TIME',
119
+ description: 'How many seconds it takes for proposals and attestations to travel across the p2p layer (one-way)',
120
+ ...numberConfigHelper(DEFAULT_ATTESTATION_PROPAGATION_TIME),
121
+ },
122
+ fakeProcessingDelayPerTxMs: {
123
+ description: 'Used for testing to introduce a fake delay after processing each tx',
124
+ },
125
+ secondsBeforeInvalidatingBlockAsCommitteeMember: {
126
+ env: 'SEQ_SECONDS_BEFORE_INVALIDATING_BLOCK_AS_COMMITTEE_MEMBER',
127
+ description:
128
+ 'How many seconds to wait before trying to invalidate a block from the pending chain as a committee member (zero to never invalidate).' +
129
+ ' The next proposer is expected to invalidate, so the committee acts as a fallback.',
130
+ ...numberConfigHelper(144), // 12 L1 blocks
131
+ },
132
+ secondsBeforeInvalidatingBlockAsNonCommitteeMember: {
133
+ env: 'SEQ_SECONDS_BEFORE_INVALIDATING_BLOCK_AS_NON_COMMITTEE_MEMBER',
134
+ description:
135
+ 'How many seconds to wait before trying to invalidate a block from the pending chain as a non-committee member (zero to never invalidate).' +
136
+ ' The next proposer is expected to invalidate, then the committee, so other sequencers act as a fallback.',
137
+ ...numberConfigHelper(432), // 36 L1 blocks
138
+ },
139
+ skipCollectingAttestations: {
140
+ description:
141
+ 'Whether to skip collecting attestations from validators and only use self-attestations (for testing only)',
142
+ ...booleanConfigHelper(false),
143
+ },
144
+ skipInvalidateBlockAsProposer: {
145
+ description: 'Do not invalidate the previous block if invalid when we are the proposer (for testing only)',
146
+ ...booleanConfigHelper(false),
147
+ },
148
+ broadcastInvalidBlockProposal: {
149
+ description: 'Broadcast invalid block proposals with corrupted state (for testing only)',
150
+ ...booleanConfigHelper(false),
151
+ },
152
+ injectFakeAttestation: {
153
+ description: 'Inject a fake attestation (for testing only)',
154
+ ...booleanConfigHelper(false),
155
+ },
156
+ ...pickConfigMappings(p2pConfigMappings, ['txPublicSetupAllowList']),
113
157
  };
114
158
 
115
159
  export const sequencerClientConfigMappings: ConfigMappingsType<SequencerClientConfig> = {
160
+ ...validatorClientConfigMappings,
116
161
  ...sequencerConfigMappings,
162
+ ...keyStoreConfigMappings,
117
163
  ...l1ReaderConfigMappings,
118
164
  ...getTxSenderConfigMappings('SEQ'),
119
165
  ...getPublisherConfigMappings('SEQ'),
@@ -127,53 +173,3 @@ export const sequencerClientConfigMappings: ConfigMappingsType<SequencerClientCo
127
173
  export function getConfigEnvVars(): SequencerClientConfig {
128
174
  return getConfigFromMappings<SequencerClientConfig>(sequencerClientConfigMappings);
129
175
  }
130
-
131
- /**
132
- * Parses a string to a list of allowed elements.
133
- * Each encoded is expected to be of one of the following formats
134
- * `I:${address}`
135
- * `I:${address}:${selector}`
136
- * `C:${classId}`
137
- * `C:${classId}:${selector}`
138
- *
139
- * @param value The string to parse
140
- * @returns A list of allowed elements
141
- */
142
- export function parseSequencerAllowList(value: string): AllowedElement[] {
143
- const entries: AllowedElement[] = [];
144
-
145
- if (!value) {
146
- return entries;
147
- }
148
-
149
- for (const val of value.split(',')) {
150
- const [typeString, identifierString, selectorString] = val.split(':');
151
- const selector = selectorString !== undefined ? FunctionSelector.fromString(selectorString) : undefined;
152
-
153
- if (typeString === 'I') {
154
- if (selector) {
155
- entries.push({
156
- address: AztecAddress.fromString(identifierString),
157
- selector,
158
- });
159
- } else {
160
- entries.push({
161
- address: AztecAddress.fromString(identifierString),
162
- });
163
- }
164
- } else if (typeString === 'C') {
165
- if (selector) {
166
- entries.push({
167
- classId: Fr.fromHexString(identifierString),
168
- selector,
169
- });
170
- } else {
171
- entries.push({
172
- classId: Fr.fromHexString(identifierString),
173
- });
174
- }
175
- }
176
- }
177
-
178
- return entries;
179
- }