0

My objective is to store hash values in the substrate chain. I have declared the storage and the module for it in the following code:

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 str => 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>>::exists(value), "key already exists");
            <Value<T>>::insert(value, sender);
            Ok(())
        }
    }
}

The code was working fine as expected as long as I was using u64 in the line but I received an error when I changed it to str:

Value: map str => Option<T::AccountId>;

The error is:

error[E0277]: the trait bound `str: _::_parity_scale_codec::EncodeLike` is not satisfied
  --> /Users/aviralsrivastava/dev/substrate-package/substrate-node-template/runtime/src/substratekitties.rs:6:1
   |
6  | / decl_storage! {
7  | |     trait Store for Module<T: Trait> as KittyStorage {
8  | |         Value: map str => Option<T::AccountId>;
9  | |     }
10 | | }
   | |_^ the trait `_::_parity_scale_codec::EncodeLike` is not implemented for `str`
   |

I tried reading about it but could not find any other method of storing a string. Although, my string will be of fixed size as it will always be SHA256.

Aviral Srivastava
  • 4,058
  • 8
  • 29
  • 81
  • Perhaps try `String` instead of `str`? – Peter Hall Mar 17 '20 at 17:12
  • You could try an array as well. So, e.g., `[u8; 20]` – apopiak Mar 17 '20 at 17:23
  • As explained [in this answer](https://stackoverflow.com/questions/24158114/what-are-the-differences-between-rusts-string-and-str) `str` has unknown length and cannot be instantiated AFAIK. – apopiak Mar 17 '20 at 17:26
  • [Here](https://docs.rs/parity-scale-codec/1.2.0/parity_scale_codec/trait.Encode.html) is a list of blanket implementations for `Encode` which you can peruse for a type to use. – apopiak Mar 17 '20 at 17:28

1 Answers1

1

You should be using a hash of known size, so do something like:

type MyHash = [u8; 32];

This would be a 256-bit hash.

Then you can create a storage item:

Value: map MyHash => Option<T::AccountId>;

You can also use the Hash primitive defined in your runtime with T::Hash, which makes it compatible with the default hashing primitives in your runtime. That would look like:

Value: map T::Hash => Option<T::AccountId>;

In Substrate, it is H256 by default (which is basically the same thing as above, but more general as it can change and be redefined by the runtime).

Shawn Tabrizi
  • 12,206
  • 1
  • 38
  • 69