Skip to content

Commit 1c7a7a3

Browse files
committed
fix: zero value storage and test
1 parent fafd949 commit 1c7a7a3

File tree

2 files changed

+80
-5
lines changed

2 files changed

+80
-5
lines changed

crates/exex/external-proofs/src/in_memory.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,19 @@ impl InMemoryStorageCursor {
217217
}
218218
}
219219

220-
let mut entries: Vec<(B256, U256)> =
221-
slot_to_latest.into_iter().map(|(slot, (_, value))| (slot, value)).collect();
220+
// Filter out zero values - they represent deleted/empty storage slots
221+
let mut entries: Vec<(B256, U256)> = slot_to_latest
222+
.into_iter()
223+
.filter_map(
224+
|(slot, (_, value))| {
225+
if value.is_zero() {
226+
None
227+
} else {
228+
Some((slot, value))
229+
}
230+
},
231+
)
232+
.collect();
222233

223234
entries.sort_by_key(|(slot, _)| *slot);
224235

@@ -377,6 +388,18 @@ impl ExternalStorage for InMemoryExternalStorage {
377388
Ok(inner.earliest_block)
378389
}
379390

391+
async fn get_latest_block_number(&self) -> ExternalStorageResult<Option<(u64, B256)>> {
392+
let inner = self.inner.read().await;
393+
// Find the latest block number from trie_updates
394+
let latest_block = inner.trie_updates.keys().max().copied();
395+
if let Some(block) = latest_block {
396+
// We don't have a hash stored, so return a default
397+
Ok(Some((block, B256::ZERO)))
398+
} else {
399+
Ok(None)
400+
}
401+
}
402+
380403
fn trie_cursor(
381404
&self,
382405
hashed_address: Option<B256>,

crates/exex/external-proofs/src/storage_tests.rs

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -980,10 +980,62 @@ mod tests {
980980
let result75 = cursor75.seek(storage_key)?.unwrap();
981981
assert_eq!(result75.1, U256::from(100));
982982

983-
// Cursor after deletion should see zero
983+
// Cursor after deletion should NOT see the entry (zero values are skipped)
984984
let mut cursor150 = storage.storage_hashed_cursor(hashed_address, 150)?;
985-
let result150 = cursor150.seek(storage_key)?.unwrap();
986-
assert_eq!(result150.1, U256::ZERO);
985+
let result150 = cursor150.seek(storage_key)?;
986+
assert!(result150.is_none(), "Zero values should be skipped/deleted");
987+
988+
Ok(())
989+
}
990+
991+
/// Test that zero values are skipped during iteration
992+
#[test_case(InMemoryExternalStorage::new(); "InMemory")]
993+
#[tokio::test]
994+
async fn test_storage_cursor_skips_zero_values<S: ExternalStorage>(
995+
storage: S,
996+
) -> Result<(), ExternalStorageError> {
997+
let hashed_address = B256::repeat_byte(0x01);
998+
999+
// Create a mix of non-zero and zero value storage slots
1000+
let storage_slots = vec![
1001+
(B256::repeat_byte(0x10), U256::from(100)), // Non-zero
1002+
(B256::repeat_byte(0x20), U256::ZERO), // Zero value - should be skipped
1003+
(B256::repeat_byte(0x30), U256::from(300)), // Non-zero
1004+
(B256::repeat_byte(0x40), U256::ZERO), // Zero value - should be skipped
1005+
(B256::repeat_byte(0x50), U256::from(500)), // Non-zero
1006+
];
1007+
1008+
// Store all slots
1009+
storage.store_hashed_storages(hashed_address, storage_slots.clone(), 50).await?;
1010+
1011+
// Create cursor and iterate through all entries
1012+
let mut cursor = storage.storage_hashed_cursor(hashed_address, 100)?;
1013+
let mut found_slots = Vec::new();
1014+
while let Some((key, value)) = cursor.next()? {
1015+
found_slots.push((key, value));
1016+
}
1017+
1018+
// Should only find 3 non-zero values
1019+
assert_eq!(found_slots.len(), 3, "Zero values should be skipped during iteration");
1020+
1021+
// Verify the non-zero values are the ones we stored
1022+
assert_eq!(found_slots[0], (B256::repeat_byte(0x10), U256::from(100)));
1023+
assert_eq!(found_slots[1], (B256::repeat_byte(0x30), U256::from(300)));
1024+
assert_eq!(found_slots[2], (B256::repeat_byte(0x50), U256::from(500)));
1025+
1026+
// Verify seeking to a zero-value slot returns None or skips to next non-zero
1027+
let mut seek_cursor = storage.storage_hashed_cursor(hashed_address, 100)?;
1028+
let seek_result = seek_cursor.seek(B256::repeat_byte(0x20))?;
1029+
1030+
// Should either return None or skip to the next non-zero value (0x30)
1031+
if let Some((key, value)) = seek_result {
1032+
assert_eq!(
1033+
key,
1034+
B256::repeat_byte(0x30),
1035+
"Should skip zero value and find next non-zero"
1036+
);
1037+
assert_eq!(value, U256::from(300));
1038+
}
9871039

9881040
Ok(())
9891041
}

0 commit comments

Comments
 (0)