Skip to content

Commit 484017e

Browse files
authored
fix: empty map slot not inserted in forest (#1642)
1 parent 6cd595a commit 484017e

File tree

5 files changed

+94
-17
lines changed

5 files changed

+94
-17
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Fixes
66

77
- Fixed network monitor displaying explorer URL as a "null" hyperlink when unset ([#1617](https://github.com/0xMiden/miden-node/pull/1617)).
8+
- Fixed empty storage maps not being inserted into `storage_entries` table when inserting storage delta ([#1642](https://github.com/0xMiden/miden-node/pull/1642)).
89

910
## v0.13.3 (2026-01-29)
1011

Cargo.lock

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ license = "MIT"
2828
readme = "README.md"
2929
repository = "https://github.com/0xMiden/miden-node"
3030
rust-version = "1.90"
31-
version = "0.13.3"
31+
version = "0.13.4"
3232

3333
# Optimize the cryptography for faster tests involving account creation.
3434
[profile.test.package.miden-crypto]

crates/store/src/inner_forest/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,11 +500,13 @@ impl InnerForest {
500500
})
501501
.collect();
502502

503-
// if the delta is empty, make sure we create an entry in the storage map roots map,
504-
// but no need to do anything else
503+
// if the delta is empty, make sure we create an entry in the storage map roots map
504+
// and storage entries map (so storage_map_entries() queries work)
505505
if map_entries.is_empty() {
506506
self.storage_map_roots
507507
.insert((account_id, slot_name.clone(), block_num), prev_root);
508+
self.storage_entries
509+
.insert((account_id, slot_name.clone(), block_num), BTreeMap::new());
508510

509511
continue;
510512
}

crates/store/src/inner_forest/tests.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,3 +444,77 @@ fn test_storage_map_incremental_updates() {
444444
assert_ne!(root_2, root_3);
445445
assert_ne!(root_1, root_3);
446446
}
447+
448+
#[test]
449+
fn test_empty_storage_map_entries_query() {
450+
use miden_protocol::account::auth::PublicKeyCommitment;
451+
use miden_protocol::account::{
452+
AccountBuilder,
453+
AccountComponent,
454+
AccountStorageMode,
455+
AccountType,
456+
StorageMap,
457+
StorageSlot,
458+
};
459+
use miden_standards::account::auth::AuthFalcon512Rpo;
460+
use miden_standards::code_builder::CodeBuilder;
461+
462+
let mut forest = InnerForest::new();
463+
let block_num = BlockNumber::GENESIS.child();
464+
let slot_name = StorageSlotName::mock(0);
465+
466+
// Create an account with an empty storage map slot
467+
let storage_map = StorageMap::with_entries(vec![]).unwrap();
468+
let component_storage = vec![StorageSlot::with_map(slot_name.clone(), storage_map)];
469+
470+
let component_code = CodeBuilder::default()
471+
.compile_component_code("test::interface", "pub proc test push.1 end")
472+
.unwrap();
473+
let account_component = AccountComponent::new(component_code, component_storage)
474+
.unwrap()
475+
.with_supports_all_types();
476+
477+
let account = AccountBuilder::new([1u8; 32])
478+
.account_type(AccountType::RegularAccountImmutableCode)
479+
.storage_mode(AccountStorageMode::Public)
480+
.with_component(account_component)
481+
.with_auth_component(AuthFalcon512Rpo::new(PublicKeyCommitment::from(EMPTY_WORD)))
482+
.build_existing()
483+
.unwrap();
484+
485+
let account_id = account.id();
486+
487+
// Convert to full-state delta (this triggers insert_account_storage path)
488+
let full_delta = AccountDelta::try_from(account).unwrap();
489+
assert!(full_delta.is_full_state(), "delta should be full-state");
490+
491+
// Apply the delta
492+
forest.update_account(block_num, &full_delta).unwrap();
493+
494+
// Verify storage_map_roots has an entry
495+
assert!(
496+
forest
497+
.storage_map_roots
498+
.contains_key(&(account_id, slot_name.clone(), block_num)),
499+
"storage_map_roots should have an entry for the empty map"
500+
);
501+
502+
// Verify storage_map_entries returns Some (not None) - this is the bug fix validation
503+
let result = forest.storage_map_entries(account_id, slot_name.clone(), block_num);
504+
assert!(result.is_some(), "storage_map_entries should return Some for empty maps");
505+
506+
// Verify the entries are empty
507+
let details = result.unwrap();
508+
assert_eq!(details.slot_name, slot_name);
509+
match details.entries {
510+
StorageMapEntries::AllEntries(entries) => {
511+
assert!(entries.is_empty(), "entries should be empty for an empty map");
512+
},
513+
StorageMapEntries::LimitExceeded => {
514+
panic!("should not exceed limit for empty map");
515+
},
516+
StorageMapEntries::EntriesWithProofs(_) => {
517+
panic!("should not have proofs for empty map query");
518+
},
519+
}
520+
}

0 commit comments

Comments
 (0)