@aztec/sequencer-client 2.0.3 → 2.1.0-rc.2
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 +7 -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 +2 -4
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +7 -10
- 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 +14 -20
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +53 -58
- 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 +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 +27 -21
- package/dest/sequencer/timetable.d.ts +0 -6
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +2 -9
- 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/package.json +28 -28
- package/src/client/sequencer-client.ts +6 -2
- package/src/config.ts +3 -0
- package/src/publisher/config.ts +13 -11
- package/src/publisher/index.ts +1 -1
- package/src/publisher/sequencer-publisher-factory.ts +12 -2
- package/src/publisher/sequencer-publisher.ts +77 -77
- package/src/sequencer/errors.ts +21 -0
- package/src/sequencer/metrics.ts +24 -100
- package/src/sequencer/sequencer.ts +51 -46
- package/src/sequencer/timetable.ts +2 -13
- package/src/sequencer/utils.ts +10 -24
|
@@ -4,15 +4,17 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
4
4
|
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
}
|
|
7
|
-
import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
|
|
7
|
+
import { BLOBS_PER_BLOCK, FIELDS_PER_BLOB, INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
|
|
8
8
|
import { FormattedViemError, NoCommitteeError } from '@aztec/ethereum';
|
|
9
9
|
import { omit, pick } from '@aztec/foundation/collection';
|
|
10
10
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
11
|
+
import { Signature } from '@aztec/foundation/eth-signature';
|
|
11
12
|
import { Fr } from '@aztec/foundation/fields';
|
|
12
13
|
import { createLogger } from '@aztec/foundation/log';
|
|
13
14
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
14
15
|
import { Timer } from '@aztec/foundation/timer';
|
|
15
|
-
import {
|
|
16
|
+
import { CommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
17
|
+
import { getSlotAtTimestamp, getSlotStartBuildTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
16
18
|
import { Gas } from '@aztec/stdlib/gas';
|
|
17
19
|
import { SequencerConfigSchema } from '@aztec/stdlib/interfaces/server';
|
|
18
20
|
import { orderAttestations } from '@aztec/stdlib/p2p';
|
|
@@ -22,8 +24,9 @@ import { ContentCommitment, ProposedBlockHeader } from '@aztec/stdlib/tx';
|
|
|
22
24
|
import { AttestationTimeoutError } from '@aztec/stdlib/validators';
|
|
23
25
|
import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
24
26
|
import EventEmitter from 'node:events';
|
|
27
|
+
import { SequencerInterruptedError, SequencerTooSlowError } from './errors.js';
|
|
25
28
|
import { SequencerMetrics } from './metrics.js';
|
|
26
|
-
import { SequencerTimetable
|
|
29
|
+
import { SequencerTimetable } from './timetable.js';
|
|
27
30
|
import { SequencerState } from './utils.js';
|
|
28
31
|
export { SequencerState };
|
|
29
32
|
/**
|
|
@@ -72,10 +75,7 @@ export { SequencerState };
|
|
|
72
75
|
publisher;
|
|
73
76
|
constructor(publisherFactory, validatorClient, globalsBuilder, p2pClient, worldState, slasherClient, l2BlockSource, l1ToL2MessageSource, blockBuilder, l1Constants, dateProvider, epochCache, rollupContract, config, telemetry = getTelemetryClient(), log = createLogger('sequencer')){
|
|
74
77
|
super(), this.publisherFactory = publisherFactory, this.validatorClient = validatorClient, this.globalsBuilder = globalsBuilder, this.p2pClient = p2pClient, this.worldState = worldState, this.slasherClient = slasherClient, this.l2BlockSource = l2BlockSource, this.l1ToL2MessageSource = l1ToL2MessageSource, this.blockBuilder = blockBuilder, this.l1Constants = l1Constants, this.dateProvider = dateProvider, this.epochCache = epochCache, this.rollupContract = rollupContract, this.config = config, this.telemetry = telemetry, this.log = log, this.pollingIntervalMs = 1000, this.maxTxsPerBlock = 32, this.minTxsPerBlock = 1, this.maxL1TxInclusionTimeIntoSlot = 0, this.state = SequencerState.STOPPED, this.maxBlockSizeInBytes = 1024 * 1024, this.maxBlockGas = new Gas(100e9, 100e9), this.enforceTimeTable = false;
|
|
75
|
-
|
|
76
|
-
const validatorAddresses = this.validatorClient?.getValidatorAddresses() ?? [];
|
|
77
|
-
const coinbase = validatorAddresses.length === 0 ? EthAddress.ZERO : this.validatorClient?.getCoinbaseForAttestor(validatorAddresses[0]) ?? EthAddress.ZERO;
|
|
78
|
-
this.metrics = new SequencerMetrics(telemetry, ()=>this.state, coinbase, this.rollupContract, 'Sequencer');
|
|
78
|
+
this.metrics = new SequencerMetrics(telemetry, this.rollupContract, 'Sequencer');
|
|
79
79
|
// Initialize config
|
|
80
80
|
this.updateConfig(this.config);
|
|
81
81
|
}
|
|
@@ -140,7 +140,6 @@ export { SequencerState };
|
|
|
140
140
|
/**
|
|
141
141
|
* Starts the sequencer and moves to IDLE state.
|
|
142
142
|
*/ start() {
|
|
143
|
-
this.metrics.start();
|
|
144
143
|
this.runningPromise = new RunningPromise(this.work.bind(this), this.log, this.pollingIntervalMs);
|
|
145
144
|
this.setState(SequencerState.IDLE, undefined, {
|
|
146
145
|
force: true
|
|
@@ -152,9 +151,10 @@ export { SequencerState };
|
|
|
152
151
|
* Stops the sequencer from processing txs and moves to STOPPED state.
|
|
153
152
|
*/ async stop() {
|
|
154
153
|
this.log.info(`Stopping sequencer`);
|
|
155
|
-
this.
|
|
154
|
+
this.setState(SequencerState.STOPPING, undefined, {
|
|
155
|
+
force: true
|
|
156
|
+
});
|
|
156
157
|
this.publisher?.interrupt();
|
|
157
|
-
await this.validatorClient?.stop();
|
|
158
158
|
await this.runningPromise?.stop();
|
|
159
159
|
this.setState(SequencerState.STOPPED, undefined, {
|
|
160
160
|
force: true
|
|
@@ -259,7 +259,6 @@ export { SequencerState };
|
|
|
259
259
|
this.publisher = publisher;
|
|
260
260
|
const coinbase = this.validatorClient.getCoinbaseForAttestor(attestorAddress);
|
|
261
261
|
const feeRecipient = this.validatorClient.getFeeRecipientForAttestor(attestorAddress);
|
|
262
|
-
this.metrics.setCoinbase(coinbase);
|
|
263
262
|
// Prepare invalidation request if the pending chain is invalid (returns undefined if no need)
|
|
264
263
|
const invalidateBlock = await publisher.simulateInvalidateBlock(syncedTo.pendingChainValidationStatus);
|
|
265
264
|
const canProposeCheck = await publisher.canProposeAtNextEthBlock(chainTipArchive, proposerAddressInNextSlot, invalidateBlock);
|
|
@@ -317,6 +316,7 @@ export { SequencerState };
|
|
|
317
316
|
publisher.enqueueInvalidateBlock(invalidateBlock);
|
|
318
317
|
}
|
|
319
318
|
this.setState(SequencerState.INITIALIZING_PROPOSAL, slot);
|
|
319
|
+
this.metrics.incOpenSlot(slot, proposerAddressInNextSlot.toString());
|
|
320
320
|
this.log.verbose(`Preparing proposal for block ${newBlockNumber} at slot ${slot}`, {
|
|
321
321
|
proposer: proposerInNextSlot?.toString(),
|
|
322
322
|
coinbase,
|
|
@@ -379,7 +379,7 @@ export { SequencerState };
|
|
|
379
379
|
blockNumber: newBlockNumber,
|
|
380
380
|
slot: Number(slot)
|
|
381
381
|
});
|
|
382
|
-
this.metrics.incFilledSlot(publisher.getSenderAddress().toString());
|
|
382
|
+
await this.metrics.incFilledSlot(publisher.getSenderAddress().toString(), coinbase);
|
|
383
383
|
} else if (block) {
|
|
384
384
|
this.emit('block-publish-failed', l1Response ?? {});
|
|
385
385
|
}
|
|
@@ -407,6 +407,10 @@ export { SequencerState };
|
|
|
407
407
|
}
|
|
408
408
|
}
|
|
409
409
|
setState(proposedState, slotNumber, opts = {}) {
|
|
410
|
+
if (this.state === SequencerState.STOPPING && proposedState !== SequencerState.STOPPED && !opts.force) {
|
|
411
|
+
this.log.warn(`Cannot set sequencer to ${proposedState} as it is stopping.`);
|
|
412
|
+
throw new SequencerInterruptedError();
|
|
413
|
+
}
|
|
410
414
|
if (this.state === SequencerState.STOPPED && !opts.force) {
|
|
411
415
|
this.log.warn(`Cannot set sequencer from ${this.state} to ${proposedState} as it is stopped.`);
|
|
412
416
|
return;
|
|
@@ -452,6 +456,7 @@ export { SequencerState };
|
|
|
452
456
|
maxTransactions: this.maxTxsPerBlock,
|
|
453
457
|
maxBlockSize: this.maxBlockSizeInBytes,
|
|
454
458
|
maxBlockGas: this.maxBlockGas,
|
|
459
|
+
maxBlobFields: BLOBS_PER_BLOCK * FIELDS_PER_BLOB,
|
|
455
460
|
deadline
|
|
456
461
|
};
|
|
457
462
|
}
|
|
@@ -470,7 +475,6 @@ export { SequencerState };
|
|
|
470
475
|
const blockNumber = newGlobalVariables.blockNumber;
|
|
471
476
|
const slot = proposalHeader.slotNumber.toBigInt();
|
|
472
477
|
const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(blockNumber);
|
|
473
|
-
// this.metrics.recordNewBlock(blockNumber, validTxs.length);
|
|
474
478
|
const workTimer = new Timer();
|
|
475
479
|
this.setState(SequencerState.CREATING_BLOCK, slot);
|
|
476
480
|
try {
|
|
@@ -515,7 +519,9 @@ export { SequencerState };
|
|
|
515
519
|
blockNumber
|
|
516
520
|
});
|
|
517
521
|
}
|
|
518
|
-
|
|
522
|
+
const attestationsAndSigners = new CommitteeAttestationsAndSigners(attestations ?? []);
|
|
523
|
+
const attestationsAndSignersSignature = this.validatorClient ? await this.validatorClient.signAttestationsAndSigners(attestationsAndSigners, proposerAddress) : Signature.empty();
|
|
524
|
+
await this.enqueuePublishL2Block(block, attestationsAndSigners, attestationsAndSignersSignature, invalidateBlock, publisher);
|
|
519
525
|
this.metrics.recordBuiltBlock(blockBuildDuration, publicGas.l2Gas);
|
|
520
526
|
return block;
|
|
521
527
|
} catch (err) {
|
|
@@ -561,32 +567,32 @@ export { SequencerState };
|
|
|
561
567
|
const attestationTimeAllowed = this.enforceTimeTable ? this.timetable.getMaxAllowedTime(SequencerState.PUBLISHING_BLOCK) : this.aztecSlotDuration;
|
|
562
568
|
this.metrics.recordRequiredAttestations(numberOfRequiredAttestations, attestationTimeAllowed);
|
|
563
569
|
const timer = new Timer();
|
|
564
|
-
let
|
|
570
|
+
let collectedAttestationsCount = 0;
|
|
565
571
|
try {
|
|
566
572
|
const attestationDeadline = new Date(this.dateProvider.now() + attestationTimeAllowed * 1000);
|
|
567
573
|
const attestations = await this.validatorClient.collectAttestations(proposal, numberOfRequiredAttestations, attestationDeadline);
|
|
568
|
-
|
|
574
|
+
collectedAttestationsCount = attestations.length;
|
|
569
575
|
// note: the smart contract requires that the signatures are provided in the order of the committee
|
|
570
576
|
return orderAttestations(attestations, committee);
|
|
571
577
|
} catch (err) {
|
|
572
578
|
if (err && err instanceof AttestationTimeoutError) {
|
|
573
|
-
|
|
579
|
+
collectedAttestationsCount = err.collectedCount;
|
|
574
580
|
}
|
|
575
581
|
throw err;
|
|
576
582
|
} finally{
|
|
577
|
-
this.metrics.recordCollectedAttestations(
|
|
583
|
+
this.metrics.recordCollectedAttestations(collectedAttestationsCount, timer.ms());
|
|
578
584
|
}
|
|
579
585
|
}
|
|
580
586
|
/**
|
|
581
587
|
* Publishes the L2Block to the rollup contract.
|
|
582
588
|
* @param block - The L2Block to be published.
|
|
583
|
-
*/ async enqueuePublishL2Block(block,
|
|
589
|
+
*/ async enqueuePublishL2Block(block, attestationsAndSigners, attestationsAndSignersSignature, invalidateBlock, publisher) {
|
|
584
590
|
// Publishes new block to the network and awaits the tx to be mined
|
|
585
591
|
this.setState(SequencerState.PUBLISHING_BLOCK, block.header.globalVariables.slotNumber.toBigInt());
|
|
586
592
|
// Time out tx at the end of the slot
|
|
587
593
|
const slot = block.header.globalVariables.slotNumber.toNumber();
|
|
588
594
|
const txTimeoutAt = new Date((this.getSlotStartBuildTimestamp(slot) + this.aztecSlotDuration) * 1000);
|
|
589
|
-
const enqueued = await publisher.enqueueProposeL2Block(block,
|
|
595
|
+
const enqueued = await publisher.enqueueProposeL2Block(block, attestationsAndSigners, attestationsAndSignersSignature, {
|
|
590
596
|
txTimeoutAt,
|
|
591
597
|
forcePendingBlockNumber: invalidateBlock?.forcePendingBlockNumber
|
|
592
598
|
});
|
|
@@ -689,7 +695,7 @@ export { SequencerState };
|
|
|
689
695
|
await publisher.sendRequests();
|
|
690
696
|
}
|
|
691
697
|
getSlotStartBuildTimestamp(slotNumber) {
|
|
692
|
-
return
|
|
698
|
+
return getSlotStartBuildTimestamp(slotNumber, this.l1Constants);
|
|
693
699
|
}
|
|
694
700
|
getSecondsIntoSlot(slotNumber) {
|
|
695
701
|
const slotStartTimestamp = this.getSlotStartBuildTimestamp(slotNumber);
|
|
@@ -45,10 +45,4 @@ export declare class SequencerTimetable {
|
|
|
45
45
|
getMaxAllowedTime(state: SequencerState): number | undefined;
|
|
46
46
|
assertTimeLeft(newState: SequencerState, secondsIntoSlot: number): void;
|
|
47
47
|
}
|
|
48
|
-
export declare class SequencerTooSlowError extends Error {
|
|
49
|
-
readonly proposedState: SequencerState;
|
|
50
|
-
readonly maxAllowedTime: number;
|
|
51
|
-
readonly currentTime: number;
|
|
52
|
-
constructor(proposedState: SequencerState, maxAllowedTime: number, currentTime: number);
|
|
53
|
-
}
|
|
54
48
|
//# sourceMappingURL=timetable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timetable.d.ts","sourceRoot":"","sources":["../../src/sequencer/timetable.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"timetable.d.ts","sourceRoot":"","sources":["../../src/sequencer/timetable.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAM5C,qBAAa,kBAAkB;IA+C3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG;IA/CtB;;;;OAIG;IACH,SAAgB,kBAAkB,EAAE,MAAM,CAAC;IAE3C;;;;OAIG;IACH,SAAgB,gBAAgB,SAAC;IAEjC,sHAAsH;IACtH,SAAgB,gBAAgB,EAAE,MAAM,CAAsB;IAE9D,uDAAuD;IACvD,SAAgB,gBAAgB,EAAE,MAAM,CAAsB;IAE9D,mGAAmG;IACnG,SAAgB,0BAA0B,EAAE,MAAM,CAAC;IAEnD,mIAAmI;IACnI,SAAgB,mBAAmB,EAAE,MAAM,CAAyB;IAEpE,wCAAwC;IACxC,SAAgB,oBAAoB,EAAE,MAAM,CAAC;IAE7C,kFAAkF;IAClF,SAAgB,iBAAiB,EAAE,MAAM,CAAC;IAE1C,2IAA2I;IAC3I,SAAgB,4BAA4B,EAAE,MAAM,CAAC;IAErD,4DAA4D;IAC5D,SAAgB,OAAO,EAAE,OAAO,CAAC;gBAG/B,IAAI,EAAE;QACJ,oBAAoB,EAAE,MAAM,CAAC;QAC7B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,4BAA4B,EAAE,MAAM,CAAC;QACrC,0BAA0B,CAAC,EAAE,MAAM,CAAC;QACpC,OAAO,EAAE,OAAO,CAAC;KAClB,EACgB,OAAO,CAAC,EAAE,gBAAgB,YAAA,EAC1B,GAAG,mCAAsC;IA+C5D,OAAO,KAAK,yCAAyC,GAEpD;IAEM,2BAA2B,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM;IAenE,OAAO,KAAK,0BAA0B,GAErC;IAEM,yBAAyB,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM;IAU3D,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS;IAuB5D,cAAc,CAAC,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM;CAkBxE"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createLogger } from '@aztec/aztec.js';
|
|
2
2
|
import { DEFAULT_ATTESTATION_PROPAGATION_TIME } from '../config.js';
|
|
3
|
+
import { SequencerTooSlowError } from './errors.js';
|
|
3
4
|
import { SequencerState } from './utils.js';
|
|
4
5
|
const MIN_EXECUTION_TIME = 1;
|
|
5
6
|
const BLOCK_PREPARE_TIME = 1;
|
|
@@ -95,6 +96,7 @@ export class SequencerTimetable {
|
|
|
95
96
|
getMaxAllowedTime(state) {
|
|
96
97
|
switch(state){
|
|
97
98
|
case SequencerState.STOPPED:
|
|
99
|
+
case SequencerState.STOPPING:
|
|
98
100
|
case SequencerState.IDLE:
|
|
99
101
|
case SequencerState.SYNCHRONIZING:
|
|
100
102
|
return; // We don't really care about times for this states
|
|
@@ -133,12 +135,3 @@ export class SequencerTimetable {
|
|
|
133
135
|
});
|
|
134
136
|
}
|
|
135
137
|
}
|
|
136
|
-
export class SequencerTooSlowError extends Error {
|
|
137
|
-
proposedState;
|
|
138
|
-
maxAllowedTime;
|
|
139
|
-
currentTime;
|
|
140
|
-
constructor(proposedState, maxAllowedTime, currentTime){
|
|
141
|
-
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;
|
|
142
|
-
this.name = 'SequencerTooSlowError';
|
|
143
|
-
}
|
|
144
|
-
}
|
|
@@ -1,35 +1,21 @@
|
|
|
1
1
|
export declare enum SequencerState {
|
|
2
|
-
/**
|
|
3
|
-
* Sequencer is stopped and not processing any txs from the pool.
|
|
4
|
-
*/
|
|
2
|
+
/** Sequencer is stopped and not processing any txs from the pool. */
|
|
5
3
|
STOPPED = "STOPPED",
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
/** Sequencer is being stopped. Will move to STOPPED shortly. */
|
|
5
|
+
STOPPING = "STOPPING",
|
|
6
|
+
/** Sequencer is awaiting the next call to work(). */
|
|
9
7
|
IDLE = "IDLE",
|
|
10
|
-
/**
|
|
11
|
-
* Synchronizing with the L2 chain.
|
|
12
|
-
*/
|
|
8
|
+
/** Synchronizing with the L2 chain. */
|
|
13
9
|
SYNCHRONIZING = "SYNCHRONIZING",
|
|
14
|
-
/**
|
|
15
|
-
* Checking if we are the proposer for the current slot.
|
|
16
|
-
*/
|
|
10
|
+
/** Checking if we are the proposer for the current slot. */
|
|
17
11
|
PROPOSER_CHECK = "PROPOSER_CHECK",
|
|
18
|
-
/**
|
|
19
|
-
* Initializing the block proposal. Will move to CREATING_BLOCK if there are valid txs to include, or back to SYNCHRONIZING otherwise.
|
|
20
|
-
*/
|
|
12
|
+
/** Initializing the block proposal. Will move to CREATING_BLOCK if there are valid txs to include, or back to SYNCHRONIZING otherwise. */
|
|
21
13
|
INITIALIZING_PROPOSAL = "INITIALIZING_PROPOSAL",
|
|
22
|
-
/**
|
|
23
|
-
* Creating a new L2 block. Includes processing public function calls and running rollup circuits. Will move to PUBLISHING_CONTRACT_DATA.
|
|
24
|
-
*/
|
|
14
|
+
/** Creating a new L2 block. Includes processing public function calls and running rollup circuits. Will move to PUBLISHING_CONTRACT_DATA. */
|
|
25
15
|
CREATING_BLOCK = "CREATING_BLOCK",
|
|
26
|
-
/**
|
|
27
|
-
* Collecting attestations from its peers. Will move to PUBLISHING_BLOCK.
|
|
28
|
-
*/
|
|
16
|
+
/** Collecting attestations from its peers. Will move to PUBLISHING_BLOCK. */
|
|
29
17
|
COLLECTING_ATTESTATIONS = "COLLECTING_ATTESTATIONS",
|
|
30
|
-
/**
|
|
31
|
-
* Sending the tx to L1 with the L2 block data and awaiting it to be mined. Will move to SYNCHRONIZING.
|
|
32
|
-
*/
|
|
18
|
+
/** Sending the tx to L1 with the L2 block data and awaiting it to be mined. Will move to SYNCHRONIZING. */
|
|
33
19
|
PUBLISHING_BLOCK = "PUBLISHING_BLOCK"
|
|
34
20
|
}
|
|
35
21
|
export type SequencerStateWithSlot = SequencerState.INITIALIZING_PROPOSAL | SequencerState.CREATING_BLOCK | SequencerState.COLLECTING_ATTESTATIONS | SequencerState.PUBLISHING_BLOCK | SequencerState.PROPOSER_CHECK;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/sequencer/utils.ts"],"names":[],"mappings":"AAAA,oBAAY,cAAc;IACxB
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/sequencer/utils.ts"],"names":[],"mappings":"AAAA,oBAAY,cAAc;IACxB,qEAAqE;IACrE,OAAO,YAAY;IACnB,gEAAgE;IAChE,QAAQ,aAAa;IACrB,qDAAqD;IACrD,IAAI,SAAS;IACb,uCAAuC;IACvC,aAAa,kBAAkB;IAC/B,4DAA4D;IAC5D,cAAc,mBAAmB;IACjC,0IAA0I;IAC1I,qBAAqB,0BAA0B;IAC/C,6IAA6I;IAC7I,cAAc,mBAAmB;IACjC,6EAA6E;IAC7E,uBAAuB,4BAA4B;IACnD,2GAA2G;IAC3G,gBAAgB,qBAAqB;CACtC;AAED,MAAM,MAAM,sBAAsB,GAC9B,cAAc,CAAC,qBAAqB,GACpC,cAAc,CAAC,cAAc,GAC7B,cAAc,CAAC,uBAAuB,GACtC,cAAc,CAAC,gBAAgB,GAC/B,cAAc,CAAC,cAAc,CAAC;AAElC,MAAM,MAAM,sBAAsB,GAAG,MAAM,cAAc,CAAC;AAE1D,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAEpE"}
|
package/dest/sequencer/utils.js
CHANGED
|
@@ -1,28 +1,13 @@
|
|
|
1
1
|
export var SequencerState = /*#__PURE__*/ function(SequencerState) {
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Checking if we are the proposer for the current slot.
|
|
13
|
-
*/ SequencerState["PROPOSER_CHECK"] = "PROPOSER_CHECK";
|
|
14
|
-
/**
|
|
15
|
-
* Initializing the block proposal. Will move to CREATING_BLOCK if there are valid txs to include, or back to SYNCHRONIZING otherwise.
|
|
16
|
-
*/ SequencerState["INITIALIZING_PROPOSAL"] = "INITIALIZING_PROPOSAL";
|
|
17
|
-
/**
|
|
18
|
-
* Creating a new L2 block. Includes processing public function calls and running rollup circuits. Will move to PUBLISHING_CONTRACT_DATA.
|
|
19
|
-
*/ SequencerState["CREATING_BLOCK"] = "CREATING_BLOCK";
|
|
20
|
-
/**
|
|
21
|
-
* Collecting attestations from its peers. Will move to PUBLISHING_BLOCK.
|
|
22
|
-
*/ SequencerState["COLLECTING_ATTESTATIONS"] = "COLLECTING_ATTESTATIONS";
|
|
23
|
-
/**
|
|
24
|
-
* Sending the tx to L1 with the L2 block data and awaiting it to be mined. Will move to SYNCHRONIZING.
|
|
25
|
-
*/ SequencerState["PUBLISHING_BLOCK"] = "PUBLISHING_BLOCK";
|
|
2
|
+
/** Sequencer is stopped and not processing any txs from the pool. */ SequencerState["STOPPED"] = "STOPPED";
|
|
3
|
+
/** Sequencer is being stopped. Will move to STOPPED shortly. */ SequencerState["STOPPING"] = "STOPPING";
|
|
4
|
+
/** Sequencer is awaiting the next call to work(). */ SequencerState["IDLE"] = "IDLE";
|
|
5
|
+
/** Synchronizing with the L2 chain. */ SequencerState["SYNCHRONIZING"] = "SYNCHRONIZING";
|
|
6
|
+
/** Checking if we are the proposer for the current slot. */ SequencerState["PROPOSER_CHECK"] = "PROPOSER_CHECK";
|
|
7
|
+
/** Initializing the block proposal. Will move to CREATING_BLOCK if there are valid txs to include, or back to SYNCHRONIZING otherwise. */ SequencerState["INITIALIZING_PROPOSAL"] = "INITIALIZING_PROPOSAL";
|
|
8
|
+
/** Creating a new L2 block. Includes processing public function calls and running rollup circuits. Will move to PUBLISHING_CONTRACT_DATA. */ SequencerState["CREATING_BLOCK"] = "CREATING_BLOCK";
|
|
9
|
+
/** Collecting attestations from its peers. Will move to PUBLISHING_BLOCK. */ SequencerState["COLLECTING_ATTESTATIONS"] = "COLLECTING_ATTESTATIONS";
|
|
10
|
+
/** Sending the tx to L1 with the L2 block data and awaiting it to be mined. Will move to SYNCHRONIZING. */ SequencerState["PUBLISHING_BLOCK"] = "PUBLISHING_BLOCK";
|
|
26
11
|
return SequencerState;
|
|
27
12
|
}({});
|
|
28
13
|
export function sequencerStateToNumber(state) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/sequencer-client",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.1.0-rc.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -26,37 +26,37 @@
|
|
|
26
26
|
"test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@aztec/aztec.js": "2.0.
|
|
30
|
-
"@aztec/bb-prover": "2.0.
|
|
31
|
-
"@aztec/blob-lib": "2.0.
|
|
32
|
-
"@aztec/blob-sink": "2.0.
|
|
33
|
-
"@aztec/constants": "2.0.
|
|
34
|
-
"@aztec/epoch-cache": "2.0.
|
|
35
|
-
"@aztec/ethereum": "2.0.
|
|
36
|
-
"@aztec/foundation": "2.0.
|
|
37
|
-
"@aztec/l1-artifacts": "2.0.
|
|
38
|
-
"@aztec/merkle-tree": "2.0.
|
|
39
|
-
"@aztec/
|
|
40
|
-
"@aztec/noir-
|
|
41
|
-
"@aztec/noir-
|
|
42
|
-
"@aztec/noir-types": "2.0.
|
|
43
|
-
"@aztec/
|
|
44
|
-
"@aztec/
|
|
45
|
-
"@aztec/
|
|
46
|
-
"@aztec/
|
|
47
|
-
"@aztec/
|
|
48
|
-
"@aztec/
|
|
49
|
-
"@aztec/
|
|
50
|
-
"@aztec/
|
|
51
|
-
"@aztec/
|
|
29
|
+
"@aztec/aztec.js": "2.1.0-rc.2",
|
|
30
|
+
"@aztec/bb-prover": "2.1.0-rc.2",
|
|
31
|
+
"@aztec/blob-lib": "2.1.0-rc.2",
|
|
32
|
+
"@aztec/blob-sink": "2.1.0-rc.2",
|
|
33
|
+
"@aztec/constants": "2.1.0-rc.2",
|
|
34
|
+
"@aztec/epoch-cache": "2.1.0-rc.2",
|
|
35
|
+
"@aztec/ethereum": "2.1.0-rc.2",
|
|
36
|
+
"@aztec/foundation": "2.1.0-rc.2",
|
|
37
|
+
"@aztec/l1-artifacts": "2.1.0-rc.2",
|
|
38
|
+
"@aztec/merkle-tree": "2.1.0-rc.2",
|
|
39
|
+
"@aztec/node-keystore": "2.1.0-rc.2",
|
|
40
|
+
"@aztec/noir-acvm_js": "2.1.0-rc.2",
|
|
41
|
+
"@aztec/noir-contracts.js": "2.1.0-rc.2",
|
|
42
|
+
"@aztec/noir-protocol-circuits-types": "2.1.0-rc.2",
|
|
43
|
+
"@aztec/noir-types": "2.1.0-rc.2",
|
|
44
|
+
"@aztec/p2p": "2.1.0-rc.2",
|
|
45
|
+
"@aztec/protocol-contracts": "2.1.0-rc.2",
|
|
46
|
+
"@aztec/prover-client": "2.1.0-rc.2",
|
|
47
|
+
"@aztec/simulator": "2.1.0-rc.2",
|
|
48
|
+
"@aztec/slasher": "2.1.0-rc.2",
|
|
49
|
+
"@aztec/stdlib": "2.1.0-rc.2",
|
|
50
|
+
"@aztec/telemetry-client": "2.1.0-rc.2",
|
|
51
|
+
"@aztec/validator-client": "2.1.0-rc.2",
|
|
52
|
+
"@aztec/world-state": "2.1.0-rc.2",
|
|
52
53
|
"lodash.chunk": "^4.2.0",
|
|
53
|
-
"lodash.pick": "^4.4.0",
|
|
54
54
|
"tslib": "^2.4.0",
|
|
55
55
|
"viem": "2.23.7"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@aztec/archiver": "2.0.
|
|
59
|
-
"@aztec/kv-store": "2.0.
|
|
58
|
+
"@aztec/archiver": "2.1.0-rc.2",
|
|
59
|
+
"@aztec/kv-store": "2.1.0-rc.2",
|
|
60
60
|
"@jest/globals": "^30.0.0",
|
|
61
61
|
"@types/jest": "^30.0.0",
|
|
62
62
|
"@types/lodash.chunk": "^4.2.7",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"@types/node": "^22.15.17",
|
|
65
65
|
"concurrently": "^7.6.0",
|
|
66
66
|
"eslint": "^9.26.0",
|
|
67
|
-
"express": "^4.21.
|
|
67
|
+
"express": "^4.21.2",
|
|
68
68
|
"jest": "^30.0.0",
|
|
69
69
|
"jest-mock-extended": "^4.0.0",
|
|
70
70
|
"prettier": "^3.5.3",
|
|
@@ -84,7 +84,7 @@ export class SequencerClient {
|
|
|
84
84
|
telemetry: telemetryClient,
|
|
85
85
|
} = deps;
|
|
86
86
|
const { l1RpcUrls: rpcUrls, l1ChainId: chainId } = config;
|
|
87
|
-
const log = createLogger('sequencer
|
|
87
|
+
const log = createLogger('sequencer');
|
|
88
88
|
const publicClient = getPublicClient(config);
|
|
89
89
|
const l1TxUtils = deps.l1TxUtils;
|
|
90
90
|
const l1Metrics = new L1Metrics(
|
|
@@ -92,7 +92,7 @@ export class SequencerClient {
|
|
|
92
92
|
publicClient,
|
|
93
93
|
l1TxUtils.map(x => x.getSenderAddress()),
|
|
94
94
|
);
|
|
95
|
-
const publisherManager = new PublisherManager(l1TxUtils);
|
|
95
|
+
const publisherManager = new PublisherManager(l1TxUtils, config);
|
|
96
96
|
const rollupContract = new RollupContract(publicClient, config.l1Contracts.rollupAddress.toString());
|
|
97
97
|
const [l1GenesisTime, slotDuration] = await Promise.all([
|
|
98
98
|
rollupContract.getL1GenesisTime(),
|
|
@@ -133,6 +133,7 @@ export class SequencerClient {
|
|
|
133
133
|
dateProvider: deps.dateProvider,
|
|
134
134
|
publisherManager,
|
|
135
135
|
nodeKeyStore: NodeKeystoreAdapter.fromKeyStoreManager(deps.nodeKeyStore),
|
|
136
|
+
logger: log,
|
|
136
137
|
});
|
|
137
138
|
const globalsBuilder = new GlobalVariableBuilder(config);
|
|
138
139
|
|
|
@@ -178,6 +179,7 @@ export class SequencerClient {
|
|
|
178
179
|
rollupContract,
|
|
179
180
|
{ ...config, maxL1TxInclusionTimeIntoSlot, maxL2BlockGas: sequencerManaLimit },
|
|
180
181
|
telemetryClient,
|
|
182
|
+
log,
|
|
181
183
|
);
|
|
182
184
|
|
|
183
185
|
await sequencer.init();
|
|
@@ -200,6 +202,7 @@ export class SequencerClient {
|
|
|
200
202
|
await this.validatorClient?.start();
|
|
201
203
|
this.sequencer.start();
|
|
202
204
|
this.l1Metrics?.start();
|
|
205
|
+
await this.publisherManager.loadState();
|
|
203
206
|
}
|
|
204
207
|
|
|
205
208
|
/**
|
|
@@ -207,6 +210,7 @@ export class SequencerClient {
|
|
|
207
210
|
*/
|
|
208
211
|
public async stop() {
|
|
209
212
|
await this.sequencer.stop();
|
|
213
|
+
await this.validatorClient?.stop();
|
|
210
214
|
this.publisherManager.interrupt();
|
|
211
215
|
this.l1Metrics?.stop();
|
|
212
216
|
}
|
package/src/config.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
pickConfigMappings,
|
|
13
13
|
} from '@aztec/foundation/config';
|
|
14
14
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
15
|
+
import { type KeyStoreConfig, keyStoreConfigMappings } from '@aztec/node-keystore';
|
|
15
16
|
import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p';
|
|
16
17
|
import { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
17
18
|
import { type ChainConfig, type SequencerConfig, chainConfigMappings } from '@aztec/stdlib/config';
|
|
@@ -33,6 +34,7 @@ export const DEFAULT_ATTESTATION_PROPAGATION_TIME = 2;
|
|
|
33
34
|
* Configuration settings for the SequencerClient.
|
|
34
35
|
*/
|
|
35
36
|
export type SequencerClientConfig = PublisherConfig &
|
|
37
|
+
KeyStoreConfig &
|
|
36
38
|
ValidatorClientConfig &
|
|
37
39
|
TxSenderConfig &
|
|
38
40
|
SequencerConfig &
|
|
@@ -149,6 +151,7 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
|
|
|
149
151
|
export const sequencerClientConfigMappings: ConfigMappingsType<SequencerClientConfig> = {
|
|
150
152
|
...validatorClientConfigMappings,
|
|
151
153
|
...sequencerConfigMappings,
|
|
154
|
+
...keyStoreConfigMappings,
|
|
152
155
|
...l1ReaderConfigMappings,
|
|
153
156
|
...getTxSenderConfigMappings('SEQ'),
|
|
154
157
|
...getPublisherConfigMappings('SEQ'),
|
package/src/publisher/config.ts
CHANGED
|
@@ -5,7 +5,12 @@ import {
|
|
|
5
5
|
l1ReaderConfigMappings,
|
|
6
6
|
l1TxUtilsConfigMappings,
|
|
7
7
|
} from '@aztec/ethereum';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
type ConfigMappingsType,
|
|
10
|
+
SecretValue,
|
|
11
|
+
booleanConfigHelper,
|
|
12
|
+
getConfigFromMappings,
|
|
13
|
+
} from '@aztec/foundation/config';
|
|
9
14
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
10
15
|
|
|
11
16
|
/**
|
|
@@ -28,10 +33,8 @@ export type TxSenderConfig = L1ReaderConfig & {
|
|
|
28
33
|
*/
|
|
29
34
|
export type PublisherConfig = L1TxUtilsConfig &
|
|
30
35
|
BlobSinkConfig & {
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
*/
|
|
34
|
-
l1PublishRetryIntervalMS: number;
|
|
36
|
+
/** True to use publishers in invalid states (timed out, cancelled, etc) if no other is available */
|
|
37
|
+
publisherAllowInvalidStates?: boolean;
|
|
35
38
|
};
|
|
36
39
|
|
|
37
40
|
export const getTxSenderConfigMappings: (
|
|
@@ -43,7 +46,7 @@ export const getTxSenderConfigMappings: (
|
|
|
43
46
|
description: 'The private keys to be used by the publisher.',
|
|
44
47
|
parseEnv: (val: string) => val.split(',').map(key => new SecretValue(`0x${key.replace('0x', '')}`)),
|
|
45
48
|
defaultValue: [],
|
|
46
|
-
fallback: scope === 'PROVER' ?
|
|
49
|
+
fallback: [scope === 'PROVER' ? `PROVER_PUBLISHER_PRIVATE_KEY` : `SEQ_PUBLISHER_PRIVATE_KEY`],
|
|
47
50
|
},
|
|
48
51
|
publisherAddresses: {
|
|
49
52
|
env: scope === 'PROVER' ? `PROVER_PUBLISHER_ADDRESSES` : `SEQ_PUBLISHER_ADDRESSES`,
|
|
@@ -60,11 +63,10 @@ export function getTxSenderConfigFromEnv(scope: 'PROVER' | 'SEQ'): Omit<TxSender
|
|
|
60
63
|
export const getPublisherConfigMappings: (
|
|
61
64
|
scope: 'PROVER' | 'SEQ',
|
|
62
65
|
) => ConfigMappingsType<PublisherConfig & L1TxUtilsConfig> = scope => ({
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
description: 'The interval to wait between publish retries.',
|
|
66
|
+
publisherAllowInvalidStates: {
|
|
67
|
+
description: 'True to use publishers in invalid states (timed out, cancelled, etc) if no other is available',
|
|
68
|
+
env: scope === `PROVER` ? `PROVER_PUBLISHER_ALLOW_INVALID_STATES` : `SEQ_PUBLISHER_ALLOW_INVALID_STATES`,
|
|
69
|
+
...booleanConfigHelper(true),
|
|
68
70
|
},
|
|
69
71
|
...l1TxUtilsConfigMappings,
|
|
70
72
|
...blobSinkConfigMapping,
|
package/src/publisher/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EthAddress } from '@aztec/aztec.js';
|
|
1
|
+
import { EthAddress, type Logger, createLogger } from '@aztec/aztec.js';
|
|
2
2
|
import type { BlobSinkClientInterface } from '@aztec/blob-sink/client';
|
|
3
3
|
import type { EpochCache } from '@aztec/epoch-cache';
|
|
4
4
|
import type { GovernanceProposerContract, PublisherFilter, PublisherManager, RollupContract } from '@aztec/ethereum';
|
|
@@ -10,7 +10,7 @@ import { NodeKeystoreAdapter } from '@aztec/validator-client';
|
|
|
10
10
|
|
|
11
11
|
import type { SequencerClientConfig } from '../config.js';
|
|
12
12
|
import { SequencerPublisherMetrics } from './sequencer-publisher-metrics.js';
|
|
13
|
-
import { SequencerPublisher } from './sequencer-publisher.js';
|
|
13
|
+
import { type Action, SequencerPublisher } from './sequencer-publisher.js';
|
|
14
14
|
|
|
15
15
|
export type AttestorPublisherPair = {
|
|
16
16
|
attestorAddress: EthAddress;
|
|
@@ -19,6 +19,12 @@ export type AttestorPublisherPair = {
|
|
|
19
19
|
|
|
20
20
|
export class SequencerPublisherFactory {
|
|
21
21
|
private publisherMetrics: SequencerPublisherMetrics;
|
|
22
|
+
|
|
23
|
+
/** Stores the last slot in which every action was carried out by a publisher */
|
|
24
|
+
private lastActions: Partial<Record<Action, bigint>> = {};
|
|
25
|
+
|
|
26
|
+
private logger: Logger;
|
|
27
|
+
|
|
22
28
|
constructor(
|
|
23
29
|
private sequencerConfig: SequencerClientConfig,
|
|
24
30
|
private deps: {
|
|
@@ -31,9 +37,11 @@ export class SequencerPublisherFactory {
|
|
|
31
37
|
governanceProposerContract: GovernanceProposerContract;
|
|
32
38
|
slashFactoryContract: SlashFactoryContract;
|
|
33
39
|
nodeKeyStore: NodeKeystoreAdapter;
|
|
40
|
+
logger?: Logger;
|
|
34
41
|
},
|
|
35
42
|
) {
|
|
36
43
|
this.publisherMetrics = new SequencerPublisherMetrics(deps.telemetry, 'SequencerPublisher');
|
|
44
|
+
this.logger = deps.logger ?? createLogger('sequencer');
|
|
37
45
|
}
|
|
38
46
|
/**
|
|
39
47
|
* Creates a new SequencerPublisher instance.
|
|
@@ -69,6 +77,8 @@ export class SequencerPublisherFactory {
|
|
|
69
77
|
slashFactoryContract: this.deps.slashFactoryContract,
|
|
70
78
|
dateProvider: this.deps.dateProvider,
|
|
71
79
|
metrics: this.publisherMetrics,
|
|
80
|
+
lastActions: this.lastActions,
|
|
81
|
+
log: this.logger.createChild('publisher'),
|
|
72
82
|
});
|
|
73
83
|
|
|
74
84
|
return {
|