From 7cdaafcf0d15fda5b3226d265cc1dc27b1edaa45 Mon Sep 17 00:00:00 2001 From: AztecBot Date: Tue, 17 Mar 2026 09:36:28 +0000 Subject: [PATCH] fix: skip handleChainFinalized when block is behind oldest available When the finalized block jumps backwards past pruned state, return early instead of clamping and continuing into the pruning logic. The previous clamping fix avoided the setFinalized error but then removeHistoricalBlocks would fail trying to prune to a block that is already the oldest. Also guard removeHistoricalBlocks against being called with a block number that is not newer than the current oldest available block. --- .../server_world_state_synchronizer.ts | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.ts b/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.ts index 5bd76e38a48b..1ed4fd7717a6 100644 --- a/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.ts +++ b/yarn-project/world-state/src/synchronizer/server_world_state_synchronizer.ts @@ -388,18 +388,16 @@ export class ServerWorldStateSynchronizer private async handleChainFinalized(blockNumber: BlockNumber) { this.log.verbose(`Finalized chain is now at block ${blockNumber}`); - // Clamp to the oldest block still available in world state. The finalized block number can - // jump backwards (e.g. when the finalization heuristic changes) and try to read block data - // that has already been pruned, which causes the native world state to throw. + // If the finalized block number is older than the oldest available block in world state, + // skip entirely. The finalized block number can jump backwards (e.g. when the finalization + // heuristic changes) and try to read block data that has already been pruned. When this + // happens, there is nothing useful to do — the native world state is already finalized + // past this point and pruning has already happened. const currentSummary = await this.merkleTreeDb.getStatusSummary(); - if (blockNumber < currentSummary.oldestHistoricalBlock) { + if (blockNumber < currentSummary.oldestHistoricalBlock || blockNumber < 1) { this.log.warn( - `Finalized block ${blockNumber} is older than the oldest available block ${currentSummary.oldestHistoricalBlock}. ` + - `Clamping to oldest available block.`, + `Finalized block ${blockNumber} is older than the oldest available block ${currentSummary.oldestHistoricalBlock}. Skipping.`, ); - blockNumber = currentSummary.oldestHistoricalBlock; - } - if (blockNumber < 1) { return; } const summary = await this.merkleTreeDb.setFinalized(blockNumber); @@ -435,6 +433,12 @@ export class ServerWorldStateSynchronizer } // Find the block at the start of the checkpoint and remove blocks up to this one const newHistoricBlock = historicCheckpoint.checkpoint.blocks[0]; + if (newHistoricBlock.number <= currentSummary.oldestHistoricalBlock) { + this.log.debug( + `Historic block ${newHistoricBlock.number} is not newer than oldest available ${currentSummary.oldestHistoricalBlock}. Skipping prune.`, + ); + return; + } this.log.verbose(`Pruning historic blocks to ${newHistoricBlock.number}`); const status = await this.merkleTreeDb.removeHistoricalBlocks(BlockNumber(newHistoricBlock.number)); this.log.debug(`World state summary `, status.summary);