@aztec/sequencer-client 0.0.1-commit.6d3c34e → 0.0.1-commit.9372f48
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.js +1 -1
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +1 -3
- package/dest/global_variable_builder/global_builder.js +2 -2
- package/dest/index.d.ts +2 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -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 +12 -4
- package/dest/publisher/sequencer-publisher.d.ts +1 -2
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +39 -18
- package/dest/sequencer/checkpoint_proposal_job.d.ts +28 -9
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +134 -31
- package/dest/sequencer/checkpoint_voter.d.ts +3 -2
- package/dest/sequencer/checkpoint_voter.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_voter.js +34 -10
- package/dest/sequencer/index.d.ts +1 -2
- package/dest/sequencer/index.d.ts.map +1 -1
- package/dest/sequencer/index.js +0 -1
- package/dest/sequencer/metrics.d.ts +2 -2
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +27 -17
- package/dest/sequencer/sequencer.d.ts +17 -9
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +67 -11
- package/dest/test/mock_checkpoint_builder.d.ts +17 -13
- package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.js +28 -10
- package/dest/test/utils.d.ts +8 -8
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +7 -7
- package/package.json +30 -28
- package/src/client/sequencer-client.ts +1 -1
- package/src/config.ts +1 -3
- package/src/global_variable_builder/global_builder.ts +2 -2
- package/src/index.ts +1 -6
- package/src/publisher/sequencer-publisher-metrics.ts +7 -3
- package/src/publisher/sequencer-publisher.ts +34 -18
- package/src/sequencer/checkpoint_proposal_job.ts +183 -51
- package/src/sequencer/checkpoint_voter.ts +32 -7
- package/src/sequencer/index.ts +0 -1
- package/src/sequencer/metrics.ts +36 -18
- package/src/sequencer/sequencer.ts +82 -10
- package/src/test/mock_checkpoint_builder.ts +64 -34
- package/src/test/utils.ts +19 -12
- package/dest/sequencer/block_builder.d.ts +0 -26
- package/dest/sequencer/block_builder.d.ts.map +0 -1
- package/dest/sequencer/block_builder.js +0 -129
- package/src/sequencer/block_builder.ts +0 -216
|
@@ -12,7 +12,7 @@ import type { DateProvider } from '@aztec/foundation/timer';
|
|
|
12
12
|
import type { TypedEventEmitter } from '@aztec/foundation/types';
|
|
13
13
|
import type { P2P } from '@aztec/p2p';
|
|
14
14
|
import type { SlasherClientInterface } from '@aztec/slasher';
|
|
15
|
-
import type {
|
|
15
|
+
import type { L2Block, L2BlockSink, L2BlockSource, ValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
16
16
|
import type { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
17
17
|
import { getSlotAtTimestamp, getSlotStartBuildTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
18
18
|
import {
|
|
@@ -57,8 +57,8 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
57
57
|
private state = SequencerState.STOPPED;
|
|
58
58
|
private metrics: SequencerMetrics;
|
|
59
59
|
|
|
60
|
-
/** The last slot for which we attempted to
|
|
61
|
-
private
|
|
60
|
+
/** The last slot for which we attempted to perform our voting duties with degraded block production */
|
|
61
|
+
private lastSlotForFallbackVote: SlotNumber | undefined;
|
|
62
62
|
|
|
63
63
|
/** The last slot for which we triggered a checkpoint proposal job, to prevent duplicate attempts. */
|
|
64
64
|
private lastSlotForCheckpointProposalJob: SlotNumber | undefined;
|
|
@@ -202,7 +202,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
202
202
|
const { slot, ts, now, epoch } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
203
203
|
|
|
204
204
|
// Check if we are synced and it's our slot, grab a publisher, check previous block invalidation, etc
|
|
205
|
-
const checkpointProposalJob = await this.prepareCheckpointProposal(slot, ts, now);
|
|
205
|
+
const checkpointProposalJob = await this.prepareCheckpointProposal(epoch, slot, ts, now);
|
|
206
206
|
if (!checkpointProposalJob) {
|
|
207
207
|
return;
|
|
208
208
|
}
|
|
@@ -234,6 +234,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
234
234
|
*/
|
|
235
235
|
@trackSpan('Sequencer.prepareCheckpointProposal')
|
|
236
236
|
private async prepareCheckpointProposal(
|
|
237
|
+
epoch: EpochNumber,
|
|
237
238
|
slot: SlotNumber,
|
|
238
239
|
ts: bigint,
|
|
239
240
|
now: bigint,
|
|
@@ -263,6 +264,25 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
263
264
|
return undefined;
|
|
264
265
|
}
|
|
265
266
|
|
|
267
|
+
// If escape hatch is open for this epoch, do not start checkpoint proposal work and do not attempt invalidations.
|
|
268
|
+
// Still perform governance/slashing voting (as proposer) once per slot.
|
|
269
|
+
const isEscapeHatchOpen = await this.epochCache.isEscapeHatchOpen(epoch);
|
|
270
|
+
|
|
271
|
+
if (isEscapeHatchOpen) {
|
|
272
|
+
this.setState(SequencerState.PROPOSER_CHECK, slot);
|
|
273
|
+
const [canPropose, proposer] = await this.checkCanPropose(slot);
|
|
274
|
+
if (canPropose) {
|
|
275
|
+
await this.tryVoteWhenEscapeHatchOpen({ slot, proposer });
|
|
276
|
+
} else {
|
|
277
|
+
this.log.trace(`Escape hatch open but we are not proposer, skipping vote-only actions`, {
|
|
278
|
+
slot,
|
|
279
|
+
epoch,
|
|
280
|
+
proposer,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
return undefined;
|
|
284
|
+
}
|
|
285
|
+
|
|
266
286
|
// Next checkpoint follows from the last synced one
|
|
267
287
|
const checkpointNumber = CheckpointNumber(syncedTo.checkpointNumber + 1);
|
|
268
288
|
|
|
@@ -357,6 +377,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
357
377
|
|
|
358
378
|
// Create and return the checkpoint proposal job
|
|
359
379
|
return this.createCheckpointProposalJob(
|
|
380
|
+
epoch,
|
|
360
381
|
slot,
|
|
361
382
|
checkpointNumber,
|
|
362
383
|
syncedTo.blockNumber,
|
|
@@ -368,6 +389,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
368
389
|
}
|
|
369
390
|
|
|
370
391
|
protected createCheckpointProposalJob(
|
|
392
|
+
epoch: EpochNumber,
|
|
371
393
|
slot: SlotNumber,
|
|
372
394
|
checkpointNumber: CheckpointNumber,
|
|
373
395
|
syncedToBlockNumber: BlockNumber,
|
|
@@ -377,6 +399,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
377
399
|
invalidateCheckpoint: InvalidateCheckpointRequest | undefined,
|
|
378
400
|
): CheckpointProposalJob {
|
|
379
401
|
return new CheckpointProposalJob(
|
|
402
|
+
epoch,
|
|
380
403
|
slot,
|
|
381
404
|
checkpointNumber,
|
|
382
405
|
syncedToBlockNumber,
|
|
@@ -389,6 +412,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
389
412
|
this.p2pClient,
|
|
390
413
|
this.worldState,
|
|
391
414
|
this.l1ToL2MessageSource,
|
|
415
|
+
this.l2BlockSource,
|
|
392
416
|
this.checkpointsBuilder,
|
|
393
417
|
this.l2BlockSource,
|
|
394
418
|
this.l1Constants,
|
|
@@ -400,8 +424,8 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
400
424
|
this.metrics,
|
|
401
425
|
this,
|
|
402
426
|
this.setState.bind(this),
|
|
403
|
-
this.log,
|
|
404
427
|
this.tracer,
|
|
428
|
+
this.log.getBindings(),
|
|
405
429
|
);
|
|
406
430
|
}
|
|
407
431
|
|
|
@@ -505,7 +529,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
505
529
|
};
|
|
506
530
|
}
|
|
507
531
|
|
|
508
|
-
const block = await this.l2BlockSource.
|
|
532
|
+
const block = await this.l2BlockSource.getL2Block(blockNumber);
|
|
509
533
|
if (!block) {
|
|
510
534
|
// this shouldn't really happen because a moment ago we checked that all components were in sync
|
|
511
535
|
this.log.error(`Failed to get L2 block ${blockNumber} from the archiver with all components in sync`);
|
|
@@ -569,7 +593,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
569
593
|
const { slot } = args;
|
|
570
594
|
|
|
571
595
|
// Prevent duplicate attempts in the same slot
|
|
572
|
-
if (this.
|
|
596
|
+
if (this.lastSlotForFallbackVote === slot) {
|
|
573
597
|
this.log.trace(`Already attempted to vote in slot ${slot} (skipping)`);
|
|
574
598
|
return;
|
|
575
599
|
}
|
|
@@ -601,7 +625,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
601
625
|
}
|
|
602
626
|
|
|
603
627
|
// Mark this slot as attempted
|
|
604
|
-
this.
|
|
628
|
+
this.lastSlotForFallbackVote = slot;
|
|
605
629
|
|
|
606
630
|
// Get a publisher for voting
|
|
607
631
|
const { attestorAddress, publisher } = await this.publisherFactory.create(proposer);
|
|
@@ -636,7 +660,55 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
636
660
|
}
|
|
637
661
|
|
|
638
662
|
/**
|
|
639
|
-
*
|
|
663
|
+
* Tries to vote on slashing actions and governance proposals when escape hatch is open.
|
|
664
|
+
* This allows the sequencer to participate in voting without performing checkpoint proposal work.
|
|
665
|
+
*/
|
|
666
|
+
@trackSpan('Sequencer.tryVoteWhenEscapeHatchOpen', ({ slot }) => ({ [Attributes.SLOT_NUMBER]: slot }))
|
|
667
|
+
protected async tryVoteWhenEscapeHatchOpen(args: {
|
|
668
|
+
slot: SlotNumber;
|
|
669
|
+
proposer: EthAddress | undefined;
|
|
670
|
+
}): Promise<void> {
|
|
671
|
+
const { slot, proposer } = args;
|
|
672
|
+
|
|
673
|
+
// Prevent duplicate attempts in the same slot
|
|
674
|
+
if (this.lastSlotForFallbackVote === slot) {
|
|
675
|
+
this.log.trace(`Already attempted to vote in slot ${slot} (escape hatch open, skipping)`);
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// Mark this slot as attempted
|
|
680
|
+
this.lastSlotForFallbackVote = slot;
|
|
681
|
+
|
|
682
|
+
const { attestorAddress, publisher } = await this.publisherFactory.create(proposer);
|
|
683
|
+
|
|
684
|
+
this.log.debug(`Escape hatch open for slot ${slot}, attempting vote-only actions`, { slot, attestorAddress });
|
|
685
|
+
|
|
686
|
+
const voter = new CheckpointVoter(
|
|
687
|
+
slot,
|
|
688
|
+
publisher,
|
|
689
|
+
attestorAddress,
|
|
690
|
+
this.validatorClient,
|
|
691
|
+
this.slasherClient,
|
|
692
|
+
this.l1Constants,
|
|
693
|
+
this.config,
|
|
694
|
+
this.metrics,
|
|
695
|
+
this.log,
|
|
696
|
+
);
|
|
697
|
+
|
|
698
|
+
const votesPromises = voter.enqueueVotes();
|
|
699
|
+
const votes = await Promise.all(votesPromises);
|
|
700
|
+
|
|
701
|
+
if (votes.every(p => !p)) {
|
|
702
|
+
this.log.debug(`No votes to enqueue for slot ${slot} (escape hatch open)`);
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
this.log.info(`Voting in slot ${slot} (escape hatch open)`, { slot });
|
|
707
|
+
await publisher.sendRequests();
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Considers invalidating a block if the pending chain is invalid. Depends on how long the invalid block
|
|
640
712
|
* has been there without being invalidated and whether the sequencer is in the committee or not. We always
|
|
641
713
|
* have the proposer try to invalidate, but if they fail, the sequencers in the committee are expected to try,
|
|
642
714
|
* and if they fail, any sequencer will try as well.
|
|
@@ -798,7 +870,7 @@ export class Sequencer extends (EventEmitter as new () => TypedEventEmitter<Sequ
|
|
|
798
870
|
}
|
|
799
871
|
|
|
800
872
|
type SequencerSyncCheckResult = {
|
|
801
|
-
block?:
|
|
873
|
+
block?: L2Block;
|
|
802
874
|
checkpointNumber: CheckpointNumber;
|
|
803
875
|
blockNumber: BlockNumber;
|
|
804
876
|
archive: Fr;
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import { type BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
|
-
import {
|
|
4
|
-
import type { FunctionsOf } from '@aztec/foundation/types';
|
|
5
|
-
import { L2BlockNew } from '@aztec/stdlib/block';
|
|
3
|
+
import { L2Block } from '@aztec/stdlib/block';
|
|
6
4
|
import { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
7
5
|
import { Gas } from '@aztec/stdlib/gas';
|
|
8
|
-
import type {
|
|
6
|
+
import type {
|
|
7
|
+
FullNodeBlockBuilderConfig,
|
|
8
|
+
ICheckpointBlockBuilder,
|
|
9
|
+
ICheckpointsBuilder,
|
|
10
|
+
MerkleTreeWriteOperations,
|
|
11
|
+
PublicProcessorLimits,
|
|
12
|
+
} from '@aztec/stdlib/interfaces/server';
|
|
9
13
|
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
10
14
|
import { makeAppendOnlyTreeSnapshot } from '@aztec/stdlib/testing';
|
|
11
15
|
import type { CheckpointGlobalVariables, Tx } from '@aztec/stdlib/tx';
|
|
12
|
-
import type {
|
|
13
|
-
BuildBlockInCheckpointResult,
|
|
14
|
-
CheckpointBuilder,
|
|
15
|
-
FullNodeCheckpointsBuilder,
|
|
16
|
-
} from '@aztec/validator-client';
|
|
16
|
+
import type { BuildBlockInCheckpointResult } from '@aztec/validator-client';
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* A fake CheckpointBuilder for testing that implements the same interface as the real one.
|
|
20
20
|
* Can be seeded with blocks to return sequentially on each `buildBlock` call.
|
|
21
21
|
*/
|
|
22
|
-
export class MockCheckpointBuilder implements
|
|
23
|
-
private blocks:
|
|
24
|
-
private builtBlocks:
|
|
22
|
+
export class MockCheckpointBuilder implements ICheckpointBlockBuilder {
|
|
23
|
+
private blocks: L2Block[] = [];
|
|
24
|
+
private builtBlocks: L2Block[] = [];
|
|
25
25
|
private usedTxsPerBlock: Tx[][] = [];
|
|
26
26
|
private blockIndex = 0;
|
|
27
27
|
|
|
28
28
|
/** Optional function to dynamically provide the block (alternative to seedBlocks) */
|
|
29
|
-
private blockProvider: (() =>
|
|
29
|
+
private blockProvider: (() => L2Block) | undefined = undefined;
|
|
30
30
|
|
|
31
31
|
/** Track calls for assertions */
|
|
32
32
|
public buildBlockCalls: Array<{
|
|
@@ -34,6 +34,8 @@ export class MockCheckpointBuilder implements FunctionsOf<CheckpointBuilder> {
|
|
|
34
34
|
timestamp: bigint;
|
|
35
35
|
opts: PublicProcessorLimits;
|
|
36
36
|
}> = [];
|
|
37
|
+
/** Track all consumed transaction hashes across buildBlock calls */
|
|
38
|
+
public consumedTxHashes: Set<string> = new Set();
|
|
37
39
|
public completeCheckpointCalled = false;
|
|
38
40
|
public getCheckpointCalled = false;
|
|
39
41
|
|
|
@@ -46,7 +48,7 @@ export class MockCheckpointBuilder implements FunctionsOf<CheckpointBuilder> {
|
|
|
46
48
|
) {}
|
|
47
49
|
|
|
48
50
|
/** Seed the builder with blocks to return on successive buildBlock calls */
|
|
49
|
-
seedBlocks(blocks:
|
|
51
|
+
seedBlocks(blocks: L2Block[], usedTxsPerBlock?: Tx[][]): this {
|
|
50
52
|
this.blocks = blocks;
|
|
51
53
|
this.usedTxsPerBlock = usedTxsPerBlock ?? blocks.map(() => []);
|
|
52
54
|
this.blockIndex = 0;
|
|
@@ -58,7 +60,7 @@ export class MockCheckpointBuilder implements FunctionsOf<CheckpointBuilder> {
|
|
|
58
60
|
* Set a function that provides blocks dynamically.
|
|
59
61
|
* Useful for tests where the block is determined at call time (e.g., sequencer tests).
|
|
60
62
|
*/
|
|
61
|
-
setBlockProvider(provider: () =>
|
|
63
|
+
setBlockProvider(provider: () => L2Block): this {
|
|
62
64
|
this.blockProvider = provider;
|
|
63
65
|
this.blocks = [];
|
|
64
66
|
return this;
|
|
@@ -68,8 +70,8 @@ export class MockCheckpointBuilder implements FunctionsOf<CheckpointBuilder> {
|
|
|
68
70
|
return this.constants;
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
buildBlock(
|
|
72
|
-
|
|
73
|
+
async buildBlock(
|
|
74
|
+
pendingTxs: Iterable<Tx> | AsyncIterable<Tx>,
|
|
73
75
|
blockNumber: BlockNumber,
|
|
74
76
|
timestamp: bigint,
|
|
75
77
|
opts: PublicProcessorLimits,
|
|
@@ -77,10 +79,10 @@ export class MockCheckpointBuilder implements FunctionsOf<CheckpointBuilder> {
|
|
|
77
79
|
this.buildBlockCalls.push({ blockNumber, timestamp, opts });
|
|
78
80
|
|
|
79
81
|
if (this.errorOnBuild) {
|
|
80
|
-
|
|
82
|
+
throw this.errorOnBuild;
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
let block:
|
|
85
|
+
let block: L2Block;
|
|
84
86
|
let usedTxs: Tx[];
|
|
85
87
|
|
|
86
88
|
if (this.blockProvider) {
|
|
@@ -96,15 +98,28 @@ export class MockCheckpointBuilder implements FunctionsOf<CheckpointBuilder> {
|
|
|
96
98
|
this.builtBlocks.push(block);
|
|
97
99
|
}
|
|
98
100
|
|
|
99
|
-
|
|
101
|
+
// Check that no pending tx has already been consumed
|
|
102
|
+
for await (const tx of pendingTxs) {
|
|
103
|
+
const hash = tx.getTxHash().toString();
|
|
104
|
+
if (this.consumedTxHashes.has(hash)) {
|
|
105
|
+
throw new Error(`Transaction ${hash} was already consumed in a previous block`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Add used txs to consumed set
|
|
110
|
+
for (const tx of usedTxs) {
|
|
111
|
+
this.consumedTxHashes.add(tx.getTxHash().toString());
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
100
115
|
block,
|
|
101
116
|
publicGas: Gas.empty(),
|
|
102
117
|
publicProcessorDuration: 0,
|
|
103
118
|
numTxs: block?.body?.txEffects?.length ?? usedTxs.length,
|
|
104
|
-
blockBuildingTimer: new Timer(),
|
|
105
119
|
usedTxs,
|
|
106
120
|
failedTxs: [],
|
|
107
|
-
|
|
121
|
+
usedTxBlobFields: block?.body?.txEffects?.reduce((sum, tx) => sum + tx.getNumBlobFields(), 0) ?? 0,
|
|
122
|
+
};
|
|
108
123
|
}
|
|
109
124
|
|
|
110
125
|
completeCheckpoint(): Promise<Checkpoint> {
|
|
@@ -146,7 +161,7 @@ export class MockCheckpointBuilder implements FunctionsOf<CheckpointBuilder> {
|
|
|
146
161
|
* Creates a CheckpointHeader from a block's header for testing.
|
|
147
162
|
* This is a simplified version that creates a minimal CheckpointHeader.
|
|
148
163
|
*/
|
|
149
|
-
private createCheckpointHeader(block:
|
|
164
|
+
private createCheckpointHeader(block: L2Block): CheckpointHeader {
|
|
150
165
|
const header = block.header;
|
|
151
166
|
const gv = header.globalVariables;
|
|
152
167
|
return CheckpointHeader.empty({
|
|
@@ -168,6 +183,7 @@ export class MockCheckpointBuilder implements FunctionsOf<CheckpointBuilder> {
|
|
|
168
183
|
this.usedTxsPerBlock = [];
|
|
169
184
|
this.blockIndex = 0;
|
|
170
185
|
this.buildBlockCalls = [];
|
|
186
|
+
this.consumedTxHashes.clear();
|
|
171
187
|
this.completeCheckpointCalled = false;
|
|
172
188
|
this.getCheckpointCalled = false;
|
|
173
189
|
this.errorOnBuild = undefined;
|
|
@@ -180,7 +196,7 @@ export class MockCheckpointBuilder implements FunctionsOf<CheckpointBuilder> {
|
|
|
180
196
|
* as FullNodeCheckpointsBuilder. Returns MockCheckpointBuilder instances.
|
|
181
197
|
* Does NOT use jest mocks - this is a proper test double.
|
|
182
198
|
*/
|
|
183
|
-
export class MockCheckpointsBuilder implements
|
|
199
|
+
export class MockCheckpointsBuilder implements ICheckpointsBuilder {
|
|
184
200
|
private checkpointBuilder: MockCheckpointBuilder | undefined;
|
|
185
201
|
|
|
186
202
|
/** Track calls for assertions */
|
|
@@ -188,12 +204,14 @@ export class MockCheckpointsBuilder implements FunctionsOf<FullNodeCheckpointsBu
|
|
|
188
204
|
checkpointNumber: CheckpointNumber;
|
|
189
205
|
constants: CheckpointGlobalVariables;
|
|
190
206
|
l1ToL2Messages: Fr[];
|
|
207
|
+
previousCheckpointOutHashes: Fr[];
|
|
191
208
|
}> = [];
|
|
192
209
|
public openCheckpointCalls: Array<{
|
|
193
210
|
checkpointNumber: CheckpointNumber;
|
|
194
211
|
constants: CheckpointGlobalVariables;
|
|
195
212
|
l1ToL2Messages: Fr[];
|
|
196
|
-
|
|
213
|
+
previousCheckpointOutHashes: Fr[];
|
|
214
|
+
existingBlocks: L2Block[];
|
|
197
215
|
}> = [];
|
|
198
216
|
public updateConfigCalls: Array<Partial<FullNodeBlockBuilderConfig>> = [];
|
|
199
217
|
|
|
@@ -240,33 +258,45 @@ export class MockCheckpointsBuilder implements FunctionsOf<FullNodeCheckpointsBu
|
|
|
240
258
|
checkpointNumber: CheckpointNumber,
|
|
241
259
|
constants: CheckpointGlobalVariables,
|
|
242
260
|
l1ToL2Messages: Fr[],
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
261
|
+
previousCheckpointOutHashes: Fr[],
|
|
262
|
+
_fork: MerkleTreeWriteOperations,
|
|
263
|
+
): Promise<ICheckpointBlockBuilder> {
|
|
264
|
+
this.startCheckpointCalls.push({ checkpointNumber, constants, l1ToL2Messages, previousCheckpointOutHashes });
|
|
246
265
|
|
|
247
266
|
if (!this.checkpointBuilder) {
|
|
248
267
|
// Auto-create a builder if none was set
|
|
249
268
|
this.checkpointBuilder = new MockCheckpointBuilder(constants, checkpointNumber);
|
|
250
269
|
}
|
|
251
270
|
|
|
252
|
-
return Promise.resolve(this.checkpointBuilder
|
|
271
|
+
return Promise.resolve(this.checkpointBuilder);
|
|
253
272
|
}
|
|
254
273
|
|
|
255
274
|
openCheckpoint(
|
|
256
275
|
checkpointNumber: CheckpointNumber,
|
|
257
276
|
constants: CheckpointGlobalVariables,
|
|
258
277
|
l1ToL2Messages: Fr[],
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
278
|
+
previousCheckpointOutHashes: Fr[],
|
|
279
|
+
_fork: MerkleTreeWriteOperations,
|
|
280
|
+
existingBlocks: L2Block[] = [],
|
|
281
|
+
): Promise<ICheckpointBlockBuilder> {
|
|
282
|
+
this.openCheckpointCalls.push({
|
|
283
|
+
checkpointNumber,
|
|
284
|
+
constants,
|
|
285
|
+
l1ToL2Messages,
|
|
286
|
+
previousCheckpointOutHashes,
|
|
287
|
+
existingBlocks,
|
|
288
|
+
});
|
|
263
289
|
|
|
264
290
|
if (!this.checkpointBuilder) {
|
|
265
291
|
// Auto-create a builder if none was set
|
|
266
292
|
this.checkpointBuilder = new MockCheckpointBuilder(constants, checkpointNumber);
|
|
267
293
|
}
|
|
268
294
|
|
|
269
|
-
return Promise.resolve(this.checkpointBuilder
|
|
295
|
+
return Promise.resolve(this.checkpointBuilder);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
getFork(_blockNumber: BlockNumber): Promise<MerkleTreeWriteOperations> {
|
|
299
|
+
throw new Error('MockCheckpointsBuilder.getFork not implemented');
|
|
270
300
|
}
|
|
271
301
|
|
|
272
302
|
/** Reset for reuse in another test */
|
package/src/test/utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Body } from '@aztec/aztec.js/block';
|
|
2
|
-
import { CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { CheckpointNumber, IndexWithinCheckpoint } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { times } from '@aztec/foundation/collection';
|
|
4
4
|
import { Secp256k1Signer } from '@aztec/foundation/crypto/secp256k1-signer';
|
|
5
5
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
@@ -7,7 +7,7 @@ import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
|
7
7
|
import { Signature } from '@aztec/foundation/eth-signature';
|
|
8
8
|
import type { P2P } from '@aztec/p2p';
|
|
9
9
|
import { PublicDataWrite } from '@aztec/stdlib/avm';
|
|
10
|
-
import { CommitteeAttestation,
|
|
10
|
+
import { CommitteeAttestation, L2Block } from '@aztec/stdlib/block';
|
|
11
11
|
import { BlockProposal, CheckpointAttestation, CheckpointProposal, ConsensusPayload } from '@aztec/stdlib/p2p';
|
|
12
12
|
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
13
13
|
import { makeAppendOnlyTreeSnapshot, mockTxForRollup } from '@aztec/stdlib/testing';
|
|
@@ -30,9 +30,9 @@ export async function makeTx(seed?: number, chainId?: Fr): Promise<Tx> {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* Creates an
|
|
33
|
+
* Creates an L2Block from transactions and global variables
|
|
34
34
|
*/
|
|
35
|
-
export async function makeBlock(txs: Tx[], globalVariables: GlobalVariables): Promise<
|
|
35
|
+
export async function makeBlock(txs: Tx[], globalVariables: GlobalVariables): Promise<L2Block> {
|
|
36
36
|
const processedTxs = await Promise.all(
|
|
37
37
|
txs.map(tx =>
|
|
38
38
|
makeProcessedTxFromPrivateOnlyTx(tx, Fr.ZERO, new PublicDataWrite(Fr.random(), Fr.random()), globalVariables),
|
|
@@ -41,7 +41,13 @@ export async function makeBlock(txs: Tx[], globalVariables: GlobalVariables): Pr
|
|
|
41
41
|
const body = new Body(processedTxs.map(tx => tx.txEffect));
|
|
42
42
|
const header = BlockHeader.empty({ globalVariables });
|
|
43
43
|
const archive = makeAppendOnlyTreeSnapshot(globalVariables.blockNumber + 1);
|
|
44
|
-
return new
|
|
44
|
+
return new L2Block(
|
|
45
|
+
archive,
|
|
46
|
+
header,
|
|
47
|
+
body,
|
|
48
|
+
CheckpointNumber.fromBlockNumber(globalVariables.blockNumber),
|
|
49
|
+
IndexWithinCheckpoint(0),
|
|
50
|
+
);
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
/**
|
|
@@ -70,16 +76,17 @@ export function createMockSignatures(signer: Secp256k1Signer): CommitteeAttestat
|
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
/**
|
|
73
|
-
* Creates a CheckpointHeader from an
|
|
74
|
-
* Uses mock values for blockHeadersHash, blobsHash and inHash since
|
|
79
|
+
* Creates a CheckpointHeader from an L2Block for testing purposes.
|
|
80
|
+
* Uses mock values for blockHeadersHash, blobsHash and inHash since L2Block doesn't have these fields.
|
|
75
81
|
*/
|
|
76
|
-
function createCheckpointHeaderFromBlock(block:
|
|
82
|
+
function createCheckpointHeaderFromBlock(block: L2Block): CheckpointHeader {
|
|
77
83
|
const gv = block.header.globalVariables;
|
|
78
84
|
return new CheckpointHeader(
|
|
79
85
|
block.header.lastArchive.root,
|
|
80
86
|
Fr.random(), // blockHeadersHash - mock value for testing
|
|
81
87
|
Fr.random(), // blobsHash - mock value for testing
|
|
82
88
|
Fr.random(), // inHash - mock value for testing
|
|
89
|
+
Fr.random(), // outHash - mock value for testing
|
|
83
90
|
gv.slotNumber,
|
|
84
91
|
gv.timestamp,
|
|
85
92
|
gv.coinbase,
|
|
@@ -92,7 +99,7 @@ function createCheckpointHeaderFromBlock(block: L2BlockNew): CheckpointHeader {
|
|
|
92
99
|
/**
|
|
93
100
|
* Creates a block proposal from a block and signature
|
|
94
101
|
*/
|
|
95
|
-
export function createBlockProposal(block:
|
|
102
|
+
export function createBlockProposal(block: L2Block, signature: Signature): BlockProposal {
|
|
96
103
|
const txHashes = block.body.txEffects.map(tx => tx.txHash);
|
|
97
104
|
return new BlockProposal(
|
|
98
105
|
block.header,
|
|
@@ -108,7 +115,7 @@ export function createBlockProposal(block: L2BlockNew, signature: Signature): Bl
|
|
|
108
115
|
* Creates a checkpoint proposal from a block and signature
|
|
109
116
|
*/
|
|
110
117
|
export function createCheckpointProposal(
|
|
111
|
-
block:
|
|
118
|
+
block: L2Block,
|
|
112
119
|
checkpointSignature: Signature,
|
|
113
120
|
blockSignature?: Signature,
|
|
114
121
|
): CheckpointProposal {
|
|
@@ -128,7 +135,7 @@ export function createCheckpointProposal(
|
|
|
128
135
|
* In production, the sender is recovered from the signature.
|
|
129
136
|
*/
|
|
130
137
|
export function createCheckpointAttestation(
|
|
131
|
-
block:
|
|
138
|
+
block: L2Block,
|
|
132
139
|
signature: Signature,
|
|
133
140
|
sender: EthAddress,
|
|
134
141
|
): CheckpointAttestation {
|
|
@@ -149,7 +156,7 @@ export async function setupTxsAndBlock(
|
|
|
149
156
|
globalVariables: GlobalVariables,
|
|
150
157
|
txCount: number,
|
|
151
158
|
chainId: Fr,
|
|
152
|
-
): Promise<{ txs: Tx[]; block:
|
|
159
|
+
): Promise<{ txs: Tx[]; block: L2Block }> {
|
|
153
160
|
const txs = await Promise.all(times(txCount, i => makeTx(i + 1, chainId)));
|
|
154
161
|
const block = await makeBlock(txs, globalVariables);
|
|
155
162
|
mockPendingTxs(p2p, txs);
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
2
|
-
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
|
-
import { DateProvider } from '@aztec/foundation/timer';
|
|
4
|
-
import { PublicProcessor } from '@aztec/simulator/server';
|
|
5
|
-
import type { ContractDataSource } from '@aztec/stdlib/contract';
|
|
6
|
-
import type { BuildBlockResult, FullNodeBlockBuilderConfig, IFullNodeBlockBuilder, MerkleTreeWriteOperations, PublicProcessorLimits, PublicProcessorValidator, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
7
|
-
import { GlobalVariables, Tx } from '@aztec/stdlib/tx';
|
|
8
|
-
import { type TelemetryClient } from '@aztec/telemetry-client';
|
|
9
|
-
export declare class FullNodeBlockBuilder implements IFullNodeBlockBuilder {
|
|
10
|
-
private config;
|
|
11
|
-
private worldState;
|
|
12
|
-
private contractDataSource;
|
|
13
|
-
private dateProvider;
|
|
14
|
-
private telemetryClient;
|
|
15
|
-
constructor(config: FullNodeBlockBuilderConfig, worldState: WorldStateSynchronizer, contractDataSource: ContractDataSource, dateProvider: DateProvider, telemetryClient?: TelemetryClient);
|
|
16
|
-
getConfig(): FullNodeBlockBuilderConfig;
|
|
17
|
-
updateConfig(config: Partial<FullNodeBlockBuilderConfig>): void;
|
|
18
|
-
makeBlockBuilderDeps(globalVariables: GlobalVariables, fork: MerkleTreeWriteOperations): Promise<{
|
|
19
|
-
processor: PublicProcessor;
|
|
20
|
-
validator: PublicProcessorValidator;
|
|
21
|
-
}>;
|
|
22
|
-
private syncToPreviousBlock;
|
|
23
|
-
buildBlock(pendingTxs: Iterable<Tx> | AsyncIterable<Tx>, l1ToL2Messages: Fr[], globalVariables: GlobalVariables, opts: PublicProcessorLimits, suppliedFork?: MerkleTreeWriteOperations): Promise<BuildBlockResult>;
|
|
24
|
-
getFork(blockNumber: BlockNumber): Promise<MerkleTreeWriteOperations>;
|
|
25
|
-
}
|
|
26
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tfYnVpbGRlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9ibG9ja19idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUU5RCxPQUFPLEtBQUssRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUl6RCxPQUFPLEVBQUUsWUFBWSxFQUFrQixNQUFNLHlCQUF5QixDQUFDO0FBR3ZFLE9BQU8sRUFHTCxlQUFlLEVBRWhCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUdqRSxPQUFPLEtBQUssRUFDVixnQkFBZ0IsRUFDaEIsMEJBQTBCLEVBQzFCLHFCQUFxQixFQUNyQix5QkFBeUIsRUFDekIscUJBQXFCLEVBQ3JCLHdCQUF3QixFQUN4QixzQkFBc0IsRUFDdkIsTUFBTSxpQ0FBaUMsQ0FBQztBQUN6QyxPQUFPLEVBQUUsZUFBZSxFQUFFLEVBQUUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxLQUFLLGVBQWUsRUFBc0IsTUFBTSx5QkFBeUIsQ0FBQztBQTBFbkYscUJBQWEsb0JBQXFCLFlBQVcscUJBQXFCO0lBRTlELE9BQU8sQ0FBQyxNQUFNO0lBQ2QsT0FBTyxDQUFDLFVBQVU7SUFDbEIsT0FBTyxDQUFDLGtCQUFrQjtJQUMxQixPQUFPLENBQUMsWUFBWTtJQUNwQixPQUFPLENBQUMsZUFBZTtJQUx6QixZQUNVLE1BQU0sRUFBRSwwQkFBMEIsRUFDbEMsVUFBVSxFQUFFLHNCQUFzQixFQUNsQyxrQkFBa0IsRUFBRSxrQkFBa0IsRUFDdEMsWUFBWSxFQUFFLFlBQVksRUFDMUIsZUFBZSxHQUFFLGVBQXNDLEVBQzdEO0lBRUcsU0FBUyxJQUFJLDBCQUEwQixDQUU3QztJQUVNLFlBQVksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLDBCQUEwQixDQUFDLFFBRTlEO0lBRVksb0JBQW9CLENBQUMsZUFBZSxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUseUJBQXlCOzs7T0FrQ2xHO1lBRWEsbUJBQW1CO0lBVTNCLFVBQVUsQ0FDZCxVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxFQUFFLENBQUMsRUFDNUMsY0FBYyxFQUFFLEVBQUUsRUFBRSxFQUNwQixlQUFlLEVBQUUsZUFBZSxFQUNoQyxJQUFJLEVBQUUscUJBQXFCLEVBQzNCLFlBQVksQ0FBQyxFQUFFLHlCQUF5QixHQUN2QyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FzQzNCO0lBRUQsT0FBTyxDQUFDLFdBQVcsRUFBRSxXQUFXLEdBQUcsT0FBTyxDQUFDLHlCQUF5QixDQUFDLENBRXBFO0NBQ0YifQ==
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"block_builder.d.ts","sourceRoot":"","sources":["../../src/sequencer/block_builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAIzD,OAAO,EAAE,YAAY,EAAkB,MAAM,yBAAyB,CAAC;AAGvE,OAAO,EAGL,eAAe,EAEhB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,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;AA0EnF,qBAAa,oBAAqB,YAAW,qBAAqB;IAE9D,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,kBAAkB;IAC1B,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,eAAe;IALzB,YACU,MAAM,EAAE,0BAA0B,EAClC,UAAU,EAAE,sBAAsB,EAClC,kBAAkB,EAAE,kBAAkB,EACtC,YAAY,EAAE,YAAY,EAC1B,eAAe,GAAE,eAAsC,EAC7D;IAEG,SAAS,IAAI,0BAA0B,CAE7C;IAEM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,0BAA0B,CAAC,QAE9D;IAEY,oBAAoB,CAAC,eAAe,EAAE,eAAe,EAAE,IAAI,EAAE,yBAAyB;;;OAkClG;YAEa,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,CAsC3B;IAED,OAAO,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAEpE;CACF"}
|