@aztec/ethereum 3.0.0-nightly.20251124 → 3.0.0-nightly.20251125
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/config.d.ts +1 -1
- package/dest/config.js +3 -3
- package/dest/contracts/rollup.d.ts +23 -22
- package/dest/contracts/rollup.d.ts.map +1 -1
- package/dest/contracts/rollup.js +39 -38
- package/dest/deploy_l1_contracts.js +2 -2
- package/dest/l1_artifacts.d.ts +1151 -755
- package/dest/l1_artifacts.d.ts.map +1 -1
- package/dest/test/chain_monitor.d.ts +13 -13
- package/dest/test/chain_monitor.d.ts.map +1 -1
- package/dest/test/chain_monitor.js +28 -28
- package/dest/test/rollup_cheat_codes.d.ts +4 -4
- package/dest/test/rollup_cheat_codes.d.ts.map +1 -1
- package/dest/test/rollup_cheat_codes.js +18 -22
- package/package.json +5 -5
- package/src/config.ts +3 -3
- package/src/contracts/rollup.ts +43 -38
- package/src/deploy_l1_contracts.ts +2 -2
- package/src/test/chain_monitor.ts +35 -35
- package/src/test/rollup_cheat_codes.ts +18 -22
|
@@ -43,25 +43,21 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
43
43
|
* Returns the pending and proven chain tips
|
|
44
44
|
* @returns The pending and proven chain tips
|
|
45
45
|
*/ async getTips() {
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
pending: res.pendingBlockNumber,
|
|
49
|
-
proven: res.provenBlockNumber
|
|
50
|
-
};
|
|
46
|
+
return await this.rollup.read.getTips();
|
|
51
47
|
}
|
|
52
48
|
/**
|
|
53
49
|
* Logs the current state of the rollup contract.
|
|
54
50
|
*/ async debugRollup() {
|
|
55
51
|
const rollup = new RollupContract(this.client, this.rollup.address);
|
|
56
|
-
const pendingNum = await rollup.
|
|
57
|
-
const provenNum = await rollup.
|
|
52
|
+
const pendingNum = await rollup.getCheckpointNumber();
|
|
53
|
+
const provenNum = await rollup.getProvenCheckpointNumber();
|
|
58
54
|
const validators = await rollup.getAttesters();
|
|
59
55
|
const committee = await rollup.getCurrentEpochCommittee();
|
|
60
56
|
const archive = await rollup.archive();
|
|
61
57
|
const slot = await this.getSlot();
|
|
62
58
|
const epochNum = await rollup.getEpochNumberForSlotNumber(slot);
|
|
63
|
-
this.logger.info(`Pending
|
|
64
|
-
this.logger.info(`Proven
|
|
59
|
+
this.logger.info(`Pending checkpoint num: ${pendingNum}`);
|
|
60
|
+
this.logger.info(`Proven checkpoint num: ${provenNum}`);
|
|
65
61
|
this.logger.info(`Validators: ${validators.map((v)=>v.toString()).join(', ')}`);
|
|
66
62
|
this.logger.info(`Committee: ${committee?.map((v)=>v.toString()).join(', ')}`);
|
|
67
63
|
this.logger.info(`Archive: ${archive}`);
|
|
@@ -144,36 +140,36 @@ import { EthCheatCodes } from './eth_cheat_codes.js';
|
|
|
144
140
|
this.logger.warn(`Advanced ${howMany} slots up to slot ${slot} in epoch ${epoch}`);
|
|
145
141
|
}
|
|
146
142
|
/**
|
|
147
|
-
* Marks the specified
|
|
148
|
-
* @param
|
|
149
|
-
*/ markAsProven(
|
|
143
|
+
* Marks the specified checkpoint (or latest if none) as proven
|
|
144
|
+
* @param maybeCheckpointNumber - The checkpoint number to mark as proven (defaults to latest pending)
|
|
145
|
+
*/ markAsProven(maybeCheckpointNumber) {
|
|
150
146
|
return this.ethCheatCodes.execWithPausedAnvil(async ()=>{
|
|
151
147
|
const tipsBefore = await this.getTips();
|
|
152
148
|
const { pending, proven } = tipsBefore;
|
|
153
|
-
let
|
|
154
|
-
if (
|
|
155
|
-
|
|
149
|
+
let checkpointNumber = maybeCheckpointNumber;
|
|
150
|
+
if (checkpointNumber === undefined || checkpointNumber > pending) {
|
|
151
|
+
checkpointNumber = pending;
|
|
156
152
|
}
|
|
157
|
-
if (
|
|
158
|
-
this.logger.debug(`
|
|
153
|
+
if (checkpointNumber <= proven) {
|
|
154
|
+
this.logger.debug(`Checkpoint ${checkpointNumber} is already proven`);
|
|
159
155
|
return;
|
|
160
156
|
}
|
|
161
157
|
// @note @LHerskind this is heavily dependent on the storage layout and size of values
|
|
162
158
|
// The rollupStore is a struct and if the size of elements or the struct changes, this can break
|
|
163
|
-
const
|
|
159
|
+
const provenCheckpointNumberSlot = hexToBigInt(RollupContract.stfStorageSlot);
|
|
164
160
|
// Need to pack it as a single 32 byte word
|
|
165
|
-
const newValue = BigInt(tipsBefore.pending) << 128n | BigInt(
|
|
166
|
-
await this.ethCheatCodes.store(EthAddress.fromString(this.rollup.address),
|
|
161
|
+
const newValue = BigInt(tipsBefore.pending) << 128n | BigInt(checkpointNumber);
|
|
162
|
+
await this.ethCheatCodes.store(EthAddress.fromString(this.rollup.address), provenCheckpointNumberSlot, newValue);
|
|
167
163
|
const tipsAfter = await this.getTips();
|
|
168
164
|
if (tipsAfter.pending < tipsAfter.proven) {
|
|
169
|
-
throw new Error('Overwrote pending tip to a
|
|
165
|
+
throw new Error('Overwrote pending tip to a checkpoint in the past');
|
|
170
166
|
}
|
|
171
167
|
this.logger.info(`Proven tip moved: ${tipsBefore.proven} -> ${tipsAfter.proven}. Pending tip: ${tipsAfter.pending}.`);
|
|
172
168
|
});
|
|
173
169
|
}
|
|
174
170
|
/**
|
|
175
171
|
* Overrides the inProgress field of the Inbox contract state
|
|
176
|
-
* @param howMuch - How many
|
|
172
|
+
* @param howMuch - How many checkpoints to move it forward
|
|
177
173
|
*/ advanceInboxInProgress(howMuch) {
|
|
178
174
|
return this.ethCheatCodes.execWithPausedAnvil(async ()=>{
|
|
179
175
|
// Storage slot 2 contains the InboxState struct
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/ethereum",
|
|
3
|
-
"version": "3.0.0-nightly.
|
|
3
|
+
"version": "3.0.0-nightly.20251125",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"../package.common.json"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@aztec/blob-lib": "3.0.0-nightly.
|
|
35
|
-
"@aztec/constants": "3.0.0-nightly.
|
|
36
|
-
"@aztec/foundation": "3.0.0-nightly.
|
|
37
|
-
"@aztec/l1-artifacts": "3.0.0-nightly.
|
|
34
|
+
"@aztec/blob-lib": "3.0.0-nightly.20251125",
|
|
35
|
+
"@aztec/constants": "3.0.0-nightly.20251125",
|
|
36
|
+
"@aztec/foundation": "3.0.0-nightly.20251125",
|
|
37
|
+
"@aztec/l1-artifacts": "3.0.0-nightly.20251125",
|
|
38
38
|
"@viem/anvil": "^0.0.10",
|
|
39
39
|
"dotenv": "^16.0.3",
|
|
40
40
|
"lodash.chunk": "^4.2.0",
|
package/src/config.ts
CHANGED
|
@@ -90,7 +90,7 @@ export const DefaultL1ContractsConfig = {
|
|
|
90
90
|
slashingExecutionDelayInRounds: 0, // round N may be submitted in round N + 1
|
|
91
91
|
slashingVetoer: EthAddress.ZERO,
|
|
92
92
|
governanceProposerRoundSize: 300,
|
|
93
|
-
manaTarget: BigInt(
|
|
93
|
+
manaTarget: BigInt(100e6),
|
|
94
94
|
provingCostPerMana: BigInt(100),
|
|
95
95
|
exitDelaySeconds: 2 * 24 * 60 * 60,
|
|
96
96
|
slasherFlavor: 'tally' as const,
|
|
@@ -200,14 +200,14 @@ const DefaultRewardConfig = {
|
|
|
200
200
|
sequencerBps: 8000,
|
|
201
201
|
rewardDistributor: EthAddress.ZERO.toString(),
|
|
202
202
|
booster: EthAddress.ZERO.toString(),
|
|
203
|
-
|
|
203
|
+
checkpointReward: 500n * 10n ** 18n,
|
|
204
204
|
};
|
|
205
205
|
|
|
206
206
|
const MainnetRewardConfig = {
|
|
207
207
|
sequencerBps: 7_000,
|
|
208
208
|
rewardDistributor: EthAddress.ZERO.toString(),
|
|
209
209
|
booster: EthAddress.ZERO.toString(),
|
|
210
|
-
|
|
210
|
+
checkpointReward: 400n * 10n ** 18n,
|
|
211
211
|
};
|
|
212
212
|
|
|
213
213
|
export const getRewardConfig = (networkName: NetworkNames) => {
|
package/src/contracts/rollup.ts
CHANGED
|
@@ -332,16 +332,16 @@ export class RollupContract {
|
|
|
332
332
|
return await slasher.getProposer();
|
|
333
333
|
}
|
|
334
334
|
|
|
335
|
-
|
|
336
|
-
return this.rollup.read.
|
|
335
|
+
getCheckpointReward() {
|
|
336
|
+
return this.rollup.read.getCheckpointReward();
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
|
|
340
|
-
return this.rollup.read.
|
|
339
|
+
getCheckpointNumber() {
|
|
340
|
+
return this.rollup.read.getPendingCheckpointNumber();
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
-
|
|
344
|
-
return this.rollup.read.
|
|
343
|
+
getProvenCheckpointNumber() {
|
|
344
|
+
return this.rollup.read.getProvenCheckpointNumber();
|
|
345
345
|
}
|
|
346
346
|
|
|
347
347
|
getSlotNumber() {
|
|
@@ -426,8 +426,8 @@ export class RollupContract {
|
|
|
426
426
|
return result;
|
|
427
427
|
}
|
|
428
428
|
|
|
429
|
-
|
|
430
|
-
return this.rollup.read.
|
|
429
|
+
getCheckpoint(checkpointNumber: bigint | number) {
|
|
430
|
+
return this.rollup.read.getCheckpoint([BigInt(checkpointNumber)]);
|
|
431
431
|
}
|
|
432
432
|
|
|
433
433
|
getTips() {
|
|
@@ -454,8 +454,8 @@ export class RollupContract {
|
|
|
454
454
|
return this.rollup.read.getCurrentEpoch();
|
|
455
455
|
}
|
|
456
456
|
|
|
457
|
-
|
|
458
|
-
return this.rollup.read.
|
|
457
|
+
getEpochNumberForCheckpoint(checkpointNumber: bigint) {
|
|
458
|
+
return this.rollup.read.getEpochForCheckpoint([BigInt(checkpointNumber)]);
|
|
459
459
|
}
|
|
460
460
|
|
|
461
461
|
async getRollupAddresses(): Promise<L1RollupContractAddresses> {
|
|
@@ -539,15 +539,16 @@ export class RollupContract {
|
|
|
539
539
|
* @dev Throws if unable to propose
|
|
540
540
|
*
|
|
541
541
|
* @param archive - The archive that we expect to be current state
|
|
542
|
-
* @return [slot,
|
|
542
|
+
* @return [slot, checkpointNumber, timeOfNextL1Slot] - If you can propose, the L2 slot number, checkpoint number and
|
|
543
|
+
* timestamp of the next L1 block
|
|
543
544
|
* @throws otherwise
|
|
544
545
|
*/
|
|
545
546
|
public async canProposeAtNextEthBlock(
|
|
546
547
|
archive: Buffer,
|
|
547
548
|
account: `0x${string}` | Account,
|
|
548
549
|
slotDuration: bigint | number,
|
|
549
|
-
opts: {
|
|
550
|
-
): Promise<{ slot: bigint;
|
|
550
|
+
opts: { forcePendingCheckpointNumber?: number } = {},
|
|
551
|
+
): Promise<{ slot: bigint; checkpointNumber: bigint; timeOfNextL1Slot: bigint }> {
|
|
551
552
|
if (typeof slotDuration === 'number') {
|
|
552
553
|
slotDuration = BigInt(slotDuration);
|
|
553
554
|
}
|
|
@@ -557,35 +558,37 @@ export class RollupContract {
|
|
|
557
558
|
|
|
558
559
|
try {
|
|
559
560
|
const {
|
|
560
|
-
result: [slot,
|
|
561
|
+
result: [slot, checkpointNumber],
|
|
561
562
|
} = await this.client.simulateContract({
|
|
562
563
|
address: this.address,
|
|
563
564
|
abi: RollupAbi,
|
|
564
565
|
functionName: 'canProposeAtTime',
|
|
565
566
|
args: [timeOfNextL1Slot, `0x${archive.toString('hex')}`, who],
|
|
566
567
|
account,
|
|
567
|
-
stateOverride: await this.
|
|
568
|
+
stateOverride: await this.makePendingCheckpointNumberOverride(opts.forcePendingCheckpointNumber),
|
|
568
569
|
});
|
|
569
570
|
|
|
570
|
-
return { slot,
|
|
571
|
+
return { slot, checkpointNumber, timeOfNextL1Slot };
|
|
571
572
|
} catch (err: unknown) {
|
|
572
573
|
throw formatViemError(err);
|
|
573
574
|
}
|
|
574
575
|
}
|
|
575
576
|
|
|
576
577
|
/**
|
|
577
|
-
* Returns a state override that sets the pending
|
|
578
|
-
* Requires querying the current state of the contract to get the current proven
|
|
578
|
+
* Returns a state override that sets the pending checkpoint number to the specified value. Useful for simulations.
|
|
579
|
+
* Requires querying the current state of the contract to get the current proven checkpoint number, as they are both
|
|
579
580
|
* stored in the same slot. If the argument is undefined, it returns an empty override.
|
|
580
581
|
*/
|
|
581
|
-
public async
|
|
582
|
-
|
|
582
|
+
public async makePendingCheckpointNumberOverride(
|
|
583
|
+
forcePendingCheckpointNumber: number | undefined,
|
|
584
|
+
): Promise<StateOverride> {
|
|
585
|
+
if (forcePendingCheckpointNumber === undefined) {
|
|
583
586
|
return [];
|
|
584
587
|
}
|
|
585
588
|
const slot = RollupContract.stfStorageSlot;
|
|
586
589
|
const currentValue = await this.client.getStorageAt({ address: this.address, slot });
|
|
587
|
-
const
|
|
588
|
-
const newValue = (BigInt(
|
|
590
|
+
const currentProvenCheckpointNumber = currentValue ? hexToBigInt(currentValue) & ((1n << 128n) - 1n) : 0n;
|
|
591
|
+
const newValue = (BigInt(forcePendingCheckpointNumber) << 128n) | currentProvenCheckpointNumber;
|
|
589
592
|
return [
|
|
590
593
|
{
|
|
591
594
|
address: this.address,
|
|
@@ -596,7 +599,7 @@ export class RollupContract {
|
|
|
596
599
|
|
|
597
600
|
/** Creates a request to Rollup#invalidateBadAttestation to be simulated or sent */
|
|
598
601
|
public buildInvalidateBadAttestationRequest(
|
|
599
|
-
|
|
602
|
+
checkpointNumber: number,
|
|
600
603
|
attestationsAndSigners: ViemCommitteeAttestations,
|
|
601
604
|
committee: EthAddress[],
|
|
602
605
|
invalidIndex: number,
|
|
@@ -607,7 +610,7 @@ export class RollupContract {
|
|
|
607
610
|
abi: RollupAbi,
|
|
608
611
|
functionName: 'invalidateBadAttestation',
|
|
609
612
|
args: [
|
|
610
|
-
BigInt(
|
|
613
|
+
BigInt(checkpointNumber),
|
|
611
614
|
attestationsAndSigners,
|
|
612
615
|
committee.map(addr => addr.toString()),
|
|
613
616
|
BigInt(invalidIndex),
|
|
@@ -618,7 +621,7 @@ export class RollupContract {
|
|
|
618
621
|
|
|
619
622
|
/** Creates a request to Rollup#invalidateInsufficientAttestations to be simulated or sent */
|
|
620
623
|
public buildInvalidateInsufficientAttestationsRequest(
|
|
621
|
-
|
|
624
|
+
checkpointNumber: number,
|
|
622
625
|
attestationsAndSigners: ViemCommitteeAttestations,
|
|
623
626
|
committee: EthAddress[],
|
|
624
627
|
): L1TxRequest {
|
|
@@ -627,17 +630,17 @@ export class RollupContract {
|
|
|
627
630
|
data: encodeFunctionData({
|
|
628
631
|
abi: RollupAbi,
|
|
629
632
|
functionName: 'invalidateInsufficientAttestations',
|
|
630
|
-
args: [BigInt(
|
|
633
|
+
args: [BigInt(checkpointNumber), attestationsAndSigners, committee.map(addr => addr.toString())],
|
|
631
634
|
}),
|
|
632
635
|
};
|
|
633
636
|
}
|
|
634
637
|
|
|
635
638
|
/** Calls getHasSubmitted directly. Returns whether the given prover has submitted a proof with the given length for the given epoch. */
|
|
636
|
-
public getHasSubmittedProof(epochNumber: number,
|
|
639
|
+
public getHasSubmittedProof(epochNumber: number, numberOfCheckpointsInEpoch: number, prover: Hex | EthAddress) {
|
|
637
640
|
if (prover instanceof EthAddress) {
|
|
638
641
|
prover = prover.toString();
|
|
639
642
|
}
|
|
640
|
-
return this.rollup.read.getHasSubmitted([BigInt(epochNumber), BigInt(
|
|
643
|
+
return this.rollup.read.getHasSubmitted([BigInt(epochNumber), BigInt(numberOfCheckpointsInEpoch), prover]);
|
|
641
644
|
}
|
|
642
645
|
|
|
643
646
|
getManaBaseFeeAt(timestamp: bigint, inFeeAsset: boolean) {
|
|
@@ -648,9 +651,9 @@ export class RollupContract {
|
|
|
648
651
|
return this.rollup.read.getSlotAt([timestamp]);
|
|
649
652
|
}
|
|
650
653
|
|
|
651
|
-
async status(
|
|
654
|
+
async status(checkpointNumber: bigint, options?: { blockNumber?: bigint }) {
|
|
652
655
|
await checkBlockTag(options?.blockNumber, this.client);
|
|
653
|
-
return this.rollup.read.status([
|
|
656
|
+
return this.rollup.read.status([checkpointNumber], options);
|
|
654
657
|
}
|
|
655
658
|
|
|
656
659
|
async canPruneAtTime(timestamp: bigint, options?: { blockNumber?: bigint }) {
|
|
@@ -662,8 +665,8 @@ export class RollupContract {
|
|
|
662
665
|
return this.rollup.read.archive();
|
|
663
666
|
}
|
|
664
667
|
|
|
665
|
-
archiveAt(
|
|
666
|
-
return this.rollup.read.archiveAt([
|
|
668
|
+
archiveAt(checkpointNumber: bigint) {
|
|
669
|
+
return this.rollup.read.archiveAt([checkpointNumber]);
|
|
667
670
|
}
|
|
668
671
|
|
|
669
672
|
getSequencerRewards(address: Hex | EthAddress) {
|
|
@@ -705,8 +708,8 @@ export class RollupContract {
|
|
|
705
708
|
return this.rollup.read.getStatus([address]);
|
|
706
709
|
}
|
|
707
710
|
|
|
708
|
-
getBlobCommitmentsHash(
|
|
709
|
-
return this.rollup.read.getBlobCommitmentsHash([
|
|
711
|
+
getBlobCommitmentsHash(checkpointNumber: bigint) {
|
|
712
|
+
return this.rollup.read.getBlobCommitmentsHash([checkpointNumber]);
|
|
710
713
|
}
|
|
711
714
|
|
|
712
715
|
getCurrentBlobCommitmentsHash() {
|
|
@@ -761,15 +764,17 @@ export class RollupContract {
|
|
|
761
764
|
);
|
|
762
765
|
}
|
|
763
766
|
|
|
764
|
-
public
|
|
765
|
-
|
|
767
|
+
public listenToCheckpointInvalidated(
|
|
768
|
+
callback: (args: { checkpointNumber: bigint }) => unknown,
|
|
769
|
+
): WatchContractEventReturnType {
|
|
770
|
+
return this.rollup.watchEvent.CheckpointInvalidated(
|
|
766
771
|
{},
|
|
767
772
|
{
|
|
768
773
|
onLogs: logs => {
|
|
769
774
|
for (const log of logs) {
|
|
770
775
|
const args = log.args;
|
|
771
|
-
if (args.
|
|
772
|
-
callback({
|
|
776
|
+
if (args.checkpointNumber !== undefined) {
|
|
777
|
+
callback({ checkpointNumber: args.checkpointNumber });
|
|
773
778
|
}
|
|
774
779
|
}
|
|
775
780
|
},
|
|
@@ -487,9 +487,9 @@ export const deploySharedContracts = async (
|
|
|
487
487
|
const rewardDistributorAddress = await registry.getRewardDistributor();
|
|
488
488
|
|
|
489
489
|
if (!args.existingTokenAddress) {
|
|
490
|
-
const
|
|
490
|
+
const checkpointReward = getRewardConfig(networkName).checkpointReward;
|
|
491
491
|
|
|
492
|
-
const funding =
|
|
492
|
+
const funding = checkpointReward * 200000n;
|
|
493
493
|
const { txHash: fundRewardDistributorTxHash } = await deployer.sendTransaction({
|
|
494
494
|
to: feeAssetAddress.toString(),
|
|
495
495
|
data: encodeFunctionData({
|
|
@@ -10,8 +10,8 @@ import type { ViemClient } from '../types.js';
|
|
|
10
10
|
|
|
11
11
|
export type ChainMonitorEventMap = {
|
|
12
12
|
'l1-block': [{ l1BlockNumber: number; timestamp: bigint }];
|
|
13
|
-
|
|
14
|
-
'
|
|
13
|
+
checkpoint: [{ checkpointNumber: number; l1BlockNumber: number; l2SlotNumber: number; timestamp: bigint }];
|
|
14
|
+
'checkpoint-proven': [{ provenCheckpointNumber: number; l1BlockNumber: number; timestamp: bigint }];
|
|
15
15
|
'l2-messages': [{ totalL2Messages: number; l1BlockNumber: number }];
|
|
16
16
|
'l2-epoch': [{ l2EpochNumber: number; timestamp: bigint; committee: EthAddress[] | undefined }];
|
|
17
17
|
'l2-slot': [{ l2SlotNumber: number; timestamp: bigint }];
|
|
@@ -27,14 +27,14 @@ export class ChainMonitor extends EventEmitter<ChainMonitorEventMap> {
|
|
|
27
27
|
|
|
28
28
|
/** Current L1 block number */
|
|
29
29
|
public l1BlockNumber!: number;
|
|
30
|
-
/** Current
|
|
31
|
-
public
|
|
32
|
-
/** Current
|
|
33
|
-
public
|
|
34
|
-
/** L1 timestamp for the current
|
|
35
|
-
public
|
|
36
|
-
/** L1 timestamp for the proven
|
|
37
|
-
public
|
|
30
|
+
/** Current checkpoint number */
|
|
31
|
+
public checkpointNumber!: number;
|
|
32
|
+
/** Current proven checkpoint number */
|
|
33
|
+
public provenCheckpointNumber!: number;
|
|
34
|
+
/** L1 timestamp for the current checkpoint */
|
|
35
|
+
public checkpointTimestamp!: bigint;
|
|
36
|
+
/** L1 timestamp for the proven checkpoint */
|
|
37
|
+
public provenCheckpointTimestamp!: bigint;
|
|
38
38
|
/** Total number of L2 messages pushed into the Inbox */
|
|
39
39
|
public totalL2Messages: number = 0;
|
|
40
40
|
/** Current L2 epoch number */
|
|
@@ -114,28 +114,28 @@ export class ChainMonitor extends EventEmitter<ChainMonitorEventMap> {
|
|
|
114
114
|
this.emit('l1-block', { l1BlockNumber: newL1BlockNumber, timestamp });
|
|
115
115
|
let msg = `L1 block ${newL1BlockNumber} mined at ${timestampString}`;
|
|
116
116
|
|
|
117
|
-
const
|
|
118
|
-
if (this.
|
|
119
|
-
const epochNumber = await this.rollup.
|
|
120
|
-
msg += ` with new
|
|
121
|
-
this.
|
|
122
|
-
this.
|
|
123
|
-
this.emit('
|
|
124
|
-
|
|
117
|
+
const newCheckpointNumber = Number(await this.rollup.getCheckpointNumber());
|
|
118
|
+
if (this.checkpointNumber !== newCheckpointNumber) {
|
|
119
|
+
const epochNumber = await this.rollup.getEpochNumberForCheckpoint(BigInt(newCheckpointNumber));
|
|
120
|
+
msg += ` with new checkpoint ${newCheckpointNumber} for epoch ${epochNumber}`;
|
|
121
|
+
this.checkpointNumber = newCheckpointNumber;
|
|
122
|
+
this.checkpointTimestamp = timestamp;
|
|
123
|
+
this.emit('checkpoint', {
|
|
124
|
+
checkpointNumber: newCheckpointNumber,
|
|
125
125
|
l1BlockNumber: newL1BlockNumber,
|
|
126
126
|
l2SlotNumber: Number(l2SlotNumber),
|
|
127
127
|
timestamp,
|
|
128
128
|
});
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
const
|
|
132
|
-
if (this.
|
|
133
|
-
const epochNumber = await this.rollup.
|
|
134
|
-
msg += ` with proof up to
|
|
135
|
-
this.
|
|
136
|
-
this.
|
|
137
|
-
this.emit('
|
|
138
|
-
|
|
131
|
+
const newProvenCheckpointNumber = Number(await this.rollup.getProvenCheckpointNumber());
|
|
132
|
+
if (this.provenCheckpointNumber !== newProvenCheckpointNumber) {
|
|
133
|
+
const epochNumber = await this.rollup.getEpochNumberForCheckpoint(BigInt(newProvenCheckpointNumber));
|
|
134
|
+
msg += ` with proof up to checkpoint ${newProvenCheckpointNumber} for epoch ${epochNumber}`;
|
|
135
|
+
this.provenCheckpointNumber = newProvenCheckpointNumber;
|
|
136
|
+
this.provenCheckpointTimestamp = timestamp;
|
|
137
|
+
this.emit('checkpoint-proven', {
|
|
138
|
+
provenCheckpointNumber: newProvenCheckpointNumber,
|
|
139
139
|
l1BlockNumber: newL1BlockNumber,
|
|
140
140
|
timestamp,
|
|
141
141
|
});
|
|
@@ -168,8 +168,8 @@ export class ChainMonitor extends EventEmitter<ChainMonitorEventMap> {
|
|
|
168
168
|
l1BlockNumber: this.l1BlockNumber,
|
|
169
169
|
l2SlotNumber,
|
|
170
170
|
l2Epoch,
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
checkpointNumber: this.checkpointNumber,
|
|
172
|
+
provenCheckpointNumber: this.provenCheckpointNumber,
|
|
173
173
|
totalL2Messages: this.totalL2Messages,
|
|
174
174
|
committee,
|
|
175
175
|
});
|
|
@@ -225,19 +225,19 @@ export class ChainMonitor extends EventEmitter<ChainMonitorEventMap> {
|
|
|
225
225
|
});
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
-
public
|
|
229
|
-
const targetBlock = typeof
|
|
230
|
-
if (this.
|
|
228
|
+
public waitUntilCheckpoint(checkpointNumber: number | bigint): Promise<void> {
|
|
229
|
+
const targetBlock = typeof checkpointNumber === 'bigint' ? checkpointNumber.valueOf() : checkpointNumber;
|
|
230
|
+
if (this.checkpointNumber >= targetBlock) {
|
|
231
231
|
return Promise.resolve();
|
|
232
232
|
}
|
|
233
233
|
return new Promise(resolve => {
|
|
234
|
-
const listener = (data: {
|
|
235
|
-
if (data.
|
|
236
|
-
this.off('
|
|
234
|
+
const listener = (data: { checkpointNumber: number; timestamp: bigint }) => {
|
|
235
|
+
if (data.checkpointNumber >= targetBlock) {
|
|
236
|
+
this.off('checkpoint', listener);
|
|
237
237
|
resolve();
|
|
238
238
|
}
|
|
239
239
|
};
|
|
240
|
-
this.on('
|
|
240
|
+
this.on('checkpoint', listener);
|
|
241
241
|
});
|
|
242
242
|
}
|
|
243
243
|
}
|
|
@@ -69,11 +69,7 @@ export class RollupCheatCodes {
|
|
|
69
69
|
/** The pending chain tip */ pending: bigint;
|
|
70
70
|
/** The proven chain tip */ proven: bigint;
|
|
71
71
|
}> {
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
pending: res.pendingBlockNumber,
|
|
75
|
-
proven: res.provenBlockNumber,
|
|
76
|
-
};
|
|
72
|
+
return await this.rollup.read.getTips();
|
|
77
73
|
}
|
|
78
74
|
|
|
79
75
|
/**
|
|
@@ -81,16 +77,16 @@ export class RollupCheatCodes {
|
|
|
81
77
|
*/
|
|
82
78
|
public async debugRollup() {
|
|
83
79
|
const rollup = new RollupContract(this.client, this.rollup.address);
|
|
84
|
-
const pendingNum = await rollup.
|
|
85
|
-
const provenNum = await rollup.
|
|
80
|
+
const pendingNum = await rollup.getCheckpointNumber();
|
|
81
|
+
const provenNum = await rollup.getProvenCheckpointNumber();
|
|
86
82
|
const validators = await rollup.getAttesters();
|
|
87
83
|
const committee = await rollup.getCurrentEpochCommittee();
|
|
88
84
|
const archive = await rollup.archive();
|
|
89
85
|
const slot = await this.getSlot();
|
|
90
86
|
const epochNum = await rollup.getEpochNumberForSlotNumber(slot);
|
|
91
87
|
|
|
92
|
-
this.logger.info(`Pending
|
|
93
|
-
this.logger.info(`Proven
|
|
88
|
+
this.logger.info(`Pending checkpoint num: ${pendingNum}`);
|
|
89
|
+
this.logger.info(`Proven checkpoint num: ${provenNum}`);
|
|
94
90
|
this.logger.info(`Validators: ${validators.map(v => v.toString()).join(', ')}`);
|
|
95
91
|
this.logger.info(`Committee: ${committee?.map(v => v.toString()).join(', ')}`);
|
|
96
92
|
this.logger.info(`Archive: ${archive}`);
|
|
@@ -171,34 +167,34 @@ export class RollupCheatCodes {
|
|
|
171
167
|
}
|
|
172
168
|
|
|
173
169
|
/**
|
|
174
|
-
* Marks the specified
|
|
175
|
-
* @param
|
|
170
|
+
* Marks the specified checkpoint (or latest if none) as proven
|
|
171
|
+
* @param maybeCheckpointNumber - The checkpoint number to mark as proven (defaults to latest pending)
|
|
176
172
|
*/
|
|
177
|
-
public markAsProven(
|
|
173
|
+
public markAsProven(maybeCheckpointNumber?: number | bigint) {
|
|
178
174
|
return this.ethCheatCodes.execWithPausedAnvil(async () => {
|
|
179
175
|
const tipsBefore = await this.getTips();
|
|
180
176
|
const { pending, proven } = tipsBefore;
|
|
181
177
|
|
|
182
|
-
let
|
|
183
|
-
if (
|
|
184
|
-
|
|
178
|
+
let checkpointNumber = maybeCheckpointNumber;
|
|
179
|
+
if (checkpointNumber === undefined || checkpointNumber > pending) {
|
|
180
|
+
checkpointNumber = pending;
|
|
185
181
|
}
|
|
186
|
-
if (
|
|
187
|
-
this.logger.debug(`
|
|
182
|
+
if (checkpointNumber <= proven) {
|
|
183
|
+
this.logger.debug(`Checkpoint ${checkpointNumber} is already proven`);
|
|
188
184
|
return;
|
|
189
185
|
}
|
|
190
186
|
|
|
191
187
|
// @note @LHerskind this is heavily dependent on the storage layout and size of values
|
|
192
188
|
// The rollupStore is a struct and if the size of elements or the struct changes, this can break
|
|
193
|
-
const
|
|
189
|
+
const provenCheckpointNumberSlot = hexToBigInt(RollupContract.stfStorageSlot);
|
|
194
190
|
|
|
195
191
|
// Need to pack it as a single 32 byte word
|
|
196
|
-
const newValue = (BigInt(tipsBefore.pending) << 128n) | BigInt(
|
|
197
|
-
await this.ethCheatCodes.store(EthAddress.fromString(this.rollup.address),
|
|
192
|
+
const newValue = (BigInt(tipsBefore.pending) << 128n) | BigInt(checkpointNumber);
|
|
193
|
+
await this.ethCheatCodes.store(EthAddress.fromString(this.rollup.address), provenCheckpointNumberSlot, newValue);
|
|
198
194
|
|
|
199
195
|
const tipsAfter = await this.getTips();
|
|
200
196
|
if (tipsAfter.pending < tipsAfter.proven) {
|
|
201
|
-
throw new Error('Overwrote pending tip to a
|
|
197
|
+
throw new Error('Overwrote pending tip to a checkpoint in the past');
|
|
202
198
|
}
|
|
203
199
|
|
|
204
200
|
this.logger.info(
|
|
@@ -209,7 +205,7 @@ export class RollupCheatCodes {
|
|
|
209
205
|
|
|
210
206
|
/**
|
|
211
207
|
* Overrides the inProgress field of the Inbox contract state
|
|
212
|
-
* @param howMuch - How many
|
|
208
|
+
* @param howMuch - How many checkpoints to move it forward
|
|
213
209
|
*/
|
|
214
210
|
public advanceInboxInProgress(howMuch: number | bigint): Promise<bigint> {
|
|
215
211
|
return this.ethCheatCodes.execWithPausedAnvil(async () => {
|