@aztec/sequencer-client 3.0.0-canary.a9708bd → 3.0.0-devnet.3
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/client/sequencer-client.d.ts +5 -4
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +17 -12
- package/dest/config.d.ts +2 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +10 -0
- package/dest/publisher/config.d.ts +2 -8
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +7 -16
- package/dest/publisher/index.d.ts +1 -1
- package/dest/publisher/index.d.ts.map +1 -1
- package/dest/publisher/index.js +1 -1
- package/dest/publisher/sequencer-publisher-factory.d.ts +6 -1
- package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-factory.js +8 -1
- package/dest/publisher/sequencer-publisher-metrics.d.ts +1 -1
- package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-metrics.js +1 -1
- package/dest/publisher/sequencer-publisher.d.ts +16 -22
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +72 -72
- package/dest/sequencer/block_builder.d.ts +2 -5
- package/dest/sequencer/block_builder.d.ts.map +1 -1
- package/dest/sequencer/block_builder.js +18 -6
- package/dest/sequencer/errors.d.ts +11 -0
- package/dest/sequencer/errors.d.ts.map +1 -0
- package/dest/sequencer/errors.js +15 -0
- package/dest/sequencer/metrics.d.ts +6 -18
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +22 -88
- package/dest/sequencer/sequencer.d.ts +8 -7
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +55 -33
- package/dest/sequencer/timetable.d.ts +1 -7
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +3 -10
- package/dest/sequencer/utils.d.ts +10 -24
- package/dest/sequencer/utils.d.ts.map +1 -1
- package/dest/sequencer/utils.js +9 -24
- package/dest/tx_validator/tx_validator_factory.d.ts.map +1 -1
- package/dest/tx_validator/tx_validator_factory.js +11 -8
- package/package.json +29 -29
- package/src/client/sequencer-client.ts +18 -9
- package/src/config.ts +11 -0
- package/src/publisher/config.ts +13 -22
- package/src/publisher/index.ts +1 -1
- package/src/publisher/sequencer-publisher-factory.ts +13 -2
- package/src/publisher/sequencer-publisher-metrics.ts +1 -1
- package/src/publisher/sequencer-publisher.ts +101 -98
- package/src/sequencer/block_builder.ts +20 -21
- package/src/sequencer/errors.ts +21 -0
- package/src/sequencer/metrics.ts +25 -101
- package/src/sequencer/sequencer.ts +85 -58
- package/src/sequencer/timetable.ts +3 -14
- package/src/sequencer/utils.ts +10 -24
- package/src/tx_validator/tx_validator_factory.ts +10 -5
|
@@ -1,25 +1,19 @@
|
|
|
1
|
-
import { Blob } from '@aztec/blob-lib';
|
|
1
|
+
import { Blob, getBlobsPerL1Block, getPrefixedEthBlobCommitments } from '@aztec/blob-lib';
|
|
2
2
|
import { createBlobSinkClient } from '@aztec/blob-sink/client';
|
|
3
3
|
import { FormattedViemError, MULTI_CALL_3_ADDRESS, Multicall3, RollupContract, formatViemError, tryExtractEvent } from '@aztec/ethereum';
|
|
4
4
|
import { sumBigint } from '@aztec/foundation/bigint';
|
|
5
5
|
import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
|
|
6
6
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
7
|
+
import { Signature } from '@aztec/foundation/eth-signature';
|
|
7
8
|
import { createLogger } from '@aztec/foundation/log';
|
|
8
9
|
import { bufferToHex } from '@aztec/foundation/string';
|
|
9
10
|
import { Timer } from '@aztec/foundation/timer';
|
|
10
11
|
import { EmpireBaseAbi, ErrorsAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
11
12
|
import { encodeSlashConsensusVotes } from '@aztec/slasher';
|
|
12
|
-
import { CommitteeAttestation } from '@aztec/stdlib/block';
|
|
13
|
-
import { ConsensusPayload, SignatureDomainSeparator, getHashedSignaturePayload } from '@aztec/stdlib/p2p';
|
|
13
|
+
import { CommitteeAttestation, CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
14
14
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
15
|
-
import pick from 'lodash.pick';
|
|
16
15
|
import { encodeFunctionData, toHex } from 'viem';
|
|
17
16
|
import { SequencerPublisherMetrics } from './sequencer-publisher-metrics.js';
|
|
18
|
-
export var SignalType = /*#__PURE__*/ function(SignalType) {
|
|
19
|
-
SignalType[SignalType["GOVERNANCE"] = 0] = "GOVERNANCE";
|
|
20
|
-
SignalType[SignalType["SLASHING"] = 1] = "SLASHING";
|
|
21
|
-
return SignalType;
|
|
22
|
-
}({});
|
|
23
17
|
export const Actions = [
|
|
24
18
|
'invalidate-by-invalid-attestation',
|
|
25
19
|
'invalidate-by-insufficient-attestations',
|
|
@@ -40,7 +34,7 @@ export class SequencerPublisher {
|
|
|
40
34
|
epochCache;
|
|
41
35
|
governanceLog;
|
|
42
36
|
slashingLog;
|
|
43
|
-
|
|
37
|
+
lastActions;
|
|
44
38
|
log;
|
|
45
39
|
ethereumSlotDuration;
|
|
46
40
|
blobSinkClient;
|
|
@@ -63,14 +57,12 @@ export class SequencerPublisher {
|
|
|
63
57
|
this.interrupted = false;
|
|
64
58
|
this.governanceLog = createLogger('sequencer:publisher:governance');
|
|
65
59
|
this.slashingLog = createLogger('sequencer:publisher:slashing');
|
|
66
|
-
this.
|
|
67
|
-
[0]: 0n,
|
|
68
|
-
[1]: 0n
|
|
69
|
-
};
|
|
70
|
-
this.log = createLogger('sequencer:publisher');
|
|
60
|
+
this.lastActions = {};
|
|
71
61
|
this.requests = [];
|
|
62
|
+
this.log = deps.log ?? createLogger('sequencer:publisher');
|
|
72
63
|
this.ethereumSlotDuration = BigInt(config.ethereumSlotDuration);
|
|
73
64
|
this.epochCache = deps.epochCache;
|
|
65
|
+
this.lastActions = deps.lastActions;
|
|
74
66
|
this.blobSinkClient = deps.blobSinkClient ?? createBlobSinkClient(config, {
|
|
75
67
|
logger: createLogger('sequencer:blob-sink:client')
|
|
76
68
|
});
|
|
@@ -148,7 +140,7 @@ export class SequencerPublisher {
|
|
|
148
140
|
const gasLimit = gasLimits.length > 0 ? sumBigint(gasLimits) : undefined; // sum
|
|
149
141
|
const txTimeoutAts = gasConfigs.map((g)=>g?.txTimeoutAt).filter((g)=>g !== undefined);
|
|
150
142
|
const txTimeoutAt = txTimeoutAts.length > 0 ? new Date(Math.min(...txTimeoutAts.map((g)=>g.getTime()))) : undefined; // earliest
|
|
151
|
-
const
|
|
143
|
+
const txConfig = {
|
|
152
144
|
gasLimit,
|
|
153
145
|
txTimeoutAt
|
|
154
146
|
};
|
|
@@ -157,9 +149,10 @@ export class SequencerPublisher {
|
|
|
157
149
|
validRequests.sort((a, b)=>compareActions(a.action, b.action));
|
|
158
150
|
try {
|
|
159
151
|
this.log.debug('Forwarding transactions', {
|
|
160
|
-
validRequests: validRequests.map((request)=>request.action)
|
|
152
|
+
validRequests: validRequests.map((request)=>request.action),
|
|
153
|
+
txConfig
|
|
161
154
|
});
|
|
162
|
-
const result = await Multicall3.forward(validRequests.map((request)=>request.request), this.l1TxUtils,
|
|
155
|
+
const result = await Multicall3.forward(validRequests.map((request)=>request.request), this.l1TxUtils, txConfig, blobConfig, this.rollupContract.address, this.log);
|
|
163
156
|
const { successfulActions = [], failedActions = [] } = this.callbackBundledTransactions(validRequests, result);
|
|
164
157
|
return {
|
|
165
158
|
result,
|
|
@@ -241,8 +234,9 @@ export class SequencerPublisher {
|
|
|
241
234
|
};
|
|
242
235
|
const args = [
|
|
243
236
|
header.toViem(),
|
|
244
|
-
|
|
237
|
+
CommitteeAttestationsAndSigners.empty().getPackedAttestations(),
|
|
245
238
|
[],
|
|
239
|
+
Signature.empty().toViemSignature(),
|
|
246
240
|
`0x${'0'.repeat(64)}`,
|
|
247
241
|
header.contentCommitment.blobsHash.toString(),
|
|
248
242
|
flags
|
|
@@ -278,13 +272,13 @@ export class SequencerPublisher {
|
|
|
278
272
|
return undefined;
|
|
279
273
|
}
|
|
280
274
|
const { reason, block } = validationResult;
|
|
281
|
-
const blockNumber = block.
|
|
275
|
+
const blockNumber = block.blockNumber;
|
|
282
276
|
const logData = {
|
|
283
|
-
...block
|
|
277
|
+
...block,
|
|
284
278
|
reason
|
|
285
279
|
};
|
|
286
280
|
const currentBlockNumber = await this.rollupContract.getBlockNumber();
|
|
287
|
-
if (currentBlockNumber < validationResult.block.
|
|
281
|
+
if (currentBlockNumber < validationResult.block.blockNumber) {
|
|
288
282
|
this.log.verbose(`Skipping block ${blockNumber} invalidation since it has already been removed from the pending chain`, {
|
|
289
283
|
currentBlockNumber,
|
|
290
284
|
...logData
|
|
@@ -292,7 +286,10 @@ export class SequencerPublisher {
|
|
|
292
286
|
return undefined;
|
|
293
287
|
}
|
|
294
288
|
const request = this.buildInvalidateBlockRequest(validationResult);
|
|
295
|
-
this.log.debug(`Simulating invalidate block ${blockNumber}`,
|
|
289
|
+
this.log.debug(`Simulating invalidate block ${blockNumber}`, {
|
|
290
|
+
...logData,
|
|
291
|
+
request
|
|
292
|
+
});
|
|
296
293
|
try {
|
|
297
294
|
const { gasUsed } = await this.l1TxUtils.simulate(request, undefined, undefined, ErrorsAbi);
|
|
298
295
|
this.log.verbose(`Simulation for invalidate block ${blockNumber} succeeded`, {
|
|
@@ -343,14 +340,15 @@ export class SequencerPublisher {
|
|
|
343
340
|
}
|
|
344
341
|
const { block, committee, reason } = validationResult;
|
|
345
342
|
const logData = {
|
|
346
|
-
...block
|
|
343
|
+
...block,
|
|
347
344
|
reason
|
|
348
345
|
};
|
|
349
|
-
this.log.debug(`Simulating invalidate block ${block.
|
|
346
|
+
this.log.debug(`Simulating invalidate block ${block.blockNumber}`, logData);
|
|
347
|
+
const attestationsAndSigners = new CommitteeAttestationsAndSigners(validationResult.attestations).getPackedAttestations();
|
|
350
348
|
if (reason === 'invalid-attestation') {
|
|
351
|
-
return this.rollupContract.buildInvalidateBadAttestationRequest(block.
|
|
349
|
+
return this.rollupContract.buildInvalidateBadAttestationRequest(block.blockNumber, attestationsAndSigners, committee, validationResult.invalidIndex);
|
|
352
350
|
} else if (reason === 'insufficient-attestations') {
|
|
353
|
-
return this.rollupContract.buildInvalidateInsufficientAttestationsRequest(block.
|
|
351
|
+
return this.rollupContract.buildInvalidateInsufficientAttestationsRequest(block.blockNumber, attestationsAndSigners, committee);
|
|
354
352
|
} else {
|
|
355
353
|
const _ = reason;
|
|
356
354
|
throw new Error(`Unknown reason for invalidation`);
|
|
@@ -364,45 +362,42 @@ export class SequencerPublisher {
|
|
|
364
362
|
* @param block - The block to propose
|
|
365
363
|
* @param attestationData - The block's attestation data
|
|
366
364
|
*
|
|
367
|
-
*/ async validateBlockForSubmission(block,
|
|
368
|
-
digest: Buffer.alloc(32),
|
|
369
|
-
attestations: []
|
|
370
|
-
}, options) {
|
|
365
|
+
*/ async validateBlockForSubmission(block, attestationsAndSigners, attestationsAndSignersSignature, options) {
|
|
371
366
|
const ts = BigInt((await this.l1TxUtils.getBlock()).timestamp + this.ethereumSlotDuration);
|
|
372
367
|
// If we have no attestations, we still need to provide the empty attestations
|
|
373
368
|
// so that the committee is recalculated correctly
|
|
374
|
-
const ignoreSignatures =
|
|
369
|
+
const ignoreSignatures = attestationsAndSigners.attestations.length === 0;
|
|
375
370
|
if (ignoreSignatures) {
|
|
376
371
|
const { committee } = await this.epochCache.getCommittee(block.header.globalVariables.slotNumber.toBigInt());
|
|
377
372
|
if (!committee) {
|
|
378
373
|
this.log.warn(`No committee found for slot ${block.header.globalVariables.slotNumber.toBigInt()}`);
|
|
379
374
|
throw new Error(`No committee found for slot ${block.header.globalVariables.slotNumber.toBigInt()}`);
|
|
380
375
|
}
|
|
381
|
-
|
|
376
|
+
attestationsAndSigners.attestations = committee.map((committeeMember)=>CommitteeAttestation.fromAddress(committeeMember));
|
|
382
377
|
}
|
|
383
|
-
const
|
|
384
|
-
const
|
|
385
|
-
const
|
|
386
|
-
const signers = attestationData.attestations.filter((attest)=>!attest.signature.isEmpty()).map((attest)=>attest.address.toString());
|
|
378
|
+
const blobFields = block.getCheckpointBlobFields();
|
|
379
|
+
const blobs = getBlobsPerL1Block(blobFields);
|
|
380
|
+
const blobInput = getPrefixedEthBlobCommitments(blobs);
|
|
387
381
|
const args = [
|
|
388
382
|
{
|
|
389
|
-
header: block.
|
|
383
|
+
header: block.getCheckpointHeader().toViem(),
|
|
390
384
|
archive: toHex(block.archive.root.toBuffer()),
|
|
391
385
|
stateReference: block.header.state.toViem(),
|
|
392
|
-
txHashes: block.body.txEffects.map((txEffect)=>txEffect.txHash.toString()),
|
|
393
386
|
oracleInput: {
|
|
394
387
|
feeAssetPriceModifier: 0n
|
|
395
388
|
}
|
|
396
389
|
},
|
|
397
|
-
|
|
398
|
-
|
|
390
|
+
attestationsAndSigners.getPackedAttestations(),
|
|
391
|
+
attestationsAndSigners.getSigners().map((signer)=>signer.toString()),
|
|
392
|
+
attestationsAndSignersSignature.toViemSignature(),
|
|
399
393
|
blobInput
|
|
400
394
|
];
|
|
401
395
|
await this.simulateProposeTx(args, ts, options);
|
|
402
396
|
return ts;
|
|
403
397
|
}
|
|
404
398
|
async enqueueCastSignalHelper(slotNumber, timestamp, signalType, payload, base, signerAddress, signer) {
|
|
405
|
-
if (this.
|
|
399
|
+
if (this.lastActions[signalType] && this.lastActions[signalType] === slotNumber) {
|
|
400
|
+
this.log.debug(`Skipping duplicate vote cast signal ${signalType} for slot ${slotNumber}`);
|
|
406
401
|
return false;
|
|
407
402
|
}
|
|
408
403
|
if (payload.equals(EthAddress.ZERO)) {
|
|
@@ -417,9 +412,9 @@ export class SequencerPublisher {
|
|
|
417
412
|
if (roundInfo.lastSignalSlot >= slotNumber) {
|
|
418
413
|
return false;
|
|
419
414
|
}
|
|
420
|
-
const cachedLastVote = this.
|
|
421
|
-
this.
|
|
422
|
-
const action = signalType
|
|
415
|
+
const cachedLastVote = this.lastActions[signalType];
|
|
416
|
+
this.lastActions[signalType] = slotNumber;
|
|
417
|
+
const action = signalType;
|
|
423
418
|
const request = await base.createSignalRequestWithSignature(payload.toString(), slotNumber, this.config.l1ChainId, signerAddress.toString(), signer);
|
|
424
419
|
this.log.debug(`Created ${action} request with signature`, {
|
|
425
420
|
request,
|
|
@@ -456,7 +451,7 @@ export class SequencerPublisher {
|
|
|
456
451
|
};
|
|
457
452
|
if (!success) {
|
|
458
453
|
this.log.error(`Signaling in [${action}] for ${payload} at slot ${slotNumber} in round ${round} failed`, logData);
|
|
459
|
-
this.
|
|
454
|
+
this.lastActions[signalType] = cachedLastVote;
|
|
460
455
|
return false;
|
|
461
456
|
} else {
|
|
462
457
|
this.log.info(`Signaling in [${action}] for ${payload} at slot ${slotNumber} in round ${round} succeeded`, logData);
|
|
@@ -472,7 +467,7 @@ export class SequencerPublisher {
|
|
|
472
467
|
* @param timestamp - The timestamp of the slot to cast a signal for.
|
|
473
468
|
* @returns True if the signal was successfully enqueued, false otherwise.
|
|
474
469
|
*/ enqueueGovernanceCastSignal(governancePayload, slotNumber, timestamp, signerAddress, signer) {
|
|
475
|
-
return this.enqueueCastSignalHelper(slotNumber, timestamp,
|
|
470
|
+
return this.enqueueCastSignalHelper(slotNumber, timestamp, 'governance-signal', governancePayload, this.govProposerContract, signerAddress, signer);
|
|
476
471
|
}
|
|
477
472
|
/** Enqueues all slashing actions as returned by the slasher client. */ async enqueueSlashingActions(actions, slotNumber, timestamp, signerAddress, signer) {
|
|
478
473
|
if (actions.length === 0) {
|
|
@@ -490,7 +485,7 @@ export class SequencerPublisher {
|
|
|
490
485
|
this.log.debug(`Enqueuing slashing vote for payload ${action.payload} at slot ${slotNumber}`, {
|
|
491
486
|
signerAddress
|
|
492
487
|
});
|
|
493
|
-
await this.enqueueCastSignalHelper(slotNumber, timestamp,
|
|
488
|
+
await this.enqueueCastSignalHelper(slotNumber, timestamp, 'empire-slashing-signal', action.payload, this.slashingProposerContract, signerAddress, signer);
|
|
494
489
|
break;
|
|
495
490
|
}
|
|
496
491
|
case 'create-empire-payload':
|
|
@@ -566,19 +561,18 @@ export class SequencerPublisher {
|
|
|
566
561
|
*
|
|
567
562
|
* @param block - L2 block to propose.
|
|
568
563
|
* @returns True if the tx has been enqueued, throws otherwise. See #9315
|
|
569
|
-
*/ async enqueueProposeL2Block(block,
|
|
570
|
-
const
|
|
571
|
-
const
|
|
572
|
-
const
|
|
573
|
-
const blobs = await Blob.getBlobsPerBlock(block.body.toBlobFields());
|
|
564
|
+
*/ async enqueueProposeL2Block(block, attestationsAndSigners, attestationsAndSignersSignature, opts = {}) {
|
|
565
|
+
const checkpointHeader = block.getCheckpointHeader();
|
|
566
|
+
const blobFields = block.getCheckpointBlobFields();
|
|
567
|
+
const blobs = getBlobsPerL1Block(blobFields);
|
|
574
568
|
const proposeTxArgs = {
|
|
575
|
-
header:
|
|
569
|
+
header: checkpointHeader,
|
|
576
570
|
archive: block.archive.root.toBuffer(),
|
|
577
571
|
stateReference: block.header.state,
|
|
578
572
|
body: block.body.toBuffer(),
|
|
579
573
|
blobs,
|
|
580
|
-
|
|
581
|
-
|
|
574
|
+
attestationsAndSigners,
|
|
575
|
+
attestationsAndSignersSignature
|
|
582
576
|
};
|
|
583
577
|
let ts;
|
|
584
578
|
try {
|
|
@@ -586,12 +580,8 @@ export class SequencerPublisher {
|
|
|
586
580
|
// This means that we can avoid the simulation issues in later checks.
|
|
587
581
|
// By simulation issue, I mean the fact that the block.timestamp is equal to the last block, not the next, which
|
|
588
582
|
// make time consistency checks break.
|
|
589
|
-
const attestationData = {
|
|
590
|
-
digest: digest.toBuffer(),
|
|
591
|
-
attestations: attestations ?? []
|
|
592
|
-
};
|
|
593
583
|
// TODO(palla): Check whether we're validating twice, once here and once within addProposeTx, since we call simulateProposeTx in both places.
|
|
594
|
-
ts = await this.validateBlockForSubmission(block,
|
|
584
|
+
ts = await this.validateBlockForSubmission(block, attestationsAndSigners, attestationsAndSignersSignature, opts);
|
|
595
585
|
} catch (err) {
|
|
596
586
|
this.log.error(`Block validation failed. ${err instanceof Error ? err.message : 'No error message'}`, err, {
|
|
597
587
|
...block.getStats(),
|
|
@@ -613,8 +603,10 @@ export class SequencerPublisher {
|
|
|
613
603
|
}
|
|
614
604
|
// We issued the simulation against the rollup contract, so we need to account for the overhead of the multicall3
|
|
615
605
|
const gasLimit = this.l1TxUtils.bumpGasLimit(BigInt(Math.ceil(Number(request.gasUsed) * 64 / 63)));
|
|
606
|
+
const { gasUsed, blockNumber } = request;
|
|
616
607
|
const logData = {
|
|
617
|
-
|
|
608
|
+
gasUsed,
|
|
609
|
+
blockNumber,
|
|
618
610
|
gasLimit,
|
|
619
611
|
opts
|
|
620
612
|
};
|
|
@@ -650,8 +642,14 @@ export class SequencerPublisher {
|
|
|
650
642
|
timestamp,
|
|
651
643
|
gasLimit: undefined
|
|
652
644
|
};
|
|
645
|
+
if (this.lastActions[action] && this.lastActions[action] === slotNumber) {
|
|
646
|
+
this.log.debug(`Skipping duplicate action ${action} for slot ${slotNumber}`);
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
const cachedLastActionSlot = this.lastActions[action];
|
|
650
|
+
this.lastActions[action] = slotNumber;
|
|
651
|
+
this.log.debug(`Simulating ${action} for slot ${slotNumber}`, logData);
|
|
653
652
|
let gasUsed;
|
|
654
|
-
this.log.debug(`Simulating ${action}`, logData);
|
|
655
653
|
try {
|
|
656
654
|
({ gasUsed } = await this.l1TxUtils.simulate(request, {
|
|
657
655
|
time: timestamp
|
|
@@ -684,6 +682,7 @@ export class SequencerPublisher {
|
|
|
684
682
|
...result,
|
|
685
683
|
...logData
|
|
686
684
|
});
|
|
685
|
+
this.lastActions[action] = cachedLastActionSlot;
|
|
687
686
|
} else {
|
|
688
687
|
this.log.info(`Action ${action} at ${slotNumber} succeeded`, {
|
|
689
688
|
...result,
|
|
@@ -710,7 +709,7 @@ export class SequencerPublisher {
|
|
|
710
709
|
}
|
|
711
710
|
async prepareProposeTx(encodedData, timestamp, options) {
|
|
712
711
|
const kzg = Blob.getViemKzgInstance();
|
|
713
|
-
const blobInput =
|
|
712
|
+
const blobInput = getPrefixedEthBlobCommitments(encodedData.blobs);
|
|
714
713
|
this.log.debug('Validating blob input', {
|
|
715
714
|
blobInput
|
|
716
715
|
});
|
|
@@ -733,9 +732,7 @@ export class SequencerPublisher {
|
|
|
733
732
|
});
|
|
734
733
|
throw new Error('Failed to validate blobs');
|
|
735
734
|
});
|
|
736
|
-
const
|
|
737
|
-
const txHashes = encodedData.txHashes ? encodedData.txHashes.map((txHash)=>txHash.toString()) : [];
|
|
738
|
-
const signers = encodedData.attestations?.filter((attest)=>!attest.signature.isEmpty()).map((attest)=>attest.address.toString());
|
|
735
|
+
const signers = encodedData.attestationsAndSigners.getSigners().map((signer)=>signer.toString());
|
|
739
736
|
const args = [
|
|
740
737
|
{
|
|
741
738
|
header: encodedData.header.toViem(),
|
|
@@ -744,11 +741,11 @@ export class SequencerPublisher {
|
|
|
744
741
|
oracleInput: {
|
|
745
742
|
// We are currently not modifying these. See #9963
|
|
746
743
|
feeAssetPriceModifier: 0n
|
|
747
|
-
}
|
|
748
|
-
txHashes
|
|
744
|
+
}
|
|
749
745
|
},
|
|
750
|
-
|
|
751
|
-
signers
|
|
746
|
+
encodedData.attestationsAndSigners.getPackedAttestations(),
|
|
747
|
+
signers,
|
|
748
|
+
encodedData.attestationsAndSignersSignature.toViemSignature(),
|
|
752
749
|
blobInput
|
|
753
750
|
];
|
|
754
751
|
const { rollupData, simulationResult } = await this.simulateProposeTx(args, timestamp, options);
|
|
@@ -840,13 +837,16 @@ export class SequencerPublisher {
|
|
|
840
837
|
if (success) {
|
|
841
838
|
const endBlock = receipt.blockNumber;
|
|
842
839
|
const inclusionBlocks = Number(endBlock - startBlock);
|
|
840
|
+
const { calldataGas, calldataSize, sender } = stats;
|
|
843
841
|
const publishStats = {
|
|
844
842
|
gasPrice: receipt.effectiveGasPrice,
|
|
845
843
|
gasUsed: receipt.gasUsed,
|
|
846
844
|
blobGasUsed: receipt.blobGasUsed ?? 0n,
|
|
847
845
|
blobDataGas: receipt.blobGasPrice ?? 0n,
|
|
848
846
|
transactionHash: receipt.transactionHash,
|
|
849
|
-
|
|
847
|
+
calldataGas,
|
|
848
|
+
calldataSize,
|
|
849
|
+
sender,
|
|
850
850
|
...block.getStats(),
|
|
851
851
|
eventName: 'rollup-published-to-l1',
|
|
852
852
|
blobCount: encodedData.blobs.length,
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import type { Fr } from '@aztec/foundation/fields';
|
|
2
2
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
3
3
|
import { PublicProcessor } from '@aztec/simulator/server';
|
|
4
|
-
import type { ChainConfig, SequencerConfig } from '@aztec/stdlib/config';
|
|
5
4
|
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
6
5
|
import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
7
|
-
import type { BuildBlockResult, IFullNodeBlockBuilder, MerkleTreeWriteOperations, PublicProcessorLimits, PublicProcessorValidator, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
6
|
+
import type { BuildBlockResult, FullNodeBlockBuilderConfig, IFullNodeBlockBuilder, MerkleTreeWriteOperations, PublicProcessorLimits, PublicProcessorValidator, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
8
7
|
import { GlobalVariables, Tx } from '@aztec/stdlib/tx';
|
|
9
8
|
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
10
9
|
export declare function buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, l1ToL2Messages: Fr[], newGlobalVariables: GlobalVariables, opts: PublicProcessorLimits | undefined, worldStateFork: MerkleTreeWriteOperations, processor: PublicProcessor, validator: PublicProcessorValidator, l1Constants: Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration'>, dateProvider: DateProvider, telemetryClient?: TelemetryClient): Promise<BuildBlockResult>;
|
|
11
|
-
type FullNodeBlockBuilderConfig = Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration'> & Pick<ChainConfig, 'l1ChainId' | 'rollupVersion'> & Pick<SequencerConfig, 'txPublicSetupAllowList' | 'fakeProcessingDelayPerTxMs'>;
|
|
12
10
|
export declare class FullNodeBlockBuilder implements IFullNodeBlockBuilder {
|
|
13
11
|
private config;
|
|
14
12
|
private worldState;
|
|
@@ -17,7 +15,7 @@ export declare class FullNodeBlockBuilder implements IFullNodeBlockBuilder {
|
|
|
17
15
|
private telemetryClient;
|
|
18
16
|
constructor(config: FullNodeBlockBuilderConfig, worldState: WorldStateSynchronizer, contractDataSource: ContractDataSource, dateProvider: DateProvider, telemetryClient?: TelemetryClient);
|
|
19
17
|
getConfig(): FullNodeBlockBuilderConfig;
|
|
20
|
-
updateConfig(config: FullNodeBlockBuilderConfig): void;
|
|
18
|
+
updateConfig(config: Partial<FullNodeBlockBuilderConfig>): void;
|
|
21
19
|
makeBlockBuilderDeps(globalVariables: GlobalVariables, fork: MerkleTreeWriteOperations): Promise<{
|
|
22
20
|
processor: PublicProcessor;
|
|
23
21
|
validator: PublicProcessorValidator;
|
|
@@ -26,5 +24,4 @@ export declare class FullNodeBlockBuilder implements IFullNodeBlockBuilder {
|
|
|
26
24
|
buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, l1ToL2Messages: Fr[], globalVariables: GlobalVariables, opts: PublicProcessorLimits, suppliedFork?: MerkleTreeWriteOperations): Promise<BuildBlockResult>;
|
|
27
25
|
getFork(blockNumber: number): Promise<MerkleTreeWriteOperations>;
|
|
28
26
|
}
|
|
29
|
-
export {};
|
|
30
27
|
//# sourceMappingURL=block_builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block_builder.d.ts","sourceRoot":"","sources":["../../src/sequencer/block_builder.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAInD,OAAO,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"block_builder.d.ts","sourceRoot":"","sources":["../../src/sequencer/block_builder.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAInD,OAAO,EAAE,YAAY,EAAkB,MAAM,yBAAyB,CAAC;AAGvE,OAAO,EAGL,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,KAAK,iBAAiB,EAAuB,MAAM,6BAA6B,CAAC;AAE1F,OAAO,KAAK,EACV,gBAAgB,EAChB,0BAA0B,EAC1B,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAMnF,wBAAsB,UAAU,CAC9B,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,EAAE,CAAC,EAC5C,cAAc,EAAE,EAAE,EAAE,EACpB,kBAAkB,EAAE,eAAe,EACnC,IAAI,EAAE,qBAAqB,YAAK,EAChC,cAAc,EAAE,yBAAyB,EACzC,SAAS,EAAE,eAAe,EAC1B,SAAS,EAAE,wBAAwB,EACnC,WAAW,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,GAAG,cAAc,CAAC,EACtE,YAAY,EAAE,YAAY,EAC1B,eAAe,GAAE,eAAsC,GACtD,OAAO,CAAC,gBAAgB,CAAC,CA4C3B;AAWD,qBAAa,oBAAqB,YAAW,qBAAqB;IAE9D,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,eAAe;gBAJf,MAAM,EAAE,0BAA0B,EAClC,UAAU,EAAE,sBAAsB,EAClC,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,EAC1B,eAAe,GAAE,eAAsC;IAG1D,SAAS,IAAI,0BAA0B;IAIvC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,0BAA0B,CAAC;IAIlD,oBAAoB,CAAC,eAAe,EAAE,eAAe,EAAE,IAAI,EAAE,yBAAyB;;;;YAyCrF,mBAAmB;IAU3B,UAAU,CACd,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,EAAE,CAAC,EAC5C,cAAc,EAAE,EAAE,EAAE,EACpB,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,qBAAqB,EAC3B,YAAY,CAAC,EAAE,yBAAyB,GACvC,OAAO,CAAC,gBAAgB,CAAC;IAwC5B,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;CAGjE"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { MerkleTreeId
|
|
2
|
-
import { pick } from '@aztec/foundation/collection';
|
|
1
|
+
import { MerkleTreeId } from '@aztec/aztec.js/trees';
|
|
2
|
+
import { merge, pick } from '@aztec/foundation/collection';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { retryUntil } from '@aztec/foundation/retry';
|
|
5
5
|
import { bufferToHex } from '@aztec/foundation/string';
|
|
6
|
-
import { Timer } from '@aztec/foundation/timer';
|
|
6
|
+
import { Timer, elapsed } from '@aztec/foundation/timer';
|
|
7
7
|
import { getDefaultAllowedSetupFunctions } from '@aztec/p2p/msg_validators';
|
|
8
8
|
import { LightweightBlockFactory } from '@aztec/prover-client/block-factory';
|
|
9
9
|
import { GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, TelemetryPublicTxSimulator } from '@aztec/simulator/server';
|
|
@@ -50,6 +50,14 @@ export async function buildBlock(pendingTxs, l1ToL2Messages, newGlobalVariables,
|
|
|
50
50
|
log.trace('Built block', res.block.header);
|
|
51
51
|
return res;
|
|
52
52
|
}
|
|
53
|
+
const FullNodeBlockBuilderConfigKeys = [
|
|
54
|
+
'l1GenesisTime',
|
|
55
|
+
'slotDuration',
|
|
56
|
+
'l1ChainId',
|
|
57
|
+
'rollupVersion',
|
|
58
|
+
'txPublicSetupAllowList',
|
|
59
|
+
'fakeProcessingDelayPerTxMs'
|
|
60
|
+
];
|
|
53
61
|
export class FullNodeBlockBuilder {
|
|
54
62
|
config;
|
|
55
63
|
worldState;
|
|
@@ -64,16 +72,20 @@ export class FullNodeBlockBuilder {
|
|
|
64
72
|
this.telemetryClient = telemetryClient;
|
|
65
73
|
}
|
|
66
74
|
getConfig() {
|
|
67
|
-
return pick(this.config,
|
|
75
|
+
return pick(this.config, ...FullNodeBlockBuilderConfigKeys);
|
|
68
76
|
}
|
|
69
77
|
updateConfig(config) {
|
|
70
|
-
this.config = config;
|
|
78
|
+
this.config = merge(this.config, pick(config, ...FullNodeBlockBuilderConfigKeys));
|
|
71
79
|
}
|
|
72
80
|
async makeBlockBuilderDeps(globalVariables, fork) {
|
|
73
81
|
const txPublicSetupAllowList = this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
|
|
74
82
|
const contractsDB = new PublicContractsDB(this.contractDataSource);
|
|
75
83
|
const guardedFork = new GuardedMerkleTreeOperations(fork);
|
|
76
|
-
const publicTxSimulator = new TelemetryPublicTxSimulator(guardedFork, contractsDB, globalVariables,
|
|
84
|
+
const publicTxSimulator = new TelemetryPublicTxSimulator(guardedFork, contractsDB, globalVariables, this.telemetryClient, {
|
|
85
|
+
doMerkleOperations: true,
|
|
86
|
+
skipFeeEnforcement: true,
|
|
87
|
+
clientInitiatedSimulation: false
|
|
88
|
+
});
|
|
77
89
|
const processor = new PublicProcessor(globalVariables, guardedFork, contractsDB, publicTxSimulator, this.dateProvider, this.telemetryClient, undefined, this.config);
|
|
78
90
|
const validator = createValidatorForBlockBuilding(fork, this.contractDataSource, globalVariables, txPublicSetupAllowList);
|
|
79
91
|
return {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SequencerState } from './utils.js';
|
|
2
|
+
export declare class SequencerTooSlowError extends Error {
|
|
3
|
+
readonly proposedState: SequencerState;
|
|
4
|
+
readonly maxAllowedTime: number;
|
|
5
|
+
readonly currentTime: number;
|
|
6
|
+
constructor(proposedState: SequencerState, maxAllowedTime: number, currentTime: number);
|
|
7
|
+
}
|
|
8
|
+
export declare class SequencerInterruptedError extends Error {
|
|
9
|
+
constructor();
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/sequencer/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,qBAAa,qBAAsB,SAAQ,KAAK;aAE5B,aAAa,EAAE,cAAc;aAC7B,cAAc,EAAE,MAAM;aACtB,WAAW,EAAE,MAAM;gBAFnB,aAAa,EAAE,cAAc,EAC7B,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM;CAOtC;AAED,qBAAa,yBAA0B,SAAQ,KAAK;;CAKnD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class SequencerTooSlowError extends Error {
|
|
2
|
+
proposedState;
|
|
3
|
+
maxAllowedTime;
|
|
4
|
+
currentTime;
|
|
5
|
+
constructor(proposedState, maxAllowedTime, currentTime){
|
|
6
|
+
super(`Too far into slot for ${proposedState} (time into slot ${currentTime}s greater than ${maxAllowedTime}s allowance)`), this.proposedState = proposedState, this.maxAllowedTime = maxAllowedTime, this.currentTime = currentTime;
|
|
7
|
+
this.name = 'SequencerTooSlowError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export class SequencerInterruptedError extends Error {
|
|
11
|
+
constructor(){
|
|
12
|
+
super(`Sequencer was interrupted`);
|
|
13
|
+
this.name = 'SequencerInterruptedError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { EthAddress } from '@aztec/aztec.js/addresses';
|
|
2
2
|
import type { RollupContract } from '@aztec/ethereum';
|
|
3
3
|
import { type TelemetryClient, type Tracer } from '@aztec/telemetry-client';
|
|
4
|
-
import { type
|
|
4
|
+
import { type Hex } from 'viem';
|
|
5
|
+
import type { SequencerState } from './utils.js';
|
|
5
6
|
export declare class SequencerMetrics {
|
|
6
|
-
private coinbase;
|
|
7
7
|
private rollup;
|
|
8
8
|
readonly tracer: Tracer;
|
|
9
9
|
private meter;
|
|
@@ -11,9 +11,6 @@ export declare class SequencerMetrics {
|
|
|
11
11
|
private blockBuildDuration;
|
|
12
12
|
private blockBuildManaPerSecond;
|
|
13
13
|
private stateTransitionBufferDuration;
|
|
14
|
-
private currentBlockNumber;
|
|
15
|
-
private currentBlockSize;
|
|
16
|
-
private blockBuilderInsertions;
|
|
17
14
|
private timeToCollectAttestations;
|
|
18
15
|
private allowanceToCollectAttestations;
|
|
19
16
|
private requiredAttestions;
|
|
@@ -21,23 +18,14 @@ export declare class SequencerMetrics {
|
|
|
21
18
|
private rewards;
|
|
22
19
|
private slots;
|
|
23
20
|
private filledSlots;
|
|
24
|
-
private missedSlots;
|
|
25
21
|
private lastSeenSlot?;
|
|
26
|
-
constructor(client: TelemetryClient,
|
|
27
|
-
setCoinbase(coinbase: EthAddress): void;
|
|
28
|
-
start(): void;
|
|
29
|
-
stop(): void;
|
|
30
|
-
private observe;
|
|
22
|
+
constructor(client: TelemetryClient, rollup: RollupContract, name?: string);
|
|
31
23
|
recordRequiredAttestations(requiredAttestationsCount: number, allowanceMs: number): void;
|
|
32
24
|
recordCollectedAttestations(count: number, durationMs: number): void;
|
|
33
|
-
recordBlockBuilderTreeInsertions(timeUs: number): void;
|
|
34
|
-
recordCancelledBlock(): void;
|
|
35
25
|
recordBuiltBlock(buildDurationMs: number, totalMana: number): void;
|
|
36
26
|
recordFailedBlock(): void;
|
|
37
|
-
recordNewBlock(blockNumber: number, txCount: number): void;
|
|
38
27
|
recordStateTransitionBufferMs(durationMs: number, state: SequencerState): void;
|
|
39
|
-
|
|
40
|
-
incFilledSlot(proposer: string): void
|
|
41
|
-
private setCurrentBlock;
|
|
28
|
+
incOpenSlot(slot: bigint, proposer: string): void;
|
|
29
|
+
incFilledSlot(proposer: string, coinbase: Hex | EthAddress | undefined): Promise<void>;
|
|
42
30
|
}
|
|
43
31
|
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/sequencer/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/sequencer/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,MAAM,EAGZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,KAAK,GAAG,EAAe,MAAM,MAAM,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,qBAAa,gBAAgB;IAwBzB,OAAO,CAAC,MAAM;IAvBhB,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,KAAK,CAAQ;IAErB,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,kBAAkB,CAAY;IACtC,OAAO,CAAC,uBAAuB,CAAQ;IACvC,OAAO,CAAC,6BAA6B,CAAY;IAGjD,OAAO,CAAC,yBAAyB,CAAQ;IACzC,OAAO,CAAC,8BAA8B,CAAQ;IAC9C,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,mBAAmB,CAAQ;IAEnC,OAAO,CAAC,OAAO,CAAQ;IAEvB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,WAAW,CAAgB;IAEnC,OAAO,CAAC,YAAY,CAAC,CAAS;gBAG5B,MAAM,EAAE,eAAe,EACf,MAAM,EAAE,cAAc,EAC9B,IAAI,SAAc;IAkFb,0BAA0B,CAAC,yBAAyB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IASjF,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAKpE,gBAAgB,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAQ3D,iBAAiB;IAMjB,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc;IAMvE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAapC,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;CAkB7F"}
|