【问题标题】:How to have immutable key-value map in Substrate?如何在 Substrate 中拥有不可变的键值映射?
【发布时间】:2020-02-22 03:22:26
【问题描述】:

我正在substrate 中写key: value StorageMap。我想让它不可变,以便在不存在但存在时写入密钥:

i) 如果值和存储的一样,好吧 ii) 使交易无效。

我写了以下runtime代码:

use support::{decl_module, decl_storage, dispatch::Result, StorageMap};
use system::ensure_signed;

pub trait Trait: balances::Trait {}

decl_storage! {
    trait Store for Module<T: Trait> as KittyStorage {
        Value: map u64 => T::AccountId;
    }
}

decl_module! {
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {

        fn set_value(origin, value: u64) -> Result {
            let sender = ensure_signed(origin)?;

            <Value<T>>::insert(value, sender);

            Ok(())
        }
    }
}

official tutorial 谈到以下列方式改变密钥:

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

那么,如何使我的key:value 不可变?我应该写自己的StorageMap 吗?如果是,我应该在哪里放置该代码?

注意:我对底材和生锈都不熟悉。

【问题讨论】:

    标签: rust substrate polkadot


    【解决方案1】:

    我想让它不可变,以便在不存在但存在时写入密钥:

    i) 如果值与存储的值相同,好的 ii) 使交易无效。

    您可以在存储项上使用exists/contains_key api,您可能应该使用Option 更加明确。

    所以拿你写的代码,你会像这样修改它:

    use support::{decl_module, decl_storage, dispatch::Result, ensure, StorageMap};
    use system::ensure_signed;
    
    pub trait Trait: balances::Trait {}
    
    decl_storage! {
        trait Store for Module<T: Trait> as KittyStorage {
            Value: map u64 => Option<T::AccountId>;
        }
    }
    
    decl_module! {
        pub struct Module<T: Trait> for enum Call where origin: T::Origin {
    
            fn set_value(origin, value: u64) -> Result {
                let sender = ensure_signed(origin)?;
    
                ensure!(!<Value<T>>::contains_key(value), "key already exists");
                <Value<T>>::insert(value, sender);
    
                Ok(())
            }
        }
    }
    

    由于您在这里使用的是Option,因此您还可以读取该值并检查它是Some(value)还是None,然后出错或继续。

    您不能做的是真正使值在存储中不可变,这样所有代码都知道不会更改该值。您需要编写逻辑来提前检查该值是否存在,这样您就不会更改它。

    【讨论】:

    • 请注意,在 Substrate v1.0 中,api 是 exists,但最近更改为 contains_key。如果你正在学习 v1.0 教程,你应该使用exists
    • 嗨,Shawn,我没有完全理解下面这行:What you cannot do is truly make the value immutable in storage such that all code would know not to change the value. You would need to write logic to check ahead of time the value is there so that you don't change it. 在您提供的代码中,ensure! 调用确实会检查该值是否不存在。这不能确保没有值被覆盖吗?
    • ensure 检查确实是检查存储中是否已经存在值。我们编写了逻辑,以便如果有值,则外部提前结束,并且不更新任何值。但是,如果您编写了更多可能会更改此值的函数,则还需要检查这些函数。
    • 知道了!谢谢:)
    猜你喜欢
    • 2017-10-25
    • 2021-07-13
    • 2017-03-21
    • 2018-07-28
    • 1970-01-01
    • 2016-05-20
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多