@aztec/sequencer-client 0.48.0 → 0.50.1
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.
- package/dest/block_builder/index.d.ts +26 -0
- package/dest/block_builder/index.d.ts.map +1 -0
- package/dest/block_builder/index.js +40 -0
- package/dest/client/sequencer-client.d.ts +6 -2
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +14 -7
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +1 -6
- package/dest/global_variable_builder/global_builder.d.ts +6 -54
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +24 -12
- package/dest/global_variable_builder/index.d.ts +0 -9
- package/dest/global_variable_builder/index.d.ts.map +1 -1
- package/dest/global_variable_builder/index.js +2 -12
- package/dest/publisher/index.d.ts +0 -8
- package/dest/publisher/index.d.ts.map +1 -1
- package/dest/publisher/index.js +1 -10
- package/dest/publisher/l1-publisher.d.ts +26 -70
- package/dest/publisher/l1-publisher.d.ts.map +1 -1
- package/dest/publisher/l1-publisher.js +168 -19
- package/dest/sequencer/sequencer.d.ts +25 -11
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +90 -36
- package/package.json +18 -15
- package/src/block_builder/index.ts +51 -0
- package/src/client/sequencer-client.ts +15 -7
- package/src/config.ts +0 -5
- package/src/global_variable_builder/global_builder.ts +38 -62
- package/src/global_variable_builder/index.ts +0 -15
- package/src/publisher/index.ts +0 -14
- package/src/publisher/l1-publisher.ts +217 -95
- package/src/sequencer/sequencer.ts +113 -45
- package/dest/global_variable_builder/viem-reader.d.ts +0 -17
- package/dest/global_variable_builder/viem-reader.d.ts.map +0 -1
- package/dest/global_variable_builder/viem-reader.js +0 -40
- package/dest/publisher/viem-tx-sender.d.ts +0 -59
- package/dest/publisher/viem-tx-sender.d.ts.map +0 -1
- package/dest/publisher/viem-tx-sender.js +0 -236
- package/dest/receiver.d.ts +0 -10
- package/dest/receiver.d.ts.map +0 -1
- package/dest/receiver.js +0 -2
- package/src/global_variable_builder/viem-reader.ts +0 -64
- package/src/publisher/viem-tx-sender.ts +0 -296
- package/src/receiver.ts +0 -11
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
import { ETHEREUM_SLOT_DURATION, EthAddress } from '@aztec/circuits.js';
|
|
2
|
+
import { createEthereumChain } from '@aztec/ethereum';
|
|
1
3
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
2
4
|
import { serializeToBuffer } from '@aztec/foundation/serialize';
|
|
3
5
|
import { InterruptibleSleep } from '@aztec/foundation/sleep';
|
|
4
6
|
import { Timer } from '@aztec/foundation/timer';
|
|
7
|
+
import { AvailabilityOracleAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
5
8
|
import pick from 'lodash.pick';
|
|
9
|
+
import { createPublicClient, createWalletClient, getAddress, getContract, hexToBytes, http, } from 'viem';
|
|
10
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
6
11
|
import { L1PublisherMetrics } from './l1-publisher-metrics.js';
|
|
7
12
|
/**
|
|
8
13
|
* Publishes L2 blocks to L1. This implementation does *not* retry a transaction in
|
|
@@ -13,25 +18,77 @@ import { L1PublisherMetrics } from './l1-publisher-metrics.js';
|
|
|
13
18
|
* Adapted from https://github.com/AztecProtocol/aztec2-internal/blob/master/falafel/src/rollup_publisher.ts.
|
|
14
19
|
*/
|
|
15
20
|
export class L1Publisher {
|
|
16
|
-
constructor(
|
|
17
|
-
this.txSender = txSender;
|
|
21
|
+
constructor(config, client) {
|
|
18
22
|
this.interruptibleSleep = new InterruptibleSleep();
|
|
19
23
|
this.interrupted = false;
|
|
20
24
|
this.log = createDebugLogger('aztec:sequencer:publisher');
|
|
21
25
|
this.sleepTimeMs = config?.l1PublishRetryIntervalMS ?? 60000;
|
|
22
26
|
this.metrics = new L1PublisherMetrics(client, 'L1Publisher');
|
|
27
|
+
const { l1RpcUrl: rpcUrl, l1ChainId: chainId, publisherPrivateKey, l1Contracts } = config;
|
|
28
|
+
const chain = createEthereumChain(rpcUrl, chainId);
|
|
29
|
+
this.account = privateKeyToAccount(publisherPrivateKey);
|
|
30
|
+
const walletClient = createWalletClient({
|
|
31
|
+
account: this.account,
|
|
32
|
+
chain: chain.chainInfo,
|
|
33
|
+
transport: http(chain.rpcUrl),
|
|
34
|
+
});
|
|
35
|
+
this.publicClient = createPublicClient({
|
|
36
|
+
chain: chain.chainInfo,
|
|
37
|
+
transport: http(chain.rpcUrl),
|
|
38
|
+
});
|
|
39
|
+
this.availabilityOracleContract = getContract({
|
|
40
|
+
address: getAddress(l1Contracts.availabilityOracleAddress.toString()),
|
|
41
|
+
abi: AvailabilityOracleAbi,
|
|
42
|
+
client: walletClient,
|
|
43
|
+
});
|
|
44
|
+
this.rollupContract = getContract({
|
|
45
|
+
address: getAddress(l1Contracts.rollupAddress.toString()),
|
|
46
|
+
abi: RollupAbi,
|
|
47
|
+
client: walletClient,
|
|
48
|
+
});
|
|
23
49
|
}
|
|
24
|
-
|
|
25
|
-
return
|
|
50
|
+
getSenderAddress() {
|
|
51
|
+
return Promise.resolve(EthAddress.fromString(this.account.address));
|
|
26
52
|
}
|
|
27
|
-
|
|
28
|
-
|
|
53
|
+
// Computes who will be the L2 proposer at the next Ethereum block
|
|
54
|
+
// Using next Ethereum block so we do NOT need to wait for it being mined before seeing the effect
|
|
55
|
+
// @note Assumes that all ethereum slots have blocks
|
|
56
|
+
async getProposerAtNextEthBlock() {
|
|
57
|
+
try {
|
|
58
|
+
const ts = BigInt((await this.publicClient.getBlock()).timestamp + BigInt(ETHEREUM_SLOT_DURATION));
|
|
59
|
+
const submitter = await this.rollupContract.read.getProposerAt([ts]);
|
|
60
|
+
return EthAddress.fromString(submitter);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
this.log.warn(`Failed to get submitter: ${err}`);
|
|
64
|
+
return EthAddress.ZERO;
|
|
65
|
+
}
|
|
29
66
|
}
|
|
30
67
|
async isItMyTurnToSubmit() {
|
|
31
|
-
const submitter = await this.
|
|
32
|
-
const sender = await this.
|
|
68
|
+
const submitter = await this.getProposerAtNextEthBlock();
|
|
69
|
+
const sender = await this.getSenderAddress();
|
|
33
70
|
return submitter.isZero() || submitter.equals(sender);
|
|
34
71
|
}
|
|
72
|
+
async getCurrentEpochCommittee() {
|
|
73
|
+
const committee = await this.rollupContract.read.getCurrentEpochCommittee();
|
|
74
|
+
return committee.map(EthAddress.fromString);
|
|
75
|
+
}
|
|
76
|
+
checkIfTxsAreAvailable(block) {
|
|
77
|
+
const args = [`0x${block.body.getTxsEffectsHash().toString('hex').padStart(64, '0')}`];
|
|
78
|
+
return this.availabilityOracleContract.read.isAvailable(args);
|
|
79
|
+
}
|
|
80
|
+
async getTransactionStats(txHash) {
|
|
81
|
+
const tx = await this.publicClient.getTransaction({ hash: txHash });
|
|
82
|
+
if (!tx) {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
const calldata = hexToBytes(tx.input);
|
|
86
|
+
return {
|
|
87
|
+
transactionHash: tx.hash,
|
|
88
|
+
calldataSize: calldata.length,
|
|
89
|
+
calldataGas: getCalldataGasUsage(calldata),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
35
92
|
/**
|
|
36
93
|
* Publishes L2 block on L1.
|
|
37
94
|
* @param block - L2 block to publish.
|
|
@@ -49,6 +106,7 @@ export class L1Publisher {
|
|
|
49
106
|
const processTxArgs = {
|
|
50
107
|
header: block.header.toBuffer(),
|
|
51
108
|
archive: block.archive.root.toBuffer(),
|
|
109
|
+
blockHash: block.header.hash().toBuffer(),
|
|
52
110
|
body: encodedBody,
|
|
53
111
|
attestations,
|
|
54
112
|
};
|
|
@@ -56,7 +114,7 @@ export class L1Publisher {
|
|
|
56
114
|
while (!this.interrupted) {
|
|
57
115
|
let txHash;
|
|
58
116
|
const timer = new Timer();
|
|
59
|
-
if (await this.
|
|
117
|
+
if (await this.checkIfTxsAreAvailable(block)) {
|
|
60
118
|
this.log.verbose(`Transaction effects of block ${block.number} already published.`, ctx);
|
|
61
119
|
txHash = await this.sendProcessTx(processTxArgs);
|
|
62
120
|
}
|
|
@@ -74,7 +132,7 @@ export class L1Publisher {
|
|
|
74
132
|
}
|
|
75
133
|
// Tx was mined successfully
|
|
76
134
|
if (receipt.status) {
|
|
77
|
-
const tx = await this.
|
|
135
|
+
const tx = await this.getTransactionStats(txHash);
|
|
78
136
|
const stats = {
|
|
79
137
|
...pick(receipt, 'gasPrice', 'gasUsed', 'transactionHash'),
|
|
80
138
|
...pick(tx, 'calldataGas', 'calldataSize'),
|
|
@@ -119,13 +177,13 @@ export class L1Publisher {
|
|
|
119
177
|
}
|
|
120
178
|
// Tx was mined successfully
|
|
121
179
|
if (receipt.status) {
|
|
122
|
-
const tx = await this.
|
|
180
|
+
const tx = await this.getTransactionStats(txHash);
|
|
123
181
|
const stats = {
|
|
124
182
|
...pick(receipt, 'gasPrice', 'gasUsed', 'transactionHash'),
|
|
125
183
|
...pick(tx, 'calldataGas', 'calldataSize'),
|
|
126
184
|
eventName: 'proof-published-to-l1',
|
|
127
185
|
};
|
|
128
|
-
this.log.info(`Published
|
|
186
|
+
this.log.info(`Published proof to L1 rollup contract`, { ...stats, ...ctx });
|
|
129
187
|
this.metrics.recordSubmitProof(timer.ms(), stats);
|
|
130
188
|
return true;
|
|
131
189
|
}
|
|
@@ -150,13 +208,17 @@ export class L1Publisher {
|
|
|
150
208
|
restart() {
|
|
151
209
|
this.interrupted = false;
|
|
152
210
|
}
|
|
211
|
+
async getCurrentArchive() {
|
|
212
|
+
const archive = await this.rollupContract.read.archive();
|
|
213
|
+
return Buffer.from(archive.replace('0x', ''), 'hex');
|
|
214
|
+
}
|
|
153
215
|
/**
|
|
154
216
|
* Verifies that the given value of last archive in a block header equals current archive of the rollup contract
|
|
155
217
|
* @param lastArchive - The last archive of the block we wish to publish.
|
|
156
218
|
* @returns Boolean indicating if the hashes are equal.
|
|
157
219
|
*/
|
|
158
220
|
async checkLastArchiveHash(lastArchive) {
|
|
159
|
-
const fromChain = await this.
|
|
221
|
+
const fromChain = await this.getCurrentArchive();
|
|
160
222
|
const areSame = lastArchive.equals(fromChain);
|
|
161
223
|
if (!areSame) {
|
|
162
224
|
this.log.debug(`Contract archive: ${fromChain.toString('hex')}`);
|
|
@@ -168,7 +230,17 @@ export class L1Publisher {
|
|
|
168
230
|
try {
|
|
169
231
|
const size = Object.values(submitProofArgs).reduce((acc, arg) => acc + arg.length, 0);
|
|
170
232
|
this.log.info(`SubmitProof size=${size} bytes`);
|
|
171
|
-
|
|
233
|
+
const { header, archive, proverId, aggregationObject, proof } = submitProofArgs;
|
|
234
|
+
const args = [
|
|
235
|
+
`0x${header.toString('hex')}`,
|
|
236
|
+
`0x${archive.toString('hex')}`,
|
|
237
|
+
`0x${proverId.toString('hex')}`,
|
|
238
|
+
`0x${aggregationObject.toString('hex')}`,
|
|
239
|
+
`0x${proof.toString('hex')}`,
|
|
240
|
+
];
|
|
241
|
+
return await this.rollupContract.write.submitBlockRootProof(args, {
|
|
242
|
+
account: this.account,
|
|
243
|
+
});
|
|
172
244
|
}
|
|
173
245
|
catch (err) {
|
|
174
246
|
this.log.error(`Rollup submit proof failed`, err);
|
|
@@ -179,7 +251,10 @@ export class L1Publisher {
|
|
|
179
251
|
while (!this.interrupted) {
|
|
180
252
|
try {
|
|
181
253
|
this.log.info(`TxEffects size=${encodedBody.length} bytes`);
|
|
182
|
-
|
|
254
|
+
const args = [`0x${encodedBody.toString('hex')}`];
|
|
255
|
+
return await this.availabilityOracleContract.write.publish(args, {
|
|
256
|
+
account: this.account,
|
|
257
|
+
});
|
|
183
258
|
}
|
|
184
259
|
catch (err) {
|
|
185
260
|
this.log.error(`TxEffects publish failed`, err);
|
|
@@ -190,7 +265,28 @@ export class L1Publisher {
|
|
|
190
265
|
async sendProcessTx(encodedData) {
|
|
191
266
|
while (!this.interrupted) {
|
|
192
267
|
try {
|
|
193
|
-
|
|
268
|
+
if (encodedData.attestations) {
|
|
269
|
+
const attestations = encodedData.attestations.map(attest => attest.toViemSignature());
|
|
270
|
+
const args = [
|
|
271
|
+
`0x${encodedData.header.toString('hex')}`,
|
|
272
|
+
`0x${encodedData.archive.toString('hex')}`,
|
|
273
|
+
`0x${encodedData.blockHash.toString('hex')}`,
|
|
274
|
+
attestations,
|
|
275
|
+
];
|
|
276
|
+
return await this.rollupContract.write.process(args, {
|
|
277
|
+
account: this.account,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
const args = [
|
|
282
|
+
`0x${encodedData.header.toString('hex')}`,
|
|
283
|
+
`0x${encodedData.archive.toString('hex')}`,
|
|
284
|
+
`0x${encodedData.blockHash.toString('hex')}`,
|
|
285
|
+
];
|
|
286
|
+
return await this.rollupContract.write.process(args, {
|
|
287
|
+
account: this.account,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
194
290
|
}
|
|
195
291
|
catch (err) {
|
|
196
292
|
this.log.error(`Rollup publish failed`, err);
|
|
@@ -201,7 +297,31 @@ export class L1Publisher {
|
|
|
201
297
|
async sendPublishAndProcessTx(encodedData) {
|
|
202
298
|
while (!this.interrupted) {
|
|
203
299
|
try {
|
|
204
|
-
|
|
300
|
+
// @note This is quite a sin, but I'm committing war crimes in this code already.
|
|
301
|
+
if (encodedData.attestations) {
|
|
302
|
+
const attestations = encodedData.attestations.map(attest => attest.toViemSignature());
|
|
303
|
+
const args = [
|
|
304
|
+
`0x${encodedData.header.toString('hex')}`,
|
|
305
|
+
`0x${encodedData.archive.toString('hex')}`,
|
|
306
|
+
`0x${encodedData.blockHash.toString('hex')}`,
|
|
307
|
+
attestations,
|
|
308
|
+
`0x${encodedData.body.toString('hex')}`,
|
|
309
|
+
];
|
|
310
|
+
return await this.rollupContract.write.publishAndProcess(args, {
|
|
311
|
+
account: this.account,
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
const args = [
|
|
316
|
+
`0x${encodedData.header.toString('hex')}`,
|
|
317
|
+
`0x${encodedData.archive.toString('hex')}`,
|
|
318
|
+
`0x${encodedData.blockHash.toString('hex')}`,
|
|
319
|
+
`0x${encodedData.body.toString('hex')}`,
|
|
320
|
+
];
|
|
321
|
+
return await this.rollupContract.write.publishAndProcess(args, {
|
|
322
|
+
account: this.account,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
205
325
|
}
|
|
206
326
|
catch (err) {
|
|
207
327
|
this.log.error(`Rollup publish failed`, err);
|
|
@@ -209,10 +329,31 @@ export class L1Publisher {
|
|
|
209
329
|
}
|
|
210
330
|
}
|
|
211
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* Returns a tx receipt if the tx has been mined.
|
|
334
|
+
* @param txHash - Hash of the tx to look for.
|
|
335
|
+
* @returns Undefined if the tx hasn't been mined yet, the receipt otherwise.
|
|
336
|
+
*/
|
|
212
337
|
async getTransactionReceipt(txHash) {
|
|
213
338
|
while (!this.interrupted) {
|
|
214
339
|
try {
|
|
215
|
-
|
|
340
|
+
const receipt = await this.publicClient.getTransactionReceipt({
|
|
341
|
+
hash: txHash,
|
|
342
|
+
});
|
|
343
|
+
if (receipt) {
|
|
344
|
+
if (receipt.transactionHash !== txHash) {
|
|
345
|
+
throw new Error(`Tx hash mismatch: ${receipt.transactionHash} !== ${txHash}`);
|
|
346
|
+
}
|
|
347
|
+
return {
|
|
348
|
+
status: receipt.status === 'success',
|
|
349
|
+
transactionHash: txHash,
|
|
350
|
+
gasUsed: receipt.gasUsed,
|
|
351
|
+
gasPrice: receipt.effectiveGasPrice,
|
|
352
|
+
logs: receipt.logs,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
this.log.debug(`Receipt not found for tx hash ${txHash}`);
|
|
356
|
+
return undefined;
|
|
216
357
|
}
|
|
217
358
|
catch (err) {
|
|
218
359
|
//this.log.error(`Error getting tx receipt`, err);
|
|
@@ -224,4 +365,12 @@ export class L1Publisher {
|
|
|
224
365
|
await this.interruptibleSleep.sleep(this.sleepTimeMs);
|
|
225
366
|
}
|
|
226
367
|
}
|
|
227
|
-
|
|
368
|
+
/**
|
|
369
|
+
* Returns cost of calldata usage in Ethereum.
|
|
370
|
+
* @param data - Calldata.
|
|
371
|
+
* @returns 4 for each zero byte, 16 for each nonzero.
|
|
372
|
+
*/
|
|
373
|
+
function getCalldataGasUsage(data) {
|
|
374
|
+
return data.filter(byte => byte === 0).length * 4 + data.filter(byte => byte !== 0).length * 16;
|
|
375
|
+
}
|
|
376
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibDEtcHVibGlzaGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3B1Ymxpc2hlci9sMS1wdWJsaXNoZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLHNCQUFzQixFQUFFLFVBQVUsRUFBMkIsTUFBTSxvQkFBb0IsQ0FBQztBQUNqRyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV0RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDaEQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLFNBQVMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBR3ZFLE9BQU8sSUFBSSxNQUFNLGFBQWEsQ0FBQztBQUMvQixPQUFPLEVBT0wsa0JBQWtCLEVBQ2xCLGtCQUFrQixFQUNsQixVQUFVLEVBQ1YsV0FBVyxFQUNYLFVBQVUsRUFDVixJQUFJLEdBQ0wsTUFBTSxNQUFNLENBQUM7QUFDZCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFJcEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFpRS9EOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLE9BQU8sV0FBVztJQWtCdEIsWUFBWSxNQUF3QyxFQUFFLE1BQXVCO1FBakJyRSx1QkFBa0IsR0FBRyxJQUFJLGtCQUFrQixFQUFFLENBQUM7UUFFOUMsZ0JBQVcsR0FBRyxLQUFLLENBQUM7UUFFcEIsUUFBRyxHQUFHLGlCQUFpQixDQUFDLDJCQUEyQixDQUFDLENBQUM7UUFjM0QsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLEVBQUUsd0JBQXdCLElB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QyxNQUFjO1FBQ3hDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDO2dCQUNILE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxxQkFBcUIsQ0FBQztvQkFDNUQsSUFBSSxFQUFFLE1BQWE7aUJBQ3BCLENBQUMsQ0FBQztnQkFFSCxJQUFJLE9BQU8sRUFBRSxDQUFDO29CQUNaLElBQUksT0FBTyxDQUFDLGVBQWUsS0FBSyxNQUFNLEVBQUUsQ0FBQzt3QkFDdkMsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsT0FBTyxDQUFDLGVBQWUsUUFBUSxNQUFNLEVBQUUsQ0FBQyxDQUFDO29CQUNoRixDQUFDO29CQUVELE9BQU87d0JBQ0wsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLEtBQUssU0FBUzt3QkFDcEMsZUFBZSxFQUFFLE1BQU07d0JBQ3ZCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTzt3QkFDeEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxpQkFBaUI7d0JBQ25DLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtxQkFDbkIsQ0FBQztnQkFDSixDQUFDO2dCQUVELElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGlDQUFpQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO2dCQUMxRCxPQUFPLFNBQVMsQ0FBQztZQUNuQixDQUFDO1lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztnQkFDYixrREFBa0Q7Z0JBQ2xELE1BQU0sSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDbEMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRVMsS0FBSyxDQUFDLGtCQUFrQjtRQUNoQyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3hELENBQUM7Q0FDRjtBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLG1CQUFtQixDQUFDLElBQWdCO0lBQzNDLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLEVBQUUsQ0FBQztBQUNsRyxDQUFDIn0=
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { type L1ToL2MessageSource, type L2Block, type L2BlockSource, type ProcessedTx, Tx, type TxValidator } from '@aztec/circuit-types';
|
|
2
|
-
import { type ProverClient } from '@aztec/circuit-types/interfaces';
|
|
1
|
+
import { type L1ToL2MessageSource, type L2Block, type L2BlockSource, type ProcessedTx, Signature, Tx, type TxValidator } from '@aztec/circuit-types';
|
|
3
2
|
import { AztecAddress, EthAddress } from '@aztec/circuits.js';
|
|
4
3
|
import { type P2P } from '@aztec/p2p';
|
|
5
4
|
import { type PublicProcessorFactory } from '@aztec/simulator';
|
|
6
5
|
import { type TelemetryClient, type Tracer } from '@aztec/telemetry-client';
|
|
6
|
+
import { type ValidatorClient } from '@aztec/validator-client';
|
|
7
7
|
import { type WorldStateSynchronizer } from '@aztec/world-state';
|
|
8
|
+
import { type BlockBuilderFactory } from '../block_builder/index.js';
|
|
8
9
|
import { type GlobalVariableBuilder } from '../global_variable_builder/global_builder.js';
|
|
9
|
-
import { type
|
|
10
|
+
import { type L1Publisher } from '../publisher/l1-publisher.js';
|
|
10
11
|
import { type TxValidatorFactory } from '../tx_validator/tx_validator_factory.js';
|
|
11
12
|
import { type SequencerConfig } from './config.js';
|
|
12
13
|
/**
|
|
@@ -20,14 +21,16 @@ import { type SequencerConfig } from './config.js';
|
|
|
20
21
|
*/
|
|
21
22
|
export declare class Sequencer {
|
|
22
23
|
private publisher;
|
|
24
|
+
private validatorClient;
|
|
23
25
|
private globalsBuilder;
|
|
24
26
|
private p2pClient;
|
|
25
27
|
private worldState;
|
|
26
|
-
private
|
|
28
|
+
private blockBuilderFactory;
|
|
27
29
|
private l2BlockSource;
|
|
28
30
|
private l1ToL2MessageSource;
|
|
29
31
|
private publicProcessorFactory;
|
|
30
32
|
private txValidatorFactory;
|
|
33
|
+
private config;
|
|
31
34
|
private log;
|
|
32
35
|
private runningPromise?;
|
|
33
36
|
private pollingIntervalMs;
|
|
@@ -42,9 +45,10 @@ export declare class Sequencer {
|
|
|
42
45
|
private allowedInSetup;
|
|
43
46
|
private allowedInTeardown;
|
|
44
47
|
private maxBlockSizeInBytes;
|
|
45
|
-
private skipSubmitProofs;
|
|
46
48
|
private metrics;
|
|
47
|
-
|
|
49
|
+
private isFlushing;
|
|
50
|
+
constructor(publisher: L1Publisher, validatorClient: ValidatorClient | undefined, // During migration the validator client can be inactive
|
|
51
|
+
globalsBuilder: GlobalVariableBuilder, p2pClient: P2P, worldState: WorldStateSynchronizer, blockBuilderFactory: BlockBuilderFactory, l2BlockSource: L2BlockSource, l1ToL2MessageSource: L1ToL2MessageSource, publicProcessorFactory: PublicProcessorFactory, txValidatorFactory: TxValidatorFactory, telemetry: TelemetryClient, config?: SequencerConfig, log?: import("@aztec/foundation/log").Logger);
|
|
48
52
|
get tracer(): Tracer;
|
|
49
53
|
/**
|
|
50
54
|
* Updates sequencer config.
|
|
@@ -78,12 +82,14 @@ export declare class Sequencer {
|
|
|
78
82
|
/** Whether to skip the check of min txs per block if more than maxSecondsBetweenBlocks has passed since the previous block. */
|
|
79
83
|
private skipMinTxsPerBlockCheck;
|
|
80
84
|
private buildBlockAndPublish;
|
|
81
|
-
|
|
85
|
+
/** Forces the sequencer to bypass all time and tx count checks for the next block and build anyway. */
|
|
86
|
+
flush(): void;
|
|
87
|
+
protected collectAttestations(block: L2Block): Promise<Signature[] | undefined>;
|
|
82
88
|
/**
|
|
83
89
|
* Publishes the L2Block to the rollup contract.
|
|
84
90
|
* @param block - The L2Block to be published.
|
|
85
91
|
*/
|
|
86
|
-
protected publishL2Block(block: L2Block, attestations?:
|
|
92
|
+
protected publishL2Block(block: L2Block, attestations?: Signature[]): Promise<void>;
|
|
87
93
|
protected takeValidTxs<T extends Tx | ProcessedTx>(txs: T[], validator: TxValidator<T>): Promise<T[]>;
|
|
88
94
|
protected takeTxsWithinMaxSize(txs: Tx[]): Tx[];
|
|
89
95
|
/**
|
|
@@ -110,17 +116,25 @@ export declare enum SequencerState {
|
|
|
110
116
|
* Creating a new L2 block. Includes processing public function calls and running rollup circuits. Will move to PUBLISHING_CONTRACT_DATA.
|
|
111
117
|
*/
|
|
112
118
|
CREATING_BLOCK = 2,
|
|
119
|
+
/**
|
|
120
|
+
* Publishing blocks to validator peers. Will move to WAITING_FOR_ATTESTATIONS.
|
|
121
|
+
*/
|
|
122
|
+
PUBLISHING_BLOCK_TO_PEERS = 3,
|
|
123
|
+
/**
|
|
124
|
+
* The block has been published to peers, and we are waiting for attestations. Will move to PUBLISHING_CONTRACT_DATA.
|
|
125
|
+
*/
|
|
126
|
+
WAITING_FOR_ATTESTATIONS = 4,
|
|
113
127
|
/**
|
|
114
128
|
* Sending the tx to L1 with encrypted logs and awaiting it to be mined. Will move back to PUBLISHING_BLOCK once finished.
|
|
115
129
|
*/
|
|
116
|
-
PUBLISHING_CONTRACT_DATA =
|
|
130
|
+
PUBLISHING_CONTRACT_DATA = 5,
|
|
117
131
|
/**
|
|
118
132
|
* Sending the tx to L1 with the L2 block data and awaiting it to be mined. Will move to IDLE.
|
|
119
133
|
*/
|
|
120
|
-
PUBLISHING_BLOCK =
|
|
134
|
+
PUBLISHING_BLOCK = 6,
|
|
121
135
|
/**
|
|
122
136
|
* Sequencer is stopped and not processing any txs from the pool.
|
|
123
137
|
*/
|
|
124
|
-
STOPPED =
|
|
138
|
+
STOPPED = 7
|
|
125
139
|
}
|
|
126
140
|
//# sourceMappingURL=sequencer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../../src/sequencer/sequencer.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../../src/sequencer/sequencer.ts"],"names":[],"mappings":"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"}
|