8

I came across the ink_storage::Mapping data structure. The official doc seems to explain that how to use it but not why it's needed. It seems more complicated to initialize and work with than the maps defined by Rust's standard library.

3 Answers 3

15

I assume that with "standard mapping" you mean the maps defined in Rust's standard library: HashMap and BTreeMap.

The reason for the existence of ink_storage::Mapping is that it works entirely different: It delegates the process of mapping keys to values to the pallet-contracts. Each item you insert into the ink_storage::Mapping will occupy a single storage cell within the contract's storage. Accesses to the map will only pull exactly the item you are accessing from storage into contract memory.

On the other hand if you just put a BTreeMap there it will be serialized as a whole into a single storage cell. Subsequently it will be pulled as a whole from contract storage into contract memory. Not very useful to store large sets of data. You should not do that. You would either use a standard Vec for small sets of data that you want to iterate or use ink_storage::Mapping.

10

The first question, what is standard Mapping?=)

I will describe differences for standard hashmap from the Rust - ink_prelude::collections::HashMap. Hope it answers your question.

ink_prelude::collections::HashMap is fully stored under one storage cell. It is fully loaded into the RAM during the execution of the contract from that storage cell. That means if HashMap contains 1000 elements, then all 1000 elements will be loaded into the RAM. It is a lot of gas.

ink_storage::Mapping is not stored in the storage cell at all. Mapping provides simple methods like get and set a value by some key. Each value's key is prefixed by the Mapping(it knows storage prefix), and each value is stored to its storage cell under the prefixed key. That means that element is only loaded if you called the get method and passed a valid key.

The usability of the Mapping is much less than HashMap. For example, you can't iterate over elements, you can't use entry functionality, and so on. But it takes much less gas and the size in the WASM bloat.

-2

From the sourcecode, I found this description in:

https://github.com/paritytech/ink/blob/master/crates/storage/src/collections/hashmap/mod.rs

/// A hash map operating on the contract storage.
///
/// Stores a mapping between keys and values.
///
/// # Note
///
/// Unlike Rust's standard `HashMap` that uses the [`core::hash::Hash`] trait
/// in order to hash its keys the storage hash map uses the [`scale::Encode`]
/// encoding in order to hash its keys using a built-in cryptographic
/// hash function provided by the chain runtime.
///
/// The main difference between the lower-level `LazyHashMap` and the
/// `storage::HashMap` is that the latter is aware of its associated keys and
/// values and operates on those instances directly as opposed to `Option`
/// instances of them. Also it provides a more high-level and user focused
/// API.
///
/// Users should generally prefer using this storage hash map over the low-level
/// `LazyHashMap` for direct usage in their smart contracts.

The critical part is that this version uses "scale::Encode" to hash the keys.

2
  • 1
    FYI: This data structure was removed from the public API before the ink! 3.0 release.
    – HCastano
    Commented Mar 24, 2022 at 0:35
  • Thank you for the heads-up, I had not realized! Commented Mar 24, 2022 at 6:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.