-
Notifications
You must be signed in to change notification settings - Fork 335
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
Thoughts on keys #1676
Merged
Merged
Thoughts on keys #1676
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
6c415f9
Add storage keys docs and pull in some functions
webmaster128 712e178
Use to_length_prefixed, to_length_prefixed_nested from cosmwasm-std
webmaster128 f5dad70
Create namespace_with_key
webmaster128 46b4830
Update packages/std/src/lib.rs
webmaster128 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# Storage keys | ||
|
||
CosmWasm provides a generic key value store to contract developers via the | ||
`Storage` trait. This is powerful but the nature of low level byte operations | ||
makes it hard to use for high level storage types. In this document we discuss | ||
the foundations of storage key composition all the way up to cw-storage-plus. | ||
|
||
In a simple world, all you need is a `&[u8]` key which you can get e.g. using | ||
`&17u64.to_be_bytes()`. This is an 8 bytes key with an encoded integer. But if | ||
you have multiple data types in your contract, you want to prefix those keys in | ||
order to avoid collisions. A simple concatenation is not sufficient because you | ||
want to avoid collisions when part of the prefixes and part of the key overlap. | ||
E.g. `b"keya" | b"x"` and `b"key" | b"ax"` (`|` denotes concatenation) must not | ||
have the same binary representation. | ||
|
||
In the early days, multiple approaches of key namespacing were discussed and | ||
were documented here: https://github.com/webmaster128/key-namespacing. The "0x00 | ||
separated ASCIIHEX" approach was never used but "Length-prefixed keys" is used. | ||
|
||
To recap, Length-prefixed keys have the following layout: | ||
|
||
``` | ||
len(namespace_1) | namespace_1 | ||
| len(namespace_2) | namespace_2 | ||
| len(namespace_3) | namespace_3 | ||
| ... | ||
| len(namespace_m) | namespace_m | ||
| key | ||
``` | ||
|
||
In this repo (package `cosmwasm-storage`), the following functions were | ||
implemented: | ||
|
||
```rust | ||
pub fn to_length_prefixed(namespace: &[u8]) -> Vec<u8> | ||
|
||
pub fn to_length_prefixed_nested(namespaces: &[&[u8]]) -> Vec<u8> | ||
|
||
fn concat(namespace: &[u8], key: &[u8]) -> Vec<u8> | ||
``` | ||
|
||
With the emerging cw-storage-plus we see two additions to that approach: | ||
|
||
1. Manually creating the namespace and concatenating it with `concat` makes no | ||
sense anymore. Instead `namespace` and `key` are always provided and a | ||
composed database key is created. | ||
2. Using a multi component namespace becomes the norm. | ||
|
||
This led to the following addition in cw-storage-plus: | ||
|
||
```rust | ||
/// This is equivalent concat(to_length_prefixed_nested(namespaces), key) | ||
/// But more efficient when the intermediate namespaces often must be recalculated | ||
pub(crate) fn namespaces_with_key(namespaces: &[&[u8]], key: &[u8]) -> Vec<u8> { | ||
``` | ||
|
||
In contrast to `concat(to_length_prefixed_nested(namespaces), key)` this direct | ||
implementation saves once vector allocation since the final length can be | ||
pre-computed and reserved. Also it's shorter to use. | ||
|
||
Also since `to_length_prefixed` returns the same result as | ||
`to_length_prefixed_nested` when called with one namespace element, there is no | ||
good reason to preserve the single component version. | ||
|
||
## 2023 updates | ||
|
||
With the deprecation if cosmwasm-storage and the adoption of the system in | ||
cw-storage-plus, it is time to do a few changes to the Length-prefixed keys | ||
standard, without breaking existing users. | ||
|
||
1. Remove the single component `to_length_prefixed` implementation and fully | ||
commit to the multi-component version. This shifts focus from the recursive | ||
implementation to the compatible iterative implementation. | ||
2. Rename "namespaces" to just "namespace" and let one namespace have multiple | ||
components. | ||
3. Adopt the combined namespace + key encoder `namespaces_with_key` from | ||
cw-storage-plus. | ||
4. Add a decomposition implementation | ||
|
||
Given the importance of Length-prefixed keys for the entire CosmWasm ecosystem, | ||
those implementations should be maintained in cosmwasm-std. The generic approach | ||
allows building all sorts of storage solutions on top of it and it allows | ||
indexers to parse storage keys for all of them. | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
mod length_prefixed; | ||
|
||
// Please note that the entire storage_keys module is public. So be careful | ||
// when adding elements here. | ||
pub use length_prefixed::{namespace_with_key, to_length_prefixed, to_length_prefixed_nested}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,15 @@ | ||
mod bucket; | ||
mod length_prefixed; | ||
mod namespace_helpers; | ||
mod prefixed_storage; | ||
mod sequence; | ||
mod singleton; | ||
mod type_helpers; | ||
|
||
pub use bucket::{bucket, bucket_read, Bucket, ReadonlyBucket}; | ||
pub use length_prefixed::{to_length_prefixed, to_length_prefixed_nested}; | ||
webmaster128 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
pub use prefixed_storage::{prefixed, prefixed_read, PrefixedStorage, ReadonlyPrefixedStorage}; | ||
pub use sequence::{currval, nextval, sequence}; | ||
pub use singleton::{singleton, singleton_read, ReadonlySingleton, Singleton}; | ||
|
||
// Re-exported for backwads compatibility. | ||
// See https://github.com/CosmWasm/cosmwasm/pull/1676. | ||
pub use cosmwasm_std::storage_keys::{to_length_prefixed, to_length_prefixed_nested}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏼