0

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

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(())
        }
    }
}

官方教程讨论了以以下方式改变密钥:

/// 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吗?如果是,我应该在哪里放置该代码?

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

4

1 回答 1

2

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

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

您可以在存储项上使用exists/ contains_keyapi,并且您应该使用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此处使用 an,您还可以读取该值并检查它是否是Some(value)None,然后错误或继续作为结果。

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

于 2020-02-22T12:16:54.000 回答