1. 程式人生 > 其它 >【Substrate Collectables教程】【第1章基礎】4. 儲存 Storage Mapping

【Substrate Collectables教程】【第1章基礎】4. 儲存 Storage Mapping

Storage Mapping

之前的 runtime 只允許為區塊鏈中的所有使用者儲存單個值。讓我們更多地思考下我們的鏈,顯然為每個使用者儲存其各自的值也是有用的(Storage Mapping)。

為此,我們將使用 storage mapping 替換簡單的 storage value

4.1 Substrate 特定型別

在我們進入 storage mappings 部分前,讓我們來談談我們將要使用的一些 substrate 特定型別。

預設的 runtime 模板包含一組 modules,這些 modules 暴露出了你開發區塊鏈需要涉及的型別。在你開發了更多 module 後,你甚至會自己構造新型別並暴露給 runtime 的其他部分。

在本教程中,我們將僅使用 3 種 substrate 特定型別:

  1. AccountId
  2. Balance
  3. Hash

我們的 module 本身不能訪問這些型別,但我們可以通過讓 module 的 Trait 繼承定義了這些型別的 module 來輕鬆獲取訪問許可權。在當前情況下,balances module 有我們需要的一切東西:

pub trait Trait: balances::Trait {}

 注意: 只能宣告一個Trait

像我們在上面的示例中所做的那樣,我們可以在指定了泛型 <T: Trait> 的任何地方通過使用 T::Type 來訪問這些型別。

4.2 宣告一個 Storage Map

Storage Map 允許你將基礎的 (key, value) 放入 runtime 儲存中。它可以像這樣宣告:

decl_storage! {
    trait Store for Module<T: Trait> as Example {
        SomeValue get(some_value_getter): map u32 => u32;
        MyValue: map T::AccountId => u32;
    }
}

你可以看到,當你想要表示 "owned" 資料時,mapping 是非常有用的。由於我們可以建立從某個使用者(AccountId)到某些值(例如 MyValue)的 mapping,因此我們可以保留有關該使用者的儲存資訊。我們甚至可以在 runtime 中構建邏輯,使 runtime 可以管理具體有哪些使用者能修改那些值,這是我們將在本教程中使用的常見模式。

要使用 storage map,你需要匯入 support::StorageMap

4.3 使用 StorageMap

用於訪問 StorageMap 的函式與 StorageValue 的位於 同一位置

/// Get the prefix key in storage.
fn prefix() -> &'static [u8];

/// Get the storage key used to fetch a value corresponding to a specific key.
fn key_for(x: &K) -> Vec<u8>;

/// true if the value is defined in storage.
fn exists<S: Storage>(key: &K, storage: &S) -> bool {
    storage.exists(&Self::key_for(key)[..])
}

/// Load the value associated with the given key from the map.
fn get<S: Storage>(key: &K, storage: &S) -> Self::Query;

/// Take the value under a key.
fn take<S: Storage>(key: &K, storage: &S) -> Self::Query;

/// Store a value to be associated with the given key from the map.
fn insert<S: Storage>(key: &K, val: &V, storage: &S) {
    storage.put(&Self::key_for(key)[..], val);
}

/// Remove the value under a key.
fn remove<S: Storage>(key: &K, storage: &S) {
    storage.kill(&Self::key_for(key)[..]);
}

/// Mutate the value under a key.
fn mutate<R, F: FnOnce(&mut Self::Query) -> R, S: Storage>(key: &K, f: F, storage: &S) -> R;

因此,如果要將值 "insert" 到一個 Storage Map 中,則需要提供 key 和 value,如下所示:

<SomeValue<T>>::insert(key, value);

你可以使用以下任一方法查詢該值:

let my_value = <SomeValue<T>>::get(key);
let also_my_value = Self::some_value_getter(key);

 如下圖:

使用 StorageMap

4.4 更新runtime