@aztec/sequencer-client 2.0.3-rc.9 → 2.1.0-rc.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/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +5 -4
- package/dest/config.d.ts +2 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +2 -0
- package/dest/publisher/config.d.ts +5 -3
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +13 -5
- 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 +5 -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.d.ts +13 -15
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +58 -55
- package/dest/sequencer/metrics.d.ts +5 -17
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +22 -88
- package/dest/sequencer/sequencer.d.ts +4 -3
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +16 -17
- package/package.json +28 -28
- package/src/client/sequencer-client.ts +4 -2
- package/src/config.ts +3 -0
- package/src/publisher/config.ts +23 -5
- package/src/publisher/index.ts +1 -1
- package/src/publisher/sequencer-publisher-factory.ts +12 -2
- package/src/publisher/sequencer-publisher.ts +77 -69
- package/src/sequencer/metrics.ts +24 -100
- package/src/sequencer/sequencer.ts +42 -38
|
@@ -4,22 +4,16 @@ import { FormattedViemError, MULTI_CALL_3_ADDRESS, Multicall3, RollupContract, f
|
|
|
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',
|
|
@@ -35,12 +29,13 @@ export const Actions = [
|
|
|
35
29
|
export const compareActions = (a, b)=>Actions.indexOf(a) - Actions.indexOf(b);
|
|
36
30
|
export class SequencerPublisher {
|
|
37
31
|
config;
|
|
32
|
+
enabled;
|
|
38
33
|
interrupted;
|
|
39
34
|
metrics;
|
|
40
35
|
epochCache;
|
|
41
36
|
governanceLog;
|
|
42
37
|
slashingLog;
|
|
43
|
-
|
|
38
|
+
lastActions;
|
|
44
39
|
log;
|
|
45
40
|
ethereumSlotDuration;
|
|
46
41
|
blobSinkClient;
|
|
@@ -63,14 +58,13 @@ export class SequencerPublisher {
|
|
|
63
58
|
this.interrupted = false;
|
|
64
59
|
this.governanceLog = createLogger('sequencer:publisher:governance');
|
|
65
60
|
this.slashingLog = createLogger('sequencer:publisher:slashing');
|
|
66
|
-
this.
|
|
67
|
-
[0]: 0n,
|
|
68
|
-
[1]: 0n
|
|
69
|
-
};
|
|
70
|
-
this.log = createLogger('sequencer:publisher');
|
|
61
|
+
this.lastActions = {};
|
|
71
62
|
this.requests = [];
|
|
63
|
+
this.enabled = config.publisherEnabled ?? true;
|
|
64
|
+
this.log = deps.log ?? createLogger('sequencer:publisher');
|
|
72
65
|
this.ethereumSlotDuration = BigInt(config.ethereumSlotDuration);
|
|
73
66
|
this.epochCache = deps.epochCache;
|
|
67
|
+
this.lastActions = deps.lastActions;
|
|
74
68
|
this.blobSinkClient = deps.blobSinkClient ?? createBlobSinkClient(config, {
|
|
75
69
|
logger: createLogger('sequencer:blob-sink:client')
|
|
76
70
|
});
|
|
@@ -106,6 +100,13 @@ export class SequencerPublisher {
|
|
|
106
100
|
* - a receipt and errorMsg if it failed on L1
|
|
107
101
|
* - undefined if no valid requests are found OR the tx failed to send.
|
|
108
102
|
*/ async sendRequests() {
|
|
103
|
+
if (!this.enabled) {
|
|
104
|
+
this.log.warn(`Sending L1 txs is disabled`, {
|
|
105
|
+
requestsDiscarded: this.requests.map((r)=>r.action)
|
|
106
|
+
});
|
|
107
|
+
this.requests = [];
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
109
110
|
const requestsToProcess = [
|
|
110
111
|
...this.requests
|
|
111
112
|
];
|
|
@@ -241,8 +242,9 @@ export class SequencerPublisher {
|
|
|
241
242
|
};
|
|
242
243
|
const args = [
|
|
243
244
|
header.toViem(),
|
|
244
|
-
|
|
245
|
+
CommitteeAttestationsAndSigners.empty().getPackedAttestations(),
|
|
245
246
|
[],
|
|
247
|
+
Signature.empty().toViemSignature(),
|
|
246
248
|
`0x${'0'.repeat(64)}`,
|
|
247
249
|
header.contentCommitment.blobsHash.toString(),
|
|
248
250
|
flags
|
|
@@ -350,10 +352,11 @@ export class SequencerPublisher {
|
|
|
350
352
|
reason
|
|
351
353
|
};
|
|
352
354
|
this.log.debug(`Simulating invalidate block ${block.blockNumber}`, logData);
|
|
355
|
+
const attestationsAndSigners = new CommitteeAttestationsAndSigners(attestations).getPackedAttestations();
|
|
353
356
|
if (reason === 'invalid-attestation') {
|
|
354
|
-
return this.rollupContract.buildInvalidateBadAttestationRequest(block.blockNumber,
|
|
357
|
+
return this.rollupContract.buildInvalidateBadAttestationRequest(block.blockNumber, attestationsAndSigners, committee, validationResult.invalidIndex);
|
|
355
358
|
} else if (reason === 'insufficient-attestations') {
|
|
356
|
-
return this.rollupContract.buildInvalidateInsufficientAttestationsRequest(block.blockNumber,
|
|
359
|
+
return this.rollupContract.buildInvalidateInsufficientAttestationsRequest(block.blockNumber, attestationsAndSigners, committee);
|
|
357
360
|
} else {
|
|
358
361
|
const _ = reason;
|
|
359
362
|
throw new Error(`Unknown reason for invalidation`);
|
|
@@ -367,45 +370,41 @@ export class SequencerPublisher {
|
|
|
367
370
|
* @param block - The block to propose
|
|
368
371
|
* @param attestationData - The block's attestation data
|
|
369
372
|
*
|
|
370
|
-
*/ async validateBlockForSubmission(block,
|
|
371
|
-
digest: Buffer.alloc(32),
|
|
372
|
-
attestations: []
|
|
373
|
-
}, options) {
|
|
373
|
+
*/ async validateBlockForSubmission(block, attestationsAndSigners, attestationsAndSignersSignature, options) {
|
|
374
374
|
const ts = BigInt((await this.l1TxUtils.getBlock()).timestamp + this.ethereumSlotDuration);
|
|
375
375
|
// If we have no attestations, we still need to provide the empty attestations
|
|
376
376
|
// so that the committee is recalculated correctly
|
|
377
|
-
const ignoreSignatures =
|
|
377
|
+
const ignoreSignatures = attestationsAndSigners.attestations.length === 0;
|
|
378
378
|
if (ignoreSignatures) {
|
|
379
379
|
const { committee } = await this.epochCache.getCommittee(block.header.globalVariables.slotNumber.toBigInt());
|
|
380
380
|
if (!committee) {
|
|
381
381
|
this.log.warn(`No committee found for slot ${block.header.globalVariables.slotNumber.toBigInt()}`);
|
|
382
382
|
throw new Error(`No committee found for slot ${block.header.globalVariables.slotNumber.toBigInt()}`);
|
|
383
383
|
}
|
|
384
|
-
|
|
384
|
+
attestationsAndSigners.attestations = committee.map((committeeMember)=>CommitteeAttestation.fromAddress(committeeMember));
|
|
385
385
|
}
|
|
386
386
|
const blobs = await Blob.getBlobsPerBlock(block.body.toBlobFields());
|
|
387
387
|
const blobInput = Blob.getPrefixedEthBlobCommitments(blobs);
|
|
388
|
-
const formattedAttestations = attestationData.attestations.map((attest)=>attest.toViem());
|
|
389
|
-
const signers = attestationData.attestations.filter((attest)=>!attest.signature.isEmpty()).map((attest)=>attest.address.toString());
|
|
390
388
|
const args = [
|
|
391
389
|
{
|
|
392
390
|
header: block.header.toPropose().toViem(),
|
|
393
391
|
archive: toHex(block.archive.root.toBuffer()),
|
|
394
392
|
stateReference: block.header.state.toViem(),
|
|
395
|
-
txHashes: block.body.txEffects.map((txEffect)=>txEffect.txHash.toString()),
|
|
396
393
|
oracleInput: {
|
|
397
394
|
feeAssetPriceModifier: 0n
|
|
398
395
|
}
|
|
399
396
|
},
|
|
400
|
-
|
|
401
|
-
|
|
397
|
+
attestationsAndSigners.getPackedAttestations(),
|
|
398
|
+
attestationsAndSigners.getSigners().map((signer)=>signer.toString()),
|
|
399
|
+
attestationsAndSignersSignature.toViemSignature(),
|
|
402
400
|
blobInput
|
|
403
401
|
];
|
|
404
402
|
await this.simulateProposeTx(args, ts, options);
|
|
405
403
|
return ts;
|
|
406
404
|
}
|
|
407
405
|
async enqueueCastSignalHelper(slotNumber, timestamp, signalType, payload, base, signerAddress, signer) {
|
|
408
|
-
if (this.
|
|
406
|
+
if (this.lastActions[signalType] && this.lastActions[signalType] === slotNumber) {
|
|
407
|
+
this.log.debug(`Skipping duplicate vote cast signal ${signalType} for slot ${slotNumber}`);
|
|
409
408
|
return false;
|
|
410
409
|
}
|
|
411
410
|
if (payload.equals(EthAddress.ZERO)) {
|
|
@@ -420,9 +419,9 @@ export class SequencerPublisher {
|
|
|
420
419
|
if (roundInfo.lastSignalSlot >= slotNumber) {
|
|
421
420
|
return false;
|
|
422
421
|
}
|
|
423
|
-
const cachedLastVote = this.
|
|
424
|
-
this.
|
|
425
|
-
const action = signalType
|
|
422
|
+
const cachedLastVote = this.lastActions[signalType];
|
|
423
|
+
this.lastActions[signalType] = slotNumber;
|
|
424
|
+
const action = signalType;
|
|
426
425
|
const request = await base.createSignalRequestWithSignature(payload.toString(), slotNumber, this.config.l1ChainId, signerAddress.toString(), signer);
|
|
427
426
|
this.log.debug(`Created ${action} request with signature`, {
|
|
428
427
|
request,
|
|
@@ -459,7 +458,7 @@ export class SequencerPublisher {
|
|
|
459
458
|
};
|
|
460
459
|
if (!success) {
|
|
461
460
|
this.log.error(`Signaling in [${action}] for ${payload} at slot ${slotNumber} in round ${round} failed`, logData);
|
|
462
|
-
this.
|
|
461
|
+
this.lastActions[signalType] = cachedLastVote;
|
|
463
462
|
return false;
|
|
464
463
|
} else {
|
|
465
464
|
this.log.info(`Signaling in [${action}] for ${payload} at slot ${slotNumber} in round ${round} succeeded`, logData);
|
|
@@ -475,7 +474,7 @@ export class SequencerPublisher {
|
|
|
475
474
|
* @param timestamp - The timestamp of the slot to cast a signal for.
|
|
476
475
|
* @returns True if the signal was successfully enqueued, false otherwise.
|
|
477
476
|
*/ enqueueGovernanceCastSignal(governancePayload, slotNumber, timestamp, signerAddress, signer) {
|
|
478
|
-
return this.enqueueCastSignalHelper(slotNumber, timestamp,
|
|
477
|
+
return this.enqueueCastSignalHelper(slotNumber, timestamp, 'governance-signal', governancePayload, this.govProposerContract, signerAddress, signer);
|
|
479
478
|
}
|
|
480
479
|
/** Enqueues all slashing actions as returned by the slasher client. */ async enqueueSlashingActions(actions, slotNumber, timestamp, signerAddress, signer) {
|
|
481
480
|
if (actions.length === 0) {
|
|
@@ -493,7 +492,7 @@ export class SequencerPublisher {
|
|
|
493
492
|
this.log.debug(`Enqueuing slashing vote for payload ${action.payload} at slot ${slotNumber}`, {
|
|
494
493
|
signerAddress
|
|
495
494
|
});
|
|
496
|
-
await this.enqueueCastSignalHelper(slotNumber, timestamp,
|
|
495
|
+
await this.enqueueCastSignalHelper(slotNumber, timestamp, 'empire-slashing-signal', action.payload, this.slashingProposerContract, signerAddress, signer);
|
|
497
496
|
break;
|
|
498
497
|
}
|
|
499
498
|
case 'create-empire-payload':
|
|
@@ -569,10 +568,8 @@ export class SequencerPublisher {
|
|
|
569
568
|
*
|
|
570
569
|
* @param block - L2 block to propose.
|
|
571
570
|
* @returns True if the tx has been enqueued, throws otherwise. See #9315
|
|
572
|
-
*/ async enqueueProposeL2Block(block,
|
|
571
|
+
*/ async enqueueProposeL2Block(block, attestationsAndSigners, attestationsAndSignersSignature, opts = {}) {
|
|
573
572
|
const proposedBlockHeader = block.header.toPropose();
|
|
574
|
-
const consensusPayload = ConsensusPayload.fromBlock(block);
|
|
575
|
-
const digest = getHashedSignaturePayload(consensusPayload, SignatureDomainSeparator.blockAttestation);
|
|
576
573
|
const blobs = await Blob.getBlobsPerBlock(block.body.toBlobFields());
|
|
577
574
|
const proposeTxArgs = {
|
|
578
575
|
header: proposedBlockHeader,
|
|
@@ -580,8 +577,8 @@ export class SequencerPublisher {
|
|
|
580
577
|
stateReference: block.header.state,
|
|
581
578
|
body: block.body.toBuffer(),
|
|
582
579
|
blobs,
|
|
583
|
-
|
|
584
|
-
|
|
580
|
+
attestationsAndSigners,
|
|
581
|
+
attestationsAndSignersSignature
|
|
585
582
|
};
|
|
586
583
|
let ts;
|
|
587
584
|
try {
|
|
@@ -589,12 +586,8 @@ export class SequencerPublisher {
|
|
|
589
586
|
// This means that we can avoid the simulation issues in later checks.
|
|
590
587
|
// By simulation issue, I mean the fact that the block.timestamp is equal to the last block, not the next, which
|
|
591
588
|
// make time consistency checks break.
|
|
592
|
-
const attestationData = {
|
|
593
|
-
digest: digest.toBuffer(),
|
|
594
|
-
attestations: attestations ?? []
|
|
595
|
-
};
|
|
596
589
|
// TODO(palla): Check whether we're validating twice, once here and once within addProposeTx, since we call simulateProposeTx in both places.
|
|
597
|
-
ts = await this.validateBlockForSubmission(block,
|
|
590
|
+
ts = await this.validateBlockForSubmission(block, attestationsAndSigners, attestationsAndSignersSignature, opts);
|
|
598
591
|
} catch (err) {
|
|
599
592
|
this.log.error(`Block validation failed. ${err instanceof Error ? err.message : 'No error message'}`, err, {
|
|
600
593
|
...block.getStats(),
|
|
@@ -616,8 +609,10 @@ export class SequencerPublisher {
|
|
|
616
609
|
}
|
|
617
610
|
// We issued the simulation against the rollup contract, so we need to account for the overhead of the multicall3
|
|
618
611
|
const gasLimit = this.l1TxUtils.bumpGasLimit(BigInt(Math.ceil(Number(request.gasUsed) * 64 / 63)));
|
|
612
|
+
const { gasUsed, blockNumber } = request;
|
|
619
613
|
const logData = {
|
|
620
|
-
|
|
614
|
+
gasUsed,
|
|
615
|
+
blockNumber,
|
|
621
616
|
gasLimit,
|
|
622
617
|
opts
|
|
623
618
|
};
|
|
@@ -653,8 +648,14 @@ export class SequencerPublisher {
|
|
|
653
648
|
timestamp,
|
|
654
649
|
gasLimit: undefined
|
|
655
650
|
};
|
|
651
|
+
if (this.lastActions[action] && this.lastActions[action] === slotNumber) {
|
|
652
|
+
this.log.debug(`Skipping duplicate action ${action} for slot ${slotNumber}`);
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
const cachedLastActionSlot = this.lastActions[action];
|
|
656
|
+
this.lastActions[action] = slotNumber;
|
|
657
|
+
this.log.debug(`Simulating ${action} for slot ${slotNumber}`, logData);
|
|
656
658
|
let gasUsed;
|
|
657
|
-
this.log.debug(`Simulating ${action}`, logData);
|
|
658
659
|
try {
|
|
659
660
|
({ gasUsed } = await this.l1TxUtils.simulate(request, {
|
|
660
661
|
time: timestamp
|
|
@@ -687,6 +688,7 @@ export class SequencerPublisher {
|
|
|
687
688
|
...result,
|
|
688
689
|
...logData
|
|
689
690
|
});
|
|
691
|
+
this.lastActions[action] = cachedLastActionSlot;
|
|
690
692
|
} else {
|
|
691
693
|
this.log.info(`Action ${action} at ${slotNumber} succeeded`, {
|
|
692
694
|
...result,
|
|
@@ -736,9 +738,7 @@ export class SequencerPublisher {
|
|
|
736
738
|
});
|
|
737
739
|
throw new Error('Failed to validate blobs');
|
|
738
740
|
});
|
|
739
|
-
const
|
|
740
|
-
const txHashes = encodedData.txHashes ? encodedData.txHashes.map((txHash)=>txHash.toString()) : [];
|
|
741
|
-
const signers = encodedData.attestations?.filter((attest)=>!attest.signature.isEmpty()).map((attest)=>attest.address.toString());
|
|
741
|
+
const signers = encodedData.attestationsAndSigners.getSigners().map((signer)=>signer.toString());
|
|
742
742
|
const args = [
|
|
743
743
|
{
|
|
744
744
|
header: encodedData.header.toViem(),
|
|
@@ -747,11 +747,11 @@ export class SequencerPublisher {
|
|
|
747
747
|
oracleInput: {
|
|
748
748
|
// We are currently not modifying these. See #9963
|
|
749
749
|
feeAssetPriceModifier: 0n
|
|
750
|
-
}
|
|
751
|
-
txHashes
|
|
750
|
+
}
|
|
752
751
|
},
|
|
753
|
-
|
|
754
|
-
signers
|
|
752
|
+
encodedData.attestationsAndSigners.getPackedAttestations(),
|
|
753
|
+
signers,
|
|
754
|
+
encodedData.attestationsAndSignersSignature.toViemSignature(),
|
|
755
755
|
blobInput
|
|
756
756
|
];
|
|
757
757
|
const { rollupData, simulationResult } = await this.simulateProposeTx(args, timestamp, options);
|
|
@@ -843,13 +843,16 @@ export class SequencerPublisher {
|
|
|
843
843
|
if (success) {
|
|
844
844
|
const endBlock = receipt.blockNumber;
|
|
845
845
|
const inclusionBlocks = Number(endBlock - startBlock);
|
|
846
|
+
const { calldataGas, calldataSize, sender } = stats;
|
|
846
847
|
const publishStats = {
|
|
847
848
|
gasPrice: receipt.effectiveGasPrice,
|
|
848
849
|
gasUsed: receipt.gasUsed,
|
|
849
850
|
blobGasUsed: receipt.blobGasUsed ?? 0n,
|
|
850
851
|
blobDataGas: receipt.blobGasPrice ?? 0n,
|
|
851
852
|
transactionHash: receipt.transactionHash,
|
|
852
|
-
|
|
853
|
+
calldataGas,
|
|
854
|
+
calldataSize,
|
|
855
|
+
sender,
|
|
853
856
|
...block.getStats(),
|
|
854
857
|
eventName: 'rollup-published-to-l1',
|
|
855
858
|
blobCount: encodedData.blobs.length,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { EthAddress } from '@aztec/aztec.js';
|
|
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,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/sequencer/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,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"}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Attributes, Metrics, ValueType } from '@aztec/telemetry-client';
|
|
2
2
|
import { formatUnits } from 'viem';
|
|
3
|
-
import { sequencerStateToNumber } from './utils.js';
|
|
4
3
|
export class SequencerMetrics {
|
|
5
|
-
coinbase;
|
|
6
4
|
rollup;
|
|
7
5
|
tracer;
|
|
8
6
|
meter;
|
|
@@ -10,9 +8,6 @@ export class SequencerMetrics {
|
|
|
10
8
|
blockBuildDuration;
|
|
11
9
|
blockBuildManaPerSecond;
|
|
12
10
|
stateTransitionBufferDuration;
|
|
13
|
-
currentBlockNumber;
|
|
14
|
-
currentBlockSize;
|
|
15
|
-
blockBuilderInsertions;
|
|
16
11
|
// these are gauges because for individual sequencers building a block is not something that happens often enough to warrant a histogram
|
|
17
12
|
timeToCollectAttestations;
|
|
18
13
|
allowanceToCollectAttestations;
|
|
@@ -21,19 +16,9 @@ export class SequencerMetrics {
|
|
|
21
16
|
rewards;
|
|
22
17
|
slots;
|
|
23
18
|
filledSlots;
|
|
24
|
-
missedSlots;
|
|
25
19
|
lastSeenSlot;
|
|
26
|
-
constructor(client,
|
|
27
|
-
this.coinbase = coinbase;
|
|
20
|
+
constructor(client, rollup, name = 'Sequencer'){
|
|
28
21
|
this.rollup = rollup;
|
|
29
|
-
this.observe = async (observer)=>{
|
|
30
|
-
let rewards = 0n;
|
|
31
|
-
rewards = await this.rollup.getSequencerRewards(this.coinbase);
|
|
32
|
-
const fmt = parseFloat(formatUnits(rewards, 18));
|
|
33
|
-
observer.observe(this.rewards, fmt, {
|
|
34
|
-
[Attributes.COINBASE]: this.coinbase.toString()
|
|
35
|
-
});
|
|
36
|
-
};
|
|
37
22
|
this.meter = client.getMeter(name);
|
|
38
23
|
this.tracer = client.getTracer(name);
|
|
39
24
|
this.blockCounter = this.meter.createUpDownCounter(Metrics.SEQUENCER_BLOCK_COUNT);
|
|
@@ -52,37 +37,14 @@ export class SequencerMetrics {
|
|
|
52
37
|
description: 'The time difference between when the sequencer needed to transition to a new state and when it actually did.',
|
|
53
38
|
valueType: ValueType.INT
|
|
54
39
|
});
|
|
55
|
-
const currentState = this.meter.createObservableGauge(Metrics.SEQUENCER_CURRENT_STATE, {
|
|
56
|
-
description: 'Current state of the sequencer'
|
|
57
|
-
});
|
|
58
|
-
currentState.addCallback((observer)=>{
|
|
59
|
-
observer.observe(sequencerStateToNumber(getState()));
|
|
60
|
-
});
|
|
61
|
-
this.currentBlockNumber = this.meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_NUMBER, {
|
|
62
|
-
description: 'Current block number',
|
|
63
|
-
valueType: ValueType.INT
|
|
64
|
-
});
|
|
65
|
-
this.currentBlockSize = this.meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_SIZE, {
|
|
66
|
-
description: 'Current block size',
|
|
67
|
-
valueType: ValueType.INT
|
|
68
|
-
});
|
|
69
|
-
this.blockBuilderInsertions = this.meter.createHistogram(Metrics.SEQUENCER_BLOCK_BUILD_INSERTION_TIME, {
|
|
70
|
-
description: 'Timer for tree insertions performed by the block builder',
|
|
71
|
-
unit: 'us',
|
|
72
|
-
valueType: ValueType.INT
|
|
73
|
-
});
|
|
74
40
|
// Init gauges and counters
|
|
75
|
-
this.setCurrentBlock(0, 0);
|
|
76
|
-
this.blockCounter.add(0, {
|
|
77
|
-
[Attributes.STATUS]: 'cancelled'
|
|
78
|
-
});
|
|
79
41
|
this.blockCounter.add(0, {
|
|
80
42
|
[Attributes.STATUS]: 'failed'
|
|
81
43
|
});
|
|
82
44
|
this.blockCounter.add(0, {
|
|
83
45
|
[Attributes.STATUS]: 'built'
|
|
84
46
|
});
|
|
85
|
-
this.rewards = this.meter.
|
|
47
|
+
this.rewards = this.meter.createGauge(Metrics.SEQUENCER_CURRENT_BLOCK_REWARDS, {
|
|
86
48
|
valueType: ValueType.DOUBLE,
|
|
87
49
|
description: 'The rewards earned'
|
|
88
50
|
});
|
|
@@ -90,14 +52,13 @@ export class SequencerMetrics {
|
|
|
90
52
|
valueType: ValueType.INT,
|
|
91
53
|
description: 'The number of slots this sequencer was selected for'
|
|
92
54
|
});
|
|
93
|
-
|
|
55
|
+
/**
|
|
56
|
+
* NOTE: we do not track missed slots as a separate metric. That would be difficult to determine
|
|
57
|
+
* Instead, use a computed metric, `slots - filledSlots` to get the number of slots a sequencer has missed.
|
|
58
|
+
*/ this.filledSlots = this.meter.createUpDownCounter(Metrics.SEQUENCER_FILLED_SLOT_COUNT, {
|
|
94
59
|
valueType: ValueType.INT,
|
|
95
60
|
description: 'The number of slots this sequencer has filled'
|
|
96
61
|
});
|
|
97
|
-
this.missedSlots = this.meter.createUpDownCounter(Metrics.SEQUENCER_MISSED_SLOT_COUNT, {
|
|
98
|
-
valueType: ValueType.INT,
|
|
99
|
-
description: 'The number of slots this sequencer has missed to fill'
|
|
100
|
-
});
|
|
101
62
|
this.timeToCollectAttestations = this.meter.createGauge(Metrics.SEQUENCER_COLLECT_ATTESTATIONS_DURATION, {
|
|
102
63
|
description: 'The time spent collecting attestations from committee members',
|
|
103
64
|
unit: 'ms',
|
|
@@ -117,20 +78,6 @@ export class SequencerMetrics {
|
|
|
117
78
|
description: 'The minimum number of attestations required to publish a block'
|
|
118
79
|
});
|
|
119
80
|
}
|
|
120
|
-
setCoinbase(coinbase) {
|
|
121
|
-
this.coinbase = coinbase;
|
|
122
|
-
}
|
|
123
|
-
start() {
|
|
124
|
-
this.meter.addBatchObservableCallback(this.observe, [
|
|
125
|
-
this.rewards
|
|
126
|
-
]);
|
|
127
|
-
}
|
|
128
|
-
stop() {
|
|
129
|
-
this.meter.removeBatchObservableCallback(this.observe, [
|
|
130
|
-
this.rewards
|
|
131
|
-
]);
|
|
132
|
-
}
|
|
133
|
-
observe;
|
|
134
81
|
recordRequiredAttestations(requiredAttestationsCount, allowanceMs) {
|
|
135
82
|
this.requiredAttestions.record(requiredAttestationsCount);
|
|
136
83
|
this.allowanceToCollectAttestations.record(Math.ceil(allowanceMs));
|
|
@@ -142,15 +89,6 @@ export class SequencerMetrics {
|
|
|
142
89
|
this.collectedAttestions.record(count);
|
|
143
90
|
this.timeToCollectAttestations.record(Math.ceil(durationMs));
|
|
144
91
|
}
|
|
145
|
-
recordBlockBuilderTreeInsertions(timeUs) {
|
|
146
|
-
this.blockBuilderInsertions.record(Math.ceil(timeUs));
|
|
147
|
-
}
|
|
148
|
-
recordCancelledBlock() {
|
|
149
|
-
this.blockCounter.add(1, {
|
|
150
|
-
[Attributes.STATUS]: 'cancelled'
|
|
151
|
-
});
|
|
152
|
-
this.setCurrentBlock(0, 0);
|
|
153
|
-
}
|
|
154
92
|
recordBuiltBlock(buildDurationMs, totalMana) {
|
|
155
93
|
this.blockCounter.add(1, {
|
|
156
94
|
[Attributes.STATUS]: 'built'
|
|
@@ -162,41 +100,37 @@ export class SequencerMetrics {
|
|
|
162
100
|
this.blockCounter.add(1, {
|
|
163
101
|
[Attributes.STATUS]: 'failed'
|
|
164
102
|
});
|
|
165
|
-
this.setCurrentBlock(0, 0);
|
|
166
|
-
}
|
|
167
|
-
recordNewBlock(blockNumber, txCount) {
|
|
168
|
-
this.setCurrentBlock(blockNumber, txCount);
|
|
169
103
|
}
|
|
170
104
|
recordStateTransitionBufferMs(durationMs, state) {
|
|
171
105
|
this.stateTransitionBufferDuration.record(durationMs, {
|
|
172
106
|
[Attributes.SEQUENCER_STATE]: state
|
|
173
107
|
});
|
|
174
108
|
}
|
|
175
|
-
|
|
109
|
+
incOpenSlot(slot, proposer) {
|
|
176
110
|
// sequencer went through the loop a second time. Noop
|
|
177
111
|
if (slot === this.lastSeenSlot) {
|
|
178
112
|
return;
|
|
179
113
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
if (typeof slot === 'bigint') {
|
|
186
|
-
this.slots.add(1, {
|
|
187
|
-
[Attributes.BLOCK_PROPOSER]: proposer
|
|
188
|
-
});
|
|
189
|
-
}
|
|
114
|
+
this.slots.add(1, {
|
|
115
|
+
[Attributes.BLOCK_PROPOSER]: proposer
|
|
116
|
+
});
|
|
190
117
|
this.lastSeenSlot = slot;
|
|
191
118
|
}
|
|
192
|
-
incFilledSlot(proposer) {
|
|
119
|
+
async incFilledSlot(proposer, coinbase) {
|
|
193
120
|
this.filledSlots.add(1, {
|
|
194
121
|
[Attributes.BLOCK_PROPOSER]: proposer
|
|
195
122
|
});
|
|
196
123
|
this.lastSeenSlot = undefined;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
124
|
+
if (coinbase) {
|
|
125
|
+
try {
|
|
126
|
+
const rewards = await this.rollup.getSequencerRewards(coinbase);
|
|
127
|
+
const fmt = parseFloat(formatUnits(rewards, 18));
|
|
128
|
+
this.rewards.record(fmt, {
|
|
129
|
+
[Attributes.COINBASE]: coinbase.toString()
|
|
130
|
+
});
|
|
131
|
+
} catch {
|
|
132
|
+
// no-op
|
|
133
|
+
}
|
|
134
|
+
}
|
|
201
135
|
}
|
|
202
136
|
}
|
|
@@ -2,16 +2,17 @@ import type { L2Block } from '@aztec/aztec.js';
|
|
|
2
2
|
import type { EpochCache } from '@aztec/epoch-cache';
|
|
3
3
|
import { type RollupContract } from '@aztec/ethereum';
|
|
4
4
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
|
+
import { Signature } from '@aztec/foundation/eth-signature';
|
|
5
6
|
import { Fr } from '@aztec/foundation/fields';
|
|
6
7
|
import { type DateProvider } from '@aztec/foundation/timer';
|
|
7
8
|
import type { TypedEventEmitter } from '@aztec/foundation/types';
|
|
8
9
|
import type { P2P } from '@aztec/p2p';
|
|
9
10
|
import type { SlasherClientInterface } from '@aztec/slasher';
|
|
10
|
-
import type
|
|
11
|
+
import { type CommitteeAttestation, CommitteeAttestationsAndSigners, type L2BlockSource, type ValidateBlockResult } from '@aztec/stdlib/block';
|
|
11
12
|
import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
12
13
|
import { type IFullNodeBlockBuilder, type PublicProcessorLimits, type WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
13
14
|
import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
|
|
14
|
-
import { Tx
|
|
15
|
+
import { Tx } from '@aztec/stdlib/tx';
|
|
15
16
|
import { type TelemetryClient, type Tracer } from '@aztec/telemetry-client';
|
|
16
17
|
import type { ValidatorClient } from '@aztec/validator-client';
|
|
17
18
|
import type { GlobalVariableBuilder } from '../global_variable_builder/global_builder.js';
|
|
@@ -160,7 +161,7 @@ export declare class Sequencer extends Sequencer_base {
|
|
|
160
161
|
* Publishes the L2Block to the rollup contract.
|
|
161
162
|
* @param block - The L2Block to be published.
|
|
162
163
|
*/
|
|
163
|
-
protected enqueuePublishL2Block(block: L2Block,
|
|
164
|
+
protected enqueuePublishL2Block(block: L2Block, attestationsAndSigners: CommitteeAttestationsAndSigners, attestationsAndSignersSignature: Signature, invalidateBlock: InvalidateBlockRequest | undefined, publisher: SequencerPublisher): Promise<void>;
|
|
164
165
|
/**
|
|
165
166
|
* Returns whether all dependencies have caught up.
|
|
166
167
|
* We don't check against the previous block submitted since it may have been reorg'd out.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../../src/sequencer/sequencer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAwC,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE5F,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAG9C,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"sequencer.d.ts","sourceRoot":"","sources":["../../src/sequencer/sequencer.ts"],"names":[],"mappings":"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"}
|