substrate icon indicating copy to clipboard operation
substrate copied to clipboard

CountedNMap implementation

Open Mr-Leshiy opened this issue 3 years ago • 24 comments

add CountedStorageNMap implementation which is similar as CountedStorageMap for StorageMap but for the StorageNMap https://github.com/paritytech/substrate/issues/10602

Mr-Leshiy avatar Jan 10 '22 10:01 Mr-Leshiy

@bkchr , @shawntabrizi don't want to be tactless, but can we proceed with this PR, it will be helpful to solve this issue https://github.com/paritytech/polkadot-sdk/issues/316. Also after if this PR will be approved and merged I will prepare the same update for the StorageNMap.

Mr-Leshiy avatar Feb 11 '22 14:02 Mr-Leshiy

This PR seems valuable, yet hat slipped through the crack. Partially due to lack of labeling and project assignment from our side. Hopefully will get some review soon. Thanks @Mr-Leshiy!

kianenigma avatar Mar 19 '22 22:03 kianenigma

I'm honestly interested to know why can't we just have a CountedStorageNMap instead? The CountedStorageDoubleMap can just be a type alias to a CountedStorageNMap that way (and the same can also be said for CountedStorageMap).

KiChjang avatar May 13 '22 08:05 KiChjang

Hey, is anyone still working on this? Due to the inactivity this issue has been automatically marked as stale. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jun 12 '22 09:06 stale[bot]

@KiChjang , so sorry for the delay.

I'm honestly interested to know why can't we just have a CountedStorageNMap instead? The CountedStorageDoubleMap can just be a type alias to a CountedStorageNMap that way (and the same can also be said for CountedStorageMap).

For my understanding it is impossible to implement in such way, because all these types of storages have different type of interfaces and also have different type of implementation. So in this case it is impossible to unify them and hide under the same implementation and interface.

Mr-Leshiy avatar Jun 12 '22 10:06 Mr-Leshiy

I'm sorry but what you said doesn't expose or explain what exactly the impossibility is. Why is it not as simple as this:

type CountedStorageDoubleMap<P, H1, K1, H2, K2, V, Q, O, M> = CountedStorageNMap<P, (NMapKey<H1, K1>, NMapKey<H2, K2>), V, Q, O, M>;

What exactly is different about the interfaces?

KiChjang avatar Jun 13 '22 12:06 KiChjang

@KiChjang , as a reference we can consider the following function from the original double map and from the original nmap contains_key.

DoubleMap function signature contains_key:

contains_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> bool

Nmap function signature contains_key:

contains_key<KArg: EncodeLikeTuple<Key::KArg> + TupleToEncodedIter>(key: KArg) -> bool

Mr-Leshiy avatar Jun 21 '22 17:06 Mr-Leshiy

Okay, then we don't do a type alias, but call into the NMap methods underneath, i.e.

fn contains_key<KArg1, KArg2>(k1: KArg1, k2: KArg2) -> bool {
    NMap::contains_key(((k1, Hasher1::hasher()), (k2, Hasher2::hasher())))
}

The point here is to reduce the amount of code that we have to maintain by using NMap behind the scenes.

KiChjang avatar Jun 22 '22 09:06 KiChjang

@KiChjang , But how it will helps if I will replace an underneath implementation from the native DoubleMap storage to the NMap ? And if so I am coming with the general question why we have to different implementations of DoubleMap and NMap ?

Mr-Leshiy avatar Jun 29 '22 08:06 Mr-Leshiy

DoubleMap is a relic of the past when we didn't have NMap. Since we're going to support 2 keys in a counted map, it would then make a lot more sense now to not support legacy code and see if we can all use NMap underneath.

KiChjang avatar Jun 29 '22 08:06 KiChjang

@KiChjang I gotcha, sorry that was so annoying with questions and doubts, but I was not totally understood what do you mean and why need to change it 😊 So, what do you think if I will change this implementation just for the NMap, so will have a CountedNMap ? And later will figure out how to extend it to be compatible with the DoubleMap interface ?

Mr-Leshiy avatar Jun 29 '22 11:06 Mr-Leshiy

That sounds like a workable plan to me. It may also be easier if you attempt to convert the existing StorageDoubleMap to use StorageNMap underneath first, but having a CountedNMap implementation right now is also valuable as well.

KiChjang avatar Jul 15 '22 15:07 KiChjang

Hey, is anyone still working on this? Due to the inactivity this issue has been automatically marked as stale. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Aug 14 '22 19:08 stale[bot]

In progress...

Mr-Leshiy avatar Aug 17 '22 16:08 Mr-Leshiy

@KiChjang Hello, I returning back to you ! Hope you are well ))) I have updated implementation and added CountedStorageNMap implementation, also removed CountedStorageDoubleMap. If we will successfully proceed with this one and it will be needed I will add CountedStorageDoubleMap implementation. :)

Mr-Leshiy avatar Aug 18 '22 14:08 Mr-Leshiy

Everything looks great so far!

Hmm... since we still have StorageDoubleMap nowadays, I think we do have to add a CountedStorageDoubleMap after all, since that is what people would expect, but we can then have it actually use a CountedStorageNMap underneath.

KiChjang avatar Aug 19 '22 12:08 KiChjang

@KiChjang , totally agree with you. But I would prefer to make StorageDoubleMap in the separate PR. But if you think that ti should be done here, I can do it, but will need some time for it :)

Mr-Leshiy avatar Aug 19 '22 19:08 Mr-Leshiy

@KiChjang , totally agree with you. But I would prefer to make StorageDoubleMap in the separate PR. But if you think that ti should be done here, I can do it, but will need some time for it :)

Totally fine as well. That also reminds me -- CountedStorageMap itself can use StorageNMap underneath too, no reason to have separate implementations of it.

KiChjang avatar Aug 20 '22 04:08 KiChjang

Hey, is anyone still working on this? Due to the inactivity this issue has been automatically marked as stale. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Dec 23 '22 00:12 stale[bot]

Still in progress ...

Mr-Leshiy avatar Dec 25 '22 19:12 Mr-Leshiy

Hey, is anyone still working on this? Due to the inactivity this issue has been automatically marked as stale. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Feb 10 '23 00:02 stale[bot]

@KiChjang I have updated and seems fixed with your suggestion. I have tried your solution but unfortunately it does not work. I have implemented it as follows.

impl<'a, T: EncodeLike<U> + EncodeLikeTuple<U>, U: Encode> EncodeLikeTuple<U>
	for codec::Ref<'a, T, U>
{
}
impl<'a, T: EncodeLike<U> + EncodeLikeTuple<U>, U: Encode> crate::storage::private::Sealed
	for codec::Ref<'a, T, U>
{
}

I have tried different approaches but seems it would be the best one. What do you think ?

Mr-Leshiy avatar Feb 11 '23 16:02 Mr-Leshiy

Made a small relocation change, but otherwise everything LGTM.

KiChjang avatar Feb 18 '23 06:02 KiChjang

Before this can be merged we'll likely also need to add storage_alias macro support for this map along with some tests, similar to how it's done here: https://github.com/paritytech/substrate/pull/13366 Either that or a new issue, though it might be a nice precedent for posterity to have it all in one PR.

ruseinov avatar Feb 19 '23 13:02 ruseinov

Hey, is anyone still working on this? Due to the inactivity this issue has been automatically marked as stale. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Apr 02 '23 02:04 stale[bot]

Still in progress

Mr-Leshiy avatar Apr 04 '23 11:04 Mr-Leshiy

Hey, is anyone still working on this? Due to the inactivity this issue has been automatically marked as stale. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar May 04 '23 14:05 stale[bot]

Still in progress

Mr-Leshiy avatar May 05 '23 14:05 Mr-Leshiy

@Mr-Leshiy is there any progress on this?

juangirini avatar Jun 16 '23 14:06 juangirini

for convenience and boilerplate when declaring a storage in a pallet we usually declare like this:

	#[pallet::storage]
	pub(super) type Dummy2<T: Config> = CountedStorageNMap<_, T::Balance>;

And the macro will create the type to replace the first type parameter _.

So this need to be handle in the pallet macro to be usable in a pallet.

gui1117 avatar Jun 19 '23 05:06 gui1117