-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Iteration in Store Map #254
Comments
I'm 100% in favor of this, I actually have a branch update-iavl-client to bring the client library up to speed with the current grpc api offered by iavl. I failed because of some dumb ci reasons involving docker that i never figured out, but also because the iavl client tests kind of suck and should probably be rewritten. I think the first step is to do this so we can even get the api we need to make the call. A word about storage prefixes. As far as I can tell, we are doing the same thing that cosmos does (if they do anything consistent at all). This means that keys are simply prefixed several times. For example the an account in the then the account itself. This means that for example the account
I'm assuming that for example, in order to get all of the accounts, you could do something like
|
That is also my understanding of how prefixing works. There is a little bit of a concern about how to specify the entire range though. In your example it works because it's a fixed length bytestring, so you can specify the last one, but for more general string keys I think we would have to somehow figure out / use the next prefix as the end point. Ie I'm now realizing there may also be an issue with name conflicts between modules and their stores though. For example if you had a module named "authaccounts" with a store called "Map" it would end up sharing a prefix. To solve the first problem I had been trying to think through a way to construct an "endcap" which could be a key which came after any of the keys within the store. ie: But there is no such value. Since a key of all 0xff is supposed to be valid, there's no ENDCAP value which would come after that (except a longer key of all 0xff, but that only solves the problem for fixed sized keys again) If user created keys were actually strictly strings instead of bytestrings, then you could construct a separator (like 0x00) and also an endcap (0xff) which would solve both these problems... I'm not really clear on how Cosmos-SDK currently handles iterating entire substores / prefix ranges, I'll try to look into that. |
I think for the moment we can stick to "don't do anything dumb", which is surely what the cosmos sdk is doing. I can imagine in the future a runtime check for conflicting prefixes, but I don't think it's something thats worth trying to control at the type level. It's worth asking the IAVL people if you could just get all the keys that begin with a certain prefix, but I don't know enough myself to say if that's possible |
Okay, so what the SDK does seems reasonable to me. It just increments the last character by 1, so "abcd" -> "abce". Unless it ends with 0xFF, in which case it repeatedly drops the last char until it isn't 0xFF, and increments whatever remains, so "abcdFFFF" -> "abcde". If it runs out of characters, ie the prefix is 0xFF..FF then the next key would just be an empty string. |
There is currently no way to get all the keys or values from a Store Map. A simple workaround is to use both a Map and a Var, to track the set of keys used in the Map. This is rather inefficient, both for the extra storage and since extracting all the values from the map requires repeated lookup operations. Plus the extra overhead/mistake potential of keeping the key Set synced with the Map.
It should be possible to directly support this. IAVL is designed specifically with this use case in mind, keys are stored sequentially and there are operations to iterate over all keys/values in a tree or within a key range. This behavior is exposed through the gRPC layer with the
List
procedure.I would propose adding methods such as:
keys
andtoMap
/toList
to the Map Store interface which would need to be backed by aniterate
method in the RawStore/IAVLStore to get all keys/values under a particular prefix/substore.I think this could also be used to improve the efficiency of operations like
foldl
inList
andArray
since they are currently using repeated lookups to access sequentially stored values.The text was updated successfully, but these errors were encountered: