Как иметь неизменяемую карту "ключ-значение" в Substrate?
Я пишу key: value
StorageMap
в 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
? Если да, то где мне разместить этот код?
Примечание: я новичок как в подложке, так и в ржавчине.
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
а затем ошибка или продолжение в результате.
То, что вы не можете сделать, это действительно сделать неизменяемое значение в памяти таким образом, что весь код будет знать, чтобы не изменить значение. Вам нужно будет написать логику, чтобы заранее проверять наличие значения, чтобы вы не меняли его.