substrate-developer-hub / substrate-cms

5 stars 5 forks source link

Substrate Storage Deep Dive Workshop/Tutorial #19

Open shawntabrizi opened 5 years ago

shawntabrizi commented 5 years ago

There are a lot of tricks and nuances to using storage in Substrate.

@thiolliere may be able to help us here with the details of some of these things if he is so kind :)

kianenigma commented 5 years ago

I'd be happy to help with it but probably not as the main owner of the task.

An important idea worth noting: Both Indices and Council use a chunked map to deal with long Vecs. I've made an issue to standardize it but might be a while until anyone does that (if ever). Until then, I think introducing this to our users is super important.

Another one that I've learned the hard way: StorageDoubleMap vs literally storing a map (x, y) => value.

shawntabrizi commented 5 years ago

@Kianenigma can you share a code sample to get an idea of what you mean?

kianenigma commented 5 years ago

@Kianenigma can you share a code sample to get an idea of what you mean?

In cases where you have a very large vec, and you access indexes individually (no need to iterate all of them etc.), you can chunck the Vec into Sets (of 64 element per se) and fetch one set from mem. Indexing would simply be:

const SET_SIZE: u32 = 64;
decl_storage {  BigList map u32 => Vec<X> }

set_idx = global_idx / SET_SIZE;
vec_idxe = global_idx % SET_SIZE;
let set = Self::big_list(set_idx);
let target_value = set[vec_idx];

inserting and removing needs a bit bookkeeping though; one thing for sure is that you probably want a new storage item all the time that points to the next free set. Both Voters and ApprovalsOf have the same deal in council.

ltfschoen commented 5 years ago

And continue the conversation about off-chain storage, as we've already done here:

JoshOrndorff commented 5 years ago

AFAIK, storing enums is not documented anywhere. TIL

// Can't derive Default like you can for structs.
#[derive(Encode, Decode, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Status {
    Active,
    Sold,
    SellerReviewed,
    BuyerReviewed,
}

// Without a manual implementation, you can't use the enum as a storage value
impl Default for Status {
    fn default() -> Self {
        Self::Active
    }
}
bkchr commented 5 years ago

You can store it without a default. Either you specify the default yourself in the decl storage line or you store it as an optional.