From 8a1702cd74cdf7ba9607b816dd55f7be649a0ef2 Mon Sep 17 00:00:00 2001 From: YK Date: Sat, 24 Jan 2026 14:07:16 +0100 Subject: [PATCH] fix(rocksdb): filter history writes to only changed accounts/storage (#21339) Co-authored-by: Tempo AI --- .../src/providers/rocksdb/provider.rs | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/crates/storage/provider/src/providers/rocksdb/provider.rs b/crates/storage/provider/src/providers/rocksdb/provider.rs index 06e5837a91..a0e10cf47f 100644 --- a/crates/storage/provider/src/providers/rocksdb/provider.rs +++ b/crates/storage/provider/src/providers/rocksdb/provider.rs @@ -1206,6 +1206,8 @@ impl RocksDBProvider { } /// Writes account history indices for the given blocks. + /// + /// Derives history indices from reverts (same source as changesets) to ensure consistency. #[instrument(level = "debug", target = "providers::rocksdb", skip_all)] fn write_account_history( &self, @@ -1214,11 +1216,17 @@ impl RocksDBProvider { ) -> ProviderResult<()> { let mut batch = self.batch(); let mut account_history: BTreeMap> = BTreeMap::new(); + for (block_idx, block) in blocks.iter().enumerate() { let block_number = ctx.first_block_number + block_idx as u64; - let bundle = &block.execution_outcome().state; - for &address in bundle.state().keys() { - account_history.entry(address).or_default().push(block_number); + let reverts = block.execution_outcome().state.reverts.to_plain_state_reverts(); + + // Iterate through account reverts - these are exactly the accounts that have + // changesets written, ensuring history indices match changeset entries. + for account_block_reverts in reverts.accounts { + for (address, _) in account_block_reverts { + account_history.entry(address).or_default().push(block_number); + } } } @@ -1231,6 +1239,8 @@ impl RocksDBProvider { } /// Writes storage history indices for the given blocks. + /// + /// Derives history indices from reverts (same source as changesets) to ensure consistency. #[instrument(level = "debug", target = "providers::rocksdb", skip_all)] fn write_storage_history( &self, @@ -1239,13 +1249,22 @@ impl RocksDBProvider { ) -> ProviderResult<()> { let mut batch = self.batch(); let mut storage_history: BTreeMap<(Address, B256), Vec> = BTreeMap::new(); + for (block_idx, block) in blocks.iter().enumerate() { let block_number = ctx.first_block_number + block_idx as u64; - let bundle = &block.execution_outcome().state; - for (&address, account) in bundle.state() { - for &slot in account.storage.keys() { - let key = B256::new(slot.to_be_bytes()); - storage_history.entry((address, key)).or_default().push(block_number); + let reverts = block.execution_outcome().state.reverts.to_plain_state_reverts(); + + // Iterate through storage reverts - these are exactly the slots that have + // changesets written, ensuring history indices match changeset entries. + for storage_block_reverts in reverts.storage { + for revert in storage_block_reverts { + for (slot, _) in revert.storage_revert { + let key = B256::new(slot.to_be_bytes()); + storage_history + .entry((revert.address, key)) + .or_default() + .push(block_number); + } } } }