1- import { L1ToL2MessagesNotReadyError } from '@aztec/archiver' ;
21import { PROPOSER_PIPELINING_SLOT_OFFSET } from '@aztec/epoch-cache' ;
32import type { EpochCacheInterface } from '@aztec/epoch-cache' ;
43import {
@@ -8,20 +7,17 @@ import {
87} from '@aztec/ethereum/contracts' ;
98import { BlockNumber , CheckpointNumber , SlotNumber } from '@aztec/foundation/branded-types' ;
109import { compactArray } from '@aztec/foundation/collection' ;
11- import { Fr } from '@aztec/foundation/curves/bn254' ;
1210import { EthAddress } from '@aztec/foundation/eth-address' ;
1311import { BadRequestError } from '@aztec/foundation/json-rpc' ;
1412import { type Logger , createLogger } from '@aztec/foundation/log' ;
1513import { DateProvider } from '@aztec/foundation/timer' ;
16- import { isErrorClass } from '@aztec/foundation/types' ;
1714import { type AvmSimulator , PublicContractsDB , PublicProcessorFactory } from '@aztec/simulator/server' ;
1815import { CollectionLimitsConfig , PublicSimulatorConfig } from '@aztec/stdlib/avm' ;
1916import { AztecAddress } from '@aztec/stdlib/aztec-address' ;
2017import type { L2BlockSource , L2Tips } from '@aztec/stdlib/block' ;
2118import { type ProposedCheckpointData , buildCheckpointSimulationOverridesPlan } from '@aztec/stdlib/checkpoint' ;
2219import type { ContractDataSource } from '@aztec/stdlib/contract' ;
2320import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server' ;
24- import { type L1ToL2MessageSource , appendL1ToL2MessagesToTree } from '@aztec/stdlib/messaging' ;
2521import type { CoordinationSignatureContext } from '@aztec/stdlib/p2p' ;
2622import {
2723 type GlobalVariableBuilder ,
@@ -46,7 +42,6 @@ export interface NodePublicCallsSimulatorConfig {
4642export interface NodePublicCallsSimulatorDeps {
4743 blockSource : L2BlockSource ;
4844 worldStateSynchronizer : WorldStateSynchronizer ;
49- l1ToL2MessageSource : L1ToL2MessageSource ;
5045 contractDataSource : ContractDataSource ;
5146 globalVariableBuilder : GlobalVariableBuilder ;
5247 /**
@@ -87,7 +82,6 @@ export interface NodePublicCallsSimulatorDeps {
8782export class NodePublicCallsSimulator {
8883 private readonly blockSource : L2BlockSource ;
8984 private readonly worldStateSynchronizer : WorldStateSynchronizer ;
90- private readonly l1ToL2MessageSource : L1ToL2MessageSource ;
9185 private readonly contractDataSource : ContractDataSource ;
9286 private readonly globalVariableBuilder : GlobalVariableBuilder ;
9387 private readonly rollupContract : RollupContract | undefined ;
@@ -101,7 +95,6 @@ export class NodePublicCallsSimulator {
10195 constructor ( deps : NodePublicCallsSimulatorDeps ) {
10296 this . blockSource = deps . blockSource ;
10397 this . worldStateSynchronizer = deps . worldStateSynchronizer ;
104- this . l1ToL2MessageSource = deps . l1ToL2MessageSource ;
10598 this . contractDataSource = deps . contractDataSource ;
10699 this . globalVariableBuilder = deps . globalVariableBuilder ;
107100 this . rollupContract = deps . rollupContract ;
@@ -157,9 +150,7 @@ export class NodePublicCallsSimulator {
157150 // the proposed-checkpoint terminating block; it opens a new checkpoint when they coincide.
158151 const atCheckpointBoundary = proposedCheckpointLastBlock === l2Tips . proposed . number ;
159152
160- // `targetCheckpoint` is the checkpoint whose L1-to-L2 messages must be inserted into the fork
161- // before simulation. Only set when opening a new checkpoint, where the next block is its first block.
162- const { globalVariables : newGlobalVariables , targetCheckpoint } = atCheckpointBoundary
153+ const { globalVariables : newGlobalVariables } = atCheckpointBoundary
163154 ? await this . buildGlobalVariablesForNewCheckpoint ( l2Tips , proposedCheckpointData , blockNumber )
164155 : { globalVariables : await this . copyGlobalVariablesFromLatestProposedBlock ( latestBlockNumber , blockNumber ) } ;
165156
@@ -184,19 +175,12 @@ export class NodePublicCallsSimulator {
184175 // Ensure world-state has caught up with the latest block we loaded from the archiver
185176 await this . worldStateSynchronizer . syncImmediate ( latestBlockNumber ) ;
186177
187- const nextCheckpointMessages = await this . getNextCheckpointMessages ( targetCheckpoint ) ;
188-
189- // Request a new fork of the world state at the latest block number, and apply any overrides and next checkpoint messages to it before simulation
178+ // Request a new fork of the world state at the latest block number, and apply any overrides to it before
179+ // simulation. The next checkpoint's L1-to-L2 messages are not inserted here: under the streaming Inbox
180+ // (AZIP-22 Fast Inbox) a checkpoint's messages are consumed per block, so the simulation runs against the
181+ // fork's current tree without predicting the next block's message bundle.
190182 await using merkleTreeFork = await this . worldStateSynchronizer . fork ( latestBlockNumber ) ;
191183
192- if ( nextCheckpointMessages !== undefined ) {
193- this . log . debug (
194- `Appending ${ nextCheckpointMessages . length } L1-to-L2 messages to the world state tree for the next checkpoint` ,
195- { checkpointNumber : targetCheckpoint } ,
196- ) ;
197- await appendL1ToL2MessagesToTree ( merkleTreeFork , nextCheckpointMessages ) ;
198- }
199-
200184 await applyPublicDataOverrides ( merkleTreeFork , overrides ?. publicStorage ) ;
201185
202186 const config = PublicSimulatorConfig . from ( {
@@ -235,37 +219,6 @@ export class NodePublicCallsSimulator {
235219 ) ;
236220 }
237221
238- /**
239- * Fetches the next checkpoint's L1-to-L2 messages to insert into the fork before simulation. Only set
240- * when opening a new checkpoint; when continuing an in-progress checkpoint the ongoing checkpoint's
241- * messages were already applied when its first block synced, so inserting here would double-count them
242- * — which is why a missing header for the latest proposed block throws rather than falling through to
243- * this path. A not-ready or failed fetch degrades to simulating without the messages rather than
244- * failing the request.
245- */
246- private async getNextCheckpointMessages ( targetCheckpoint : CheckpointNumber | undefined ) : Promise < Fr [ ] | undefined > {
247- if ( targetCheckpoint === undefined ) {
248- return undefined ;
249- }
250- try {
251- return await this . l1ToL2MessageSource . getL1ToL2Messages ( targetCheckpoint ) ;
252- } catch ( err ) {
253- if ( isErrorClass ( err , L1ToL2MessagesNotReadyError ) ) {
254- this . log . warn (
255- `L1-to-L2 messages for checkpoint ${ targetCheckpoint } are not ready yet (simulating without them)` ,
256- { checkpointNumber : targetCheckpoint } ,
257- ) ;
258- } else {
259- this . log . error (
260- `Failed to get L1-to-L2 messages for checkpoint ${ targetCheckpoint } (simulating without them)` ,
261- err ,
262- { checkpointNumber : targetCheckpoint } ,
263- ) ;
264- }
265- return undefined ;
266- }
267- }
268-
269222 /**
270223 * Continues an in-progress checkpoint: the next block extends the checkpoint the latest proposed
271224 * block belongs to. Every block in a checkpoint shares the same `CheckpointGlobalVariables`, so the
@@ -298,19 +251,14 @@ export class NodePublicCallsSimulator {
298251 * sequencer applies so the simulated mana min fee matches what the sequencer will write into the
299252 * block header. Coinbase and fee recipient stay zero (we cannot know the future proposer's payout
300253 * addresses), unlike continuing an in-progress checkpoint which inherits the real ones from the
301- * proposed header. Returns the target checkpoint so the caller inserts that checkpoint's L1-to-L2
302- * messages into the fork.
254+ * proposed header.
303255 */
304256 private async buildGlobalVariablesForNewCheckpoint (
305257 l2Tips : L2Tips ,
306258 proposedCheckpointData : ProposedCheckpointData | undefined ,
307259 blockNumber : BlockNumber ,
308- ) : Promise < { globalVariables : GlobalVariables ; targetCheckpoint : CheckpointNumber } > {
260+ ) : Promise < { globalVariables : GlobalVariables } > {
309261 const checkpointedCheckpointNumber = l2Tips . checkpointed . checkpoint . number ;
310- // The new checkpoint sits on top of the proposed one when pipelining, otherwise on the
311- // checkpointed tip. The target slot and the overrides plan both derive from the single
312- // `proposedCheckpointData` read, so they cannot disagree about the proposed parent.
313- const proposedCheckpointNumber = proposedCheckpointData ?. checkpointNumber ?? checkpointedCheckpointNumber ;
314262
315263 const targetSlot = this . computeTargetSlot ( proposedCheckpointData ) ;
316264 const plan = await this . buildSimulationOverridesPlan ( proposedCheckpointData , checkpointedCheckpointNumber ) ;
@@ -324,7 +272,6 @@ export class NodePublicCallsSimulator {
324272
325273 return {
326274 globalVariables : GlobalVariables . from ( { blockNumber, ...checkpointGlobalVariables } ) ,
327- targetCheckpoint : CheckpointNumber ( proposedCheckpointNumber + 1 ) ,
328275 } ;
329276 }
330277
0 commit comments