@aztec/sequencer-client 0.0.1-commit.db765a8 → 0.0.1-commit.df81a97b5
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 +4 -1
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +46 -23
- package/dest/config.d.ts +25 -5
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +21 -12
- package/dest/global_variable_builder/global_builder.d.ts +13 -7
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +22 -21
- package/dest/global_variable_builder/index.d.ts +2 -2
- package/dest/global_variable_builder/index.d.ts.map +1 -1
- package/dest/publisher/config.d.ts +13 -1
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +17 -2
- package/dest/publisher/sequencer-publisher-factory.d.ts +3 -3
- package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-factory.js +2 -2
- package/dest/publisher/sequencer-publisher.d.ts +9 -4
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +33 -9
- package/dest/sequencer/checkpoint_proposal_job.d.ts +13 -7
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +166 -115
- package/dest/sequencer/events.d.ts +2 -1
- package/dest/sequencer/events.d.ts.map +1 -1
- package/dest/sequencer/metrics.d.ts +5 -1
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +11 -0
- package/dest/sequencer/sequencer.d.ts +11 -8
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +71 -61
- package/dest/sequencer/timetable.d.ts +4 -3
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +6 -7
- package/dest/sequencer/types.d.ts +2 -2
- package/dest/sequencer/types.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.d.ts +7 -9
- package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.js +39 -30
- package/package.json +27 -28
- package/src/client/sequencer-client.ts +56 -21
- package/src/config.ts +28 -14
- package/src/global_variable_builder/global_builder.ts +22 -23
- package/src/global_variable_builder/index.ts +1 -1
- package/src/publisher/config.ts +32 -0
- package/src/publisher/sequencer-publisher-factory.ts +3 -3
- package/src/publisher/sequencer-publisher.ts +39 -11
- package/src/sequencer/checkpoint_proposal_job.ts +219 -131
- package/src/sequencer/events.ts +1 -1
- package/src/sequencer/metrics.ts +14 -0
- package/src/sequencer/sequencer.ts +97 -68
- package/src/sequencer/timetable.ts +7 -7
- package/src/sequencer/types.ts +1 -1
- package/src/test/mock_checkpoint_builder.ts +51 -48
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
2
|
-
import type { L1ContractsConfig } from '@aztec/ethereum/config';
|
|
3
1
|
import { RollupContract } from '@aztec/ethereum/contracts';
|
|
4
|
-
import type {
|
|
2
|
+
import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
|
|
5
3
|
import type { ViemPublicClient } from '@aztec/ethereum/types';
|
|
6
4
|
import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
7
5
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
8
6
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
9
7
|
import { createLogger } from '@aztec/foundation/log';
|
|
8
|
+
import type { DateProvider } from '@aztec/foundation/timer';
|
|
10
9
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
11
|
-
import { type L1RollupConstants, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
10
|
+
import { type L1RollupConstants, getNextL1SlotTimestamp, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
12
11
|
import { GasFees } from '@aztec/stdlib/gas';
|
|
13
12
|
import type {
|
|
14
13
|
CheckpointGlobalVariables,
|
|
@@ -16,7 +15,12 @@ import type {
|
|
|
16
15
|
} from '@aztec/stdlib/tx';
|
|
17
16
|
import { GlobalVariables } from '@aztec/stdlib/tx';
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
/** Configuration for the GlobalVariableBuilder (excludes L1 client config). */
|
|
19
|
+
export type GlobalVariableBuilderConfig = {
|
|
20
|
+
l1Contracts: Pick<L1ContractAddresses, 'rollupAddress'>;
|
|
21
|
+
ethereumSlotDuration: number;
|
|
22
|
+
rollupVersion: bigint;
|
|
23
|
+
} & Pick<L1RollupConstants, 'slotDuration' | 'l1GenesisTime'>;
|
|
20
24
|
|
|
21
25
|
/**
|
|
22
26
|
* Simple global variables builder.
|
|
@@ -27,7 +31,6 @@ export class GlobalVariableBuilder implements GlobalVariableBuilderInterface {
|
|
|
27
31
|
private currentL1BlockNumber: bigint | undefined = undefined;
|
|
28
32
|
|
|
29
33
|
private readonly rollupContract: RollupContract;
|
|
30
|
-
private readonly publicClient: ViemPublicClient;
|
|
31
34
|
private readonly ethereumSlotDuration: number;
|
|
32
35
|
private readonly aztecSlotDuration: number;
|
|
33
36
|
private readonly l1GenesisTime: bigint;
|
|
@@ -36,28 +39,18 @@ export class GlobalVariableBuilder implements GlobalVariableBuilderInterface {
|
|
|
36
39
|
private version: Fr;
|
|
37
40
|
|
|
38
41
|
constructor(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
private readonly dateProvider: DateProvider,
|
|
43
|
+
private readonly publicClient: ViemPublicClient,
|
|
44
|
+
config: GlobalVariableBuilderConfig,
|
|
42
45
|
) {
|
|
43
|
-
const { l1RpcUrls, l1ChainId: chainId, l1Contracts } = config;
|
|
44
|
-
|
|
45
|
-
const chain = createEthereumChain(l1RpcUrls, chainId);
|
|
46
|
-
|
|
47
46
|
this.version = new Fr(config.rollupVersion);
|
|
48
|
-
this.chainId = new Fr(
|
|
47
|
+
this.chainId = new Fr(this.publicClient.chain!.id);
|
|
49
48
|
|
|
50
49
|
this.ethereumSlotDuration = config.ethereumSlotDuration;
|
|
51
50
|
this.aztecSlotDuration = config.slotDuration;
|
|
52
51
|
this.l1GenesisTime = config.l1GenesisTime;
|
|
53
52
|
|
|
54
|
-
this.
|
|
55
|
-
chain: chain.chainInfo,
|
|
56
|
-
transport: fallback(chain.rpcUrls.map(url => http(url, { batch: false }))),
|
|
57
|
-
pollingInterval: config.viemPollingIntervalMS,
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
this.rollupContract = new RollupContract(this.publicClient, l1Contracts.rollupAddress);
|
|
53
|
+
this.rollupContract = new RollupContract(this.publicClient, config.l1Contracts.rollupAddress);
|
|
61
54
|
}
|
|
62
55
|
|
|
63
56
|
/**
|
|
@@ -73,7 +66,10 @@ export class GlobalVariableBuilder implements GlobalVariableBuilderInterface {
|
|
|
73
66
|
const earliestTimestamp = await this.rollupContract.getTimestampForSlot(
|
|
74
67
|
SlotNumber.fromBigInt(BigInt(lastCheckpoint.slotNumber) + 1n),
|
|
75
68
|
);
|
|
76
|
-
const nextEthTimestamp =
|
|
69
|
+
const nextEthTimestamp = getNextL1SlotTimestamp(this.dateProvider.nowInSeconds(), {
|
|
70
|
+
l1GenesisTime: this.l1GenesisTime,
|
|
71
|
+
ethereumSlotDuration: this.ethereumSlotDuration,
|
|
72
|
+
});
|
|
77
73
|
const timestamp = earliestTimestamp > nextEthTimestamp ? earliestTimestamp : nextEthTimestamp;
|
|
78
74
|
|
|
79
75
|
return new GasFees(0, await this.rollupContract.getManaMinFeeAt(timestamp, true));
|
|
@@ -108,7 +104,10 @@ export class GlobalVariableBuilder implements GlobalVariableBuilderInterface {
|
|
|
108
104
|
const slot: SlotNumber =
|
|
109
105
|
maybeSlot ??
|
|
110
106
|
(await this.rollupContract.getSlotAt(
|
|
111
|
-
|
|
107
|
+
getNextL1SlotTimestamp(this.dateProvider.nowInSeconds(), {
|
|
108
|
+
l1GenesisTime: this.l1GenesisTime,
|
|
109
|
+
ethereumSlotDuration: this.ethereumSlotDuration,
|
|
110
|
+
}),
|
|
112
111
|
));
|
|
113
112
|
|
|
114
113
|
const checkpointGlobalVariables = await this.buildCheckpointGlobalVariables(coinbase, feeRecipient, slot);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { GlobalVariableBuilder } from './global_builder.js';
|
|
1
|
+
export { GlobalVariableBuilder, type GlobalVariableBuilderConfig } from './global_builder.js';
|
package/src/publisher/config.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { type L1TxUtilsConfig, l1TxUtilsConfigMappings } from '@aztec/ethereum/l
|
|
|
4
4
|
import { type ConfigMappingsType, SecretValue, booleanConfigHelper } from '@aztec/foundation/config';
|
|
5
5
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
6
6
|
|
|
7
|
+
import { parseEther } from 'viem';
|
|
8
|
+
|
|
7
9
|
/** Configuration of the transaction publisher. */
|
|
8
10
|
export type TxSenderConfig = L1ReaderConfig & {
|
|
9
11
|
/** The private key to be used by the publisher. */
|
|
@@ -50,13 +52,37 @@ export type PublisherConfig = L1TxUtilsConfig &
|
|
|
50
52
|
publisherForwarderAddress?: EthAddress;
|
|
51
53
|
/** Store for failed L1 transaction inputs (test networks only). Format: gs://bucket/path */
|
|
52
54
|
l1TxFailedStore?: string;
|
|
55
|
+
/** Min ETH balance below which a publisher gets funded. Undefined = funding disabled. */
|
|
56
|
+
publisherFundingThreshold?: bigint;
|
|
57
|
+
/** Amount of ETH to send when funding a publisher. Undefined = funding disabled. */
|
|
58
|
+
publisherFundingAmount?: bigint;
|
|
53
59
|
};
|
|
54
60
|
|
|
61
|
+
/** Shared config mappings for publisher funding, used by both sequencer and prover publisher configs. */
|
|
62
|
+
const publisherFundingConfigMappings = {
|
|
63
|
+
publisherFundingThreshold: {
|
|
64
|
+
env: 'PUBLISHER_FUNDING_THRESHOLD' as const,
|
|
65
|
+
description:
|
|
66
|
+
'Min ETH balance below which a publisher gets funded. Specified in ether (e.g. 0.1). Unset = funding disabled.',
|
|
67
|
+
parseEnv: (val: string) => parseEther(val),
|
|
68
|
+
},
|
|
69
|
+
publisherFundingAmount: {
|
|
70
|
+
env: 'PUBLISHER_FUNDING_AMOUNT' as const,
|
|
71
|
+
description:
|
|
72
|
+
'Amount of ETH to send when funding a publisher. Specified in ether (e.g. 0.5). Unset = funding disabled.',
|
|
73
|
+
parseEnv: (val: string) => parseEther(val),
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
55
77
|
export type ProverPublisherConfig = L1TxUtilsConfig &
|
|
56
78
|
BlobClientConfig & {
|
|
57
79
|
fishermanMode?: boolean;
|
|
58
80
|
proverPublisherAllowInvalidStates?: boolean;
|
|
59
81
|
proverPublisherForwarderAddress?: EthAddress;
|
|
82
|
+
/** Min ETH balance below which a publisher gets funded. Undefined = funding disabled. */
|
|
83
|
+
publisherFundingThreshold?: bigint;
|
|
84
|
+
/** Amount of ETH to send when funding a publisher. Undefined = funding disabled. */
|
|
85
|
+
publisherFundingAmount?: bigint;
|
|
60
86
|
};
|
|
61
87
|
|
|
62
88
|
export type SequencerPublisherConfig = L1TxUtilsConfig &
|
|
@@ -66,6 +92,10 @@ export type SequencerPublisherConfig = L1TxUtilsConfig &
|
|
|
66
92
|
sequencerPublisherForwarderAddress?: EthAddress;
|
|
67
93
|
/** Store for failed L1 transaction inputs (test networks only). Format: gs://bucket/path */
|
|
68
94
|
l1TxFailedStore?: string;
|
|
95
|
+
/** Min ETH balance below which a publisher gets funded. Undefined = funding disabled. */
|
|
96
|
+
publisherFundingThreshold?: bigint;
|
|
97
|
+
/** Amount of ETH to send when funding a publisher. Undefined = funding disabled. */
|
|
98
|
+
publisherFundingAmount?: bigint;
|
|
69
99
|
};
|
|
70
100
|
|
|
71
101
|
export function getPublisherConfigFromProverConfig(config: ProverPublisherConfig): PublisherConfig {
|
|
@@ -142,6 +172,7 @@ export const sequencerPublisherConfigMappings: ConfigMappingsType<SequencerPubli
|
|
|
142
172
|
env: 'L1_TX_FAILED_STORE',
|
|
143
173
|
description: 'Store for failed L1 transaction inputs (test networks only). Format: gs://bucket/path',
|
|
144
174
|
},
|
|
175
|
+
...publisherFundingConfigMappings,
|
|
145
176
|
};
|
|
146
177
|
|
|
147
178
|
export const proverPublisherConfigMappings: ConfigMappingsType<ProverPublisherConfig & L1TxUtilsConfig> = {
|
|
@@ -163,4 +194,5 @@ export const proverPublisherConfigMappings: ConfigMappingsType<ProverPublisherCo
|
|
|
163
194
|
description: 'Address of the forwarder contract to wrap all L1 transactions through (for testing purposes only)',
|
|
164
195
|
parseEnv: (val: string) => (val ? EthAddress.fromString(val) : undefined),
|
|
165
196
|
},
|
|
197
|
+
...publisherFundingConfigMappings,
|
|
166
198
|
};
|
|
@@ -117,8 +117,8 @@ export class SequencerPublisherFactory {
|
|
|
117
117
|
};
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
/**
|
|
121
|
-
public
|
|
122
|
-
this.deps.publisherManager.
|
|
120
|
+
/** Stops all publishers managed by this factory. Used during sequencer shutdown. */
|
|
121
|
+
public async stopAll(): Promise<void> {
|
|
122
|
+
await this.deps.publisherManager.stop();
|
|
123
123
|
}
|
|
124
124
|
}
|
|
@@ -28,6 +28,7 @@ import { FormattedViemError, formatViemError, mergeAbis, tryExtractEvent } from
|
|
|
28
28
|
import { sumBigint } from '@aztec/foundation/bigint';
|
|
29
29
|
import { toHex as toPaddedHex } from '@aztec/foundation/bigint-buffer';
|
|
30
30
|
import { CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
31
|
+
import { trimmedBytesLength } from '@aztec/foundation/buffer';
|
|
31
32
|
import { pick } from '@aztec/foundation/collection';
|
|
32
33
|
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
33
34
|
import { TimeoutError } from '@aztec/foundation/error';
|
|
@@ -41,6 +42,7 @@ import { EmpireBaseAbi, ErrorsAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
|
41
42
|
import { type ProposerSlashAction, encodeSlashConsensusVotes } from '@aztec/slasher';
|
|
42
43
|
import { CommitteeAttestationsAndSigners, type ValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
43
44
|
import type { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
45
|
+
import { getNextL1SlotTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
44
46
|
import { SlashFactoryContract } from '@aztec/stdlib/l1-contracts';
|
|
45
47
|
import type { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
46
48
|
import type { L1PublishCheckpointStats } from '@aztec/stdlib/stats';
|
|
@@ -132,6 +134,8 @@ export class SequencerPublisher {
|
|
|
132
134
|
|
|
133
135
|
protected log: Logger;
|
|
134
136
|
protected ethereumSlotDuration: bigint;
|
|
137
|
+
protected aztecSlotDuration: bigint;
|
|
138
|
+
private dateProvider: DateProvider;
|
|
135
139
|
|
|
136
140
|
private blobClient: BlobClientInterface;
|
|
137
141
|
|
|
@@ -165,7 +169,7 @@ export class SequencerPublisher {
|
|
|
165
169
|
|
|
166
170
|
constructor(
|
|
167
171
|
private config: Pick<SequencerPublisherConfig, 'fishermanMode' | 'l1TxFailedStore'> &
|
|
168
|
-
Pick<L1ContractsConfig, 'ethereumSlotDuration'> & { l1ChainId: number },
|
|
172
|
+
Pick<L1ContractsConfig, 'ethereumSlotDuration' | 'aztecSlotDuration'> & { l1ChainId: number },
|
|
169
173
|
deps: {
|
|
170
174
|
telemetry?: TelemetryClient;
|
|
171
175
|
blobClient: BlobClientInterface;
|
|
@@ -184,6 +188,8 @@ export class SequencerPublisher {
|
|
|
184
188
|
) {
|
|
185
189
|
this.log = deps.log ?? createLogger('sequencer:publisher');
|
|
186
190
|
this.ethereumSlotDuration = BigInt(config.ethereumSlotDuration);
|
|
191
|
+
this.aztecSlotDuration = BigInt(config.aztecSlotDuration);
|
|
192
|
+
this.dateProvider = deps.dateProvider;
|
|
187
193
|
this.epochCache = deps.epochCache;
|
|
188
194
|
this.lastActions = deps.lastActions;
|
|
189
195
|
|
|
@@ -285,7 +291,7 @@ export class SequencerPublisher {
|
|
|
285
291
|
}
|
|
286
292
|
|
|
287
293
|
public getCurrentL2Slot(): SlotNumber {
|
|
288
|
-
return this.epochCache.
|
|
294
|
+
return this.epochCache.getSlotNow();
|
|
289
295
|
}
|
|
290
296
|
|
|
291
297
|
/**
|
|
@@ -398,8 +404,8 @@ export class SequencerPublisher {
|
|
|
398
404
|
// @note - we can only have one blob config per bundle
|
|
399
405
|
// find requests with gas and blob configs
|
|
400
406
|
// See https://github.com/AztecProtocol/aztec-packages/issues/11513
|
|
401
|
-
const gasConfigs =
|
|
402
|
-
const blobConfigs =
|
|
407
|
+
const gasConfigs = validRequests.filter(request => request.gasConfig).map(request => request.gasConfig);
|
|
408
|
+
const blobConfigs = validRequests.filter(request => request.blobConfig).map(request => request.blobConfig);
|
|
403
409
|
|
|
404
410
|
if (blobConfigs.length > 1) {
|
|
405
411
|
throw new Error('Multiple blob configs found');
|
|
@@ -547,7 +553,16 @@ export class SequencerPublisher {
|
|
|
547
553
|
});
|
|
548
554
|
return { failedActions: requests.map(r => r.action) };
|
|
549
555
|
} else {
|
|
550
|
-
this.log.verbose(`Published bundled transactions (${actionsListStr})`, {
|
|
556
|
+
this.log.verbose(`Published bundled transactions (${actionsListStr})`, {
|
|
557
|
+
result,
|
|
558
|
+
requests: requests.map(r => ({
|
|
559
|
+
...r,
|
|
560
|
+
// Avoid logging large blob data
|
|
561
|
+
blobConfig: r.blobConfig
|
|
562
|
+
? { ...r.blobConfig, blobs: r.blobConfig.blobs.map(b => ({ size: trimmedBytesLength(b) })) }
|
|
563
|
+
: undefined,
|
|
564
|
+
})),
|
|
565
|
+
});
|
|
551
566
|
const successfulActions: Action[] = [];
|
|
552
567
|
const failedActions: Action[] = [];
|
|
553
568
|
for (const request of requests) {
|
|
@@ -586,20 +601,24 @@ export class SequencerPublisher {
|
|
|
586
601
|
}
|
|
587
602
|
|
|
588
603
|
/**
|
|
589
|
-
* @notice Will call `
|
|
604
|
+
* @notice Will call `canProposeAt` to make sure that it is possible to propose
|
|
590
605
|
* @param tipArchive - The archive to check
|
|
591
606
|
* @returns The slot and block number if it is possible to propose, undefined otherwise
|
|
592
607
|
*/
|
|
593
|
-
public
|
|
608
|
+
public canProposeAt(
|
|
594
609
|
tipArchive: Fr,
|
|
595
610
|
msgSender: EthAddress,
|
|
596
|
-
opts: { forcePendingCheckpointNumber?: CheckpointNumber } = {},
|
|
611
|
+
opts: { forcePendingCheckpointNumber?: CheckpointNumber; pipelined?: boolean } = {},
|
|
597
612
|
) {
|
|
598
613
|
// TODO: #14291 - should loop through multiple keys to check if any of them can propose
|
|
599
614
|
const ignoredErrors = ['SlotAlreadyInChain', 'InvalidProposer', 'InvalidArchive'];
|
|
600
615
|
|
|
616
|
+
const pipelined = opts.pipelined ?? this.epochCache.isProposerPipeliningEnabled();
|
|
617
|
+
const slotOffset = pipelined ? this.aztecSlotDuration : 0n;
|
|
618
|
+
const nextL1SlotTs = this.getNextL1SlotTimestamp() + slotOffset;
|
|
619
|
+
|
|
601
620
|
return this.rollupContract
|
|
602
|
-
.
|
|
621
|
+
.canProposeAt(tipArchive.toBuffer(), msgSender.toString(), nextL1SlotTs, {
|
|
603
622
|
forcePendingCheckpointNumber: opts.forcePendingCheckpointNumber,
|
|
604
623
|
})
|
|
605
624
|
.catch(err => {
|
|
@@ -613,6 +632,7 @@ export class SequencerPublisher {
|
|
|
613
632
|
return undefined;
|
|
614
633
|
});
|
|
615
634
|
}
|
|
635
|
+
|
|
616
636
|
/**
|
|
617
637
|
* @notice Will simulate `validateHeader` to make sure that the block header is valid
|
|
618
638
|
* @dev This is a convenience function that can be used by the sequencer to validate a "partial" header.
|
|
@@ -636,7 +656,7 @@ export class SequencerPublisher {
|
|
|
636
656
|
flags,
|
|
637
657
|
] as const;
|
|
638
658
|
|
|
639
|
-
const ts =
|
|
659
|
+
const ts = this.getNextL1SlotTimestamp();
|
|
640
660
|
const stateOverrides = await this.rollupContract.makePendingCheckpointNumberOverride(
|
|
641
661
|
opts?.forcePendingCheckpointNumber,
|
|
642
662
|
);
|
|
@@ -801,7 +821,9 @@ export class SequencerPublisher {
|
|
|
801
821
|
attestationsAndSignersSignature: Signature,
|
|
802
822
|
options: { forcePendingCheckpointNumber?: CheckpointNumber },
|
|
803
823
|
): Promise<bigint> {
|
|
804
|
-
|
|
824
|
+
// Anchor the simulation timestamp to the checkpoint's own slot start time
|
|
825
|
+
// rather than the current L1 block timestamp, which may overshoot into the next slot if the build ran late.
|
|
826
|
+
const ts = checkpoint.header.timestamp;
|
|
805
827
|
const blobFields = checkpoint.toBlobFields();
|
|
806
828
|
const blobs = await getBlobsPerL1Block(blobFields);
|
|
807
829
|
const blobInput = getPrefixedEthBlobCommitments(blobs);
|
|
@@ -1567,4 +1589,10 @@ export class SequencerPublisher {
|
|
|
1567
1589
|
},
|
|
1568
1590
|
});
|
|
1569
1591
|
}
|
|
1592
|
+
|
|
1593
|
+
/** Returns the timestamp to use when simulating L1 proposal calls */
|
|
1594
|
+
private getNextL1SlotTimestamp(): bigint {
|
|
1595
|
+
const l1Constants = this.epochCache.getL1Constants();
|
|
1596
|
+
return getNextL1SlotTimestamp(this.dateProvider.nowInSeconds(), l1Constants);
|
|
1597
|
+
}
|
|
1570
1598
|
}
|