From f422c550eb2adc499900f0539d841d250be0471b Mon Sep 17 00:00:00 2001 From: srdtrk Date: Sun, 21 Aug 2022 22:47:30 +0300 Subject: [PATCH 01/11] minor improvements to keymap and readme. Keymap now takes a reference when inserting --- packages/storage/Readme.md | 18 ++++---- packages/storage/src/keymap.rs | 80 ++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 42 deletions(-) diff --git a/packages/storage/Readme.md b/packages/storage/Readme.md index 0668538..caa53f9 100644 --- a/packages/storage/Readme.md +++ b/packages/storage/Readme.md @@ -9,7 +9,7 @@ This package contains many tools related to storage access patterns. This readme To import this package, add one of the following lines to your `Cargo.toml` file ```toml -secret-toolkit = { version = "0.3", default-features = false, features = ["utils", "storage", "serialization"] } +secret-toolkit = { version = "0.4", default-features = false, features = ["utils", "storage", "serialization"] } ``` for the release versions, or @@ -43,7 +43,7 @@ pub static OWNER: Item = Item::new(b"owner"); This uses Bincode2 to serde HumanAddr by default. To specify the Serde algorithm as Json, first import it from `secret-toolkit-serialization` ```ignore -use secret_toolkit_serialization::{Bincode2, Json}; +use secret_toolkit::serialization::{Bincode2, Json}; ``` then @@ -144,7 +144,7 @@ This is a storage wrapper based on AppendStore that replicates a double ended li To import and intialize this storage object as a static constant in `state.rs`, do the following: ```ignore -use secret_toolkit_storage::{DequeStore} +use secret_toolkit::storage::{DequeStore} ``` ```ignore @@ -173,7 +173,7 @@ be returned in each page. To import and intialize this storage object as a static constant in `state.rs`, do the following: ```ignore -use secret_toolkit_storage::{Keymap} +use secret_toolkit::storage::{Keymap} ``` ```ignore @@ -208,7 +208,7 @@ let foo = Foo { votes: 1111, }; -ADDR_VOTE.insert(&mut deps.storage, &user_addr, foo.clone())?; +ADDR_VOTE.insert(&mut deps.storage, &user_addr, &foo)?; // Compiler knows that this is Foo let read_foo = ADDR_VOTE.get(&deps.storage, &user_addr).unwrap(); assert_eq!(read_foo, foo1); @@ -241,8 +241,8 @@ fn test_keymap_iter_keys() -> StdResult<()> { let key1 = "key1".to_string(); let key2 = "key2".to_string(); - keymap.insert(&mut storage, &key1, foo1.clone())?; - keymap.insert(&mut storage, &key2, foo2.clone())?; + keymap.insert(&mut storage, &key1, &foo1)?; + keymap.insert(&mut storage, &key2, &foo2)?; let mut x = keymap.iter_keys(&storage)?; let (len, _) = x.size_hint(); @@ -270,8 +270,8 @@ fn test_keymap_iter() -> StdResult<()> { number: 1111, }; - keymap.insert(&mut storage, &b"key1".to_vec(), foo1.clone())?; - keymap.insert(&mut storage, &b"key2".to_vec(), foo2.clone())?; + keymap.insert(&mut storage, &b"key1".to_vec(), &foo1)?; + keymap.insert(&mut storage, &b"key2".to_vec(), &foo2)?; let mut x = keymap.iter(&storage)?; let (len, _) = x.size_hint(); diff --git a/packages/storage/src/keymap.rs b/packages/storage/src/keymap.rs index a3f3ad3..ad92ef7 100644 --- a/packages/storage/src/keymap.rs +++ b/packages/storage/src/keymap.rs @@ -20,12 +20,29 @@ fn _page_from_position(position: u32) -> u32 { } #[derive(Serialize, Deserialize)] -struct InternalItem -// where -// T: Serialize + DeserializeOwned, +struct InternalItem +where + T: Serialize + DeserializeOwned, + Ser: Serde, { - item: T, + item: Vec, index_pos: u32, + item_type: PhantomData, + serialization_type: PhantomData, +} + +impl InternalItem { + fn new(index_pos: u32, item: &T) -> StdResult { + Ok(Self { + item: Ser::serialize(item)?, + index_pos, + item_type: PhantomData, + serialization_type: PhantomData, + }) + } + fn get_item(&self) -> StdResult { + Ser::deserialize(&self.item) + } } pub struct Keymap<'a, K, T, Ser = Bincode2> @@ -148,7 +165,7 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: /// user facing get function pub fn get(&self, storage: &S, key: &K) -> Option { if let Ok(internal_item) = self._get_from_key(storage, key) { - Some(internal_item.item) + internal_item.get_item().ok() } else { None } @@ -223,13 +240,13 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: Ok(()) } /// user facing insert function - pub fn insert(&self, storage: &mut S, key: &K, item: T) -> StdResult<()> { + pub fn insert(&self, storage: &mut S, key: &K, item: &T) -> StdResult<()> { let key_vec = self.serialize_key(key)?; match self.may_load_impl(storage, &key_vec)? { - Some(mut existing_internal_item) => { + Some(existing_internal_item) => { // if item already exists - existing_internal_item.item = item; - self.save_impl(storage, &key_vec, &existing_internal_item) + let new_internal_item = InternalItem::new(existing_internal_item.index_pos, item)?; + self.save_impl(storage, &key_vec, &new_internal_item) } None => { // not already saved @@ -237,10 +254,7 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: self.set_len(storage, pos + 1)?; let page = _page_from_position(pos); // save the item - let internal_item = InternalItem { - item, - index_pos: pos, - }; + let internal_item = InternalItem::new(pos, item)?; self.save_impl(storage, &key_vec, &internal_item)?; // add index let mut indexes = self._get_indexes(storage, page)?; @@ -367,7 +381,7 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: for i in start_page_pos..=end_page_pos { let key_vec = &indexes[i as usize]; let key = self.deserialize_key(key_vec)?; - let item = self.load_impl(storage, key_vec)?.item; + let item = self.load_impl(storage, key_vec)?.get_item()?; res.push((key, item)); } } @@ -388,7 +402,7 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: let index = pos % PAGE_SIZE; let key_vec = &indexes[index as usize]; let key = self.deserialize_key(key_vec)?; - let item = self.load_impl(storage, key_vec)?.item; + let item = self.load_impl(storage, key_vec)?.get_item()?; Ok((key, item)) } /// Returns a readonly iterator only for keys. More efficient than iter(). @@ -1126,7 +1140,7 @@ mod tests { for i in 0..total_items { let key: Vec = (i as i32).to_be_bytes().to_vec(); - keymap.insert(&mut storage, &key, i)?; + keymap.insert(&mut storage, &key, &i)?; } assert_eq!(keymap.get_len(&storage)?, 1000); @@ -1143,7 +1157,7 @@ mod tests { let keymap: Keymap = Keymap::new(b"test"); for i in 0..total_items { - keymap.insert(&mut storage, &i, i)?; + keymap.insert(&mut storage, &i, &i)?; } for i in 0..total_items { @@ -1165,7 +1179,7 @@ mod tests { for i in 0..total_items { let key: Vec = (i as i32).to_be_bytes().to_vec(); - keymap.insert(&mut storage, &key, i)?; + keymap.insert(&mut storage, &key, &i)?; } for i in 0..((total_items / page_size) - 1) { @@ -1193,7 +1207,7 @@ mod tests { let keymap: Keymap = Keymap::new(b"test"); for i in 0..total_items { - keymap.insert(&mut storage, &(i as i32), i)?; + keymap.insert(&mut storage, &(i as i32), &i)?; } let values = keymap.paging_keys(&storage, 0, page_size)?; @@ -1221,8 +1235,8 @@ mod tests { number: 1111, }; - keymap.insert(&mut storage, &b"key1".to_vec(), foo1.clone())?; - keymap.insert(&mut storage, &b"key2".to_vec(), foo2.clone())?; + keymap.insert(&mut storage, &b"key1".to_vec(), &foo1)?; + keymap.insert(&mut storage, &b"key2".to_vec(), &foo2)?; let read_foo1 = keymap.get(&storage, &b"key1".to_vec()).unwrap(); let read_foo2 = keymap.get(&storage, &b"key2".to_vec()).unwrap(); @@ -1242,7 +1256,7 @@ mod tests { number: 1111, }; - keymap.insert(&mut storage, &b"key1".to_vec(), foo1.clone())?; + keymap.insert(&mut storage, &b"key1".to_vec(), &foo1)?; let contains_k1 = keymap.contains(&storage, &b"key1".to_vec()); assert_eq!(contains_k1, true); @@ -1264,8 +1278,8 @@ mod tests { number: 1111, }; - keymap.insert(&mut storage, &b"key1".to_vec(), foo1.clone())?; - keymap.insert(&mut storage, &b"key2".to_vec(), foo2.clone())?; + keymap.insert(&mut storage, &b"key1".to_vec(), &foo1)?; + keymap.insert(&mut storage, &b"key2".to_vec(), &foo2)?; let mut x = keymap.iter(&storage)?; let (len, _) = x.size_hint(); @@ -1295,8 +1309,8 @@ mod tests { let key1 = "key1".to_string(); let key2 = "key2".to_string(); - keymap.insert(&mut storage, &key1, foo1.clone())?; - keymap.insert(&mut storage, &key2, foo2.clone())?; + keymap.insert(&mut storage, &key1, &foo1)?; + keymap.insert(&mut storage, &key2, &foo2)?; let mut x = keymap.iter_keys(&storage)?; let (len, _) = x.size_hint(); @@ -1323,8 +1337,8 @@ mod tests { number: 2222, }; - keymap.insert(&mut storage, &b"key1".to_vec(), foo1.clone())?; - keymap.insert(&mut storage, &b"key1".to_vec(), foo2.clone())?; + keymap.insert(&mut storage, &b"key1".to_vec(), &foo1)?; + keymap.insert(&mut storage, &b"key1".to_vec(), &foo2)?; let foo3 = keymap.get(&storage, &b"key1".to_vec()).unwrap(); @@ -1347,8 +1361,8 @@ mod tests { string: "string one".to_string(), number: 1111, }; - keymap.insert(&mut storage, &"key1".to_string(), foo1.clone())?; - keymap.insert(&mut storage, &"key2".to_string(), foo2.clone())?; + keymap.insert(&mut storage, &"key1".to_string(), &foo1)?; + keymap.insert(&mut storage, &"key2".to_string(), &foo2)?; let read_foo1 = keymap.get(&storage, &"key1".to_string()).unwrap(); let read_foo2 = keymap.get(&storage, &"key2".to_string()).unwrap(); @@ -1398,12 +1412,12 @@ mod tests { let key1 = "k1".to_string(); let key2 = "k2".to_string(); - keymap.insert(&mut storage, &key1, foo1.clone())?; + keymap.insert(&mut storage, &key1, &foo1)?; assert_eq!(keymap.get_len(&storage)?, 1); assert!(keymap.length.lock().unwrap().eq(&Some(1))); // add another item - keymap.insert(&mut storage, &key2, foo2.clone())?; + keymap.insert(&mut storage, &key2, &foo2)?; assert_eq!(keymap.get_len(&storage)?, 2); assert!(keymap.length.lock().unwrap().eq(&Some(2))); @@ -1413,7 +1427,7 @@ mod tests { assert!(keymap.length.lock().unwrap().eq(&Some(1))); // override item (should not change length) - keymap.insert(&mut storage, &key2, foo1)?; + keymap.insert(&mut storage, &key2, &foo1)?; assert_eq!(keymap.get_len(&storage)?, 1); assert!(keymap.length.lock().unwrap().eq(&Some(1))); From f01628bbe8dc6084fb17eec257bfbee27454ade2 Mon Sep 17 00:00:00 2001 From: srdtrk Date: Sun, 21 Aug 2022 23:14:13 +0300 Subject: [PATCH 02/11] fixed some clippy errors --- packages/storage/src/append_store.rs | 6 +++--- packages/storage/src/deque_store.rs | 8 ++++---- packages/storage/src/item.rs | 5 +---- packages/storage/src/keymap.rs | 8 ++++---- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/packages/storage/src/append_store.rs b/packages/storage/src/append_store.rs index 2a5e83f..e980cfd 100644 --- a/packages/storage/src/append_store.rs +++ b/packages/storage/src/append_store.rs @@ -191,11 +191,11 @@ impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> AppendStore<'a, T, Ser> { impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> Clone for AppendStore<'a, T, Ser> { fn clone(&self) -> Self { Self { - namespace: self.namespace.clone(), + namespace: self.namespace, prefix: self.prefix.clone(), length: Mutex::new(None), - item_type: self.item_type.clone(), - serialization_type: self.serialization_type.clone(), + item_type: self.item_type, + serialization_type: self.serialization_type, } } } diff --git a/packages/storage/src/deque_store.rs b/packages/storage/src/deque_store.rs index 67dd190..2d24424 100644 --- a/packages/storage/src/deque_store.rs +++ b/packages/storage/src/deque_store.rs @@ -34,7 +34,7 @@ where serialization_type: PhantomData, } -impl<'a, 'b, T: Serialize + DeserializeOwned, Ser: Serde> DequeStore<'a, T, Ser> { +impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> DequeStore<'a, T, Ser> { /// constructor pub const fn new(prefix: &'a [u8]) -> Self { Self { @@ -301,12 +301,12 @@ impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> DequeStore<'a, T, Ser> { impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> Clone for DequeStore<'a, T, Ser> { fn clone(&self) -> Self { Self { - namespace: self.namespace.clone(), + namespace: self.namespace, prefix: self.prefix.clone(), length: Mutex::new(None), offset: Mutex::new(None), - item_type: self.item_type.clone(), - serialization_type: self.serialization_type.clone(), + item_type: self.item_type, + serialization_type: self.serialization_type, } } } diff --git a/packages/storage/src/item.rs b/packages/storage/src/item.rs index 60cf6f6..8ea9b28 100644 --- a/packages/storage/src/item.rs +++ b/packages/storage/src/item.rs @@ -55,10 +55,7 @@ where /// efficient way to see if any object is currently saved. pub fn is_empty(&self, storage: &S) -> bool { - match storage.get(self.as_slice()) { - Some(_) => false, - None => true, - } + storage.get(self.as_slice()).is_none() } /// Loads the data, perform the specified action, and store the result diff --git a/packages/storage/src/keymap.rs b/packages/storage/src/keymap.rs index ad92ef7..ae387aa 100644 --- a/packages/storage/src/keymap.rs +++ b/packages/storage/src/keymap.rs @@ -439,12 +439,12 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: { fn clone(&self) -> Self { Self { - namespace: self.namespace.clone(), + namespace: self.namespace, prefix: self.prefix.clone(), length: Mutex::new(None), - key_type: self.key_type.clone(), - item_type: self.item_type.clone(), - serialization_type: self.serialization_type.clone(), + key_type: self.key_type, + item_type: self.item_type, + serialization_type: self.serialization_type, } } } From 9cbdda66b0ceb36daefbdcc07b76da08b52f53fb Mon Sep 17 00:00:00 2001 From: srdtrk Date: Sun, 21 Aug 2022 23:42:51 +0300 Subject: [PATCH 03/11] testing changes to clone --- packages/storage/src/keymap.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/storage/src/keymap.rs b/packages/storage/src/keymap.rs index ae387aa..7bc94e3 100644 --- a/packages/storage/src/keymap.rs +++ b/packages/storage/src/keymap.rs @@ -442,9 +442,9 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: namespace: self.namespace, prefix: self.prefix.clone(), length: Mutex::new(None), - key_type: self.key_type, - item_type: self.item_type, - serialization_type: self.serialization_type, + key_type: PhantomData, + item_type: PhantomData, + serialization_type: PhantomData, } } } From 8ec8d58b113aa4cc60547641472b416a6b067a0d Mon Sep 17 00:00:00 2001 From: srdtrk Date: Sun, 21 Aug 2022 23:58:07 +0300 Subject: [PATCH 04/11] updated the clone method --- packages/storage/src/append_store.rs | 4 ++-- packages/storage/src/deque_store.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/storage/src/append_store.rs b/packages/storage/src/append_store.rs index e980cfd..3050a59 100644 --- a/packages/storage/src/append_store.rs +++ b/packages/storage/src/append_store.rs @@ -194,8 +194,8 @@ impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> Clone for AppendStore<'a, namespace: self.namespace, prefix: self.prefix.clone(), length: Mutex::new(None), - item_type: self.item_type, - serialization_type: self.serialization_type, + item_type: PhantomData, + serialization_type: PhantomData, } } } diff --git a/packages/storage/src/deque_store.rs b/packages/storage/src/deque_store.rs index 2d24424..93565ad 100644 --- a/packages/storage/src/deque_store.rs +++ b/packages/storage/src/deque_store.rs @@ -305,8 +305,8 @@ impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> Clone for DequeStore<'a, T prefix: self.prefix.clone(), length: Mutex::new(None), offset: Mutex::new(None), - item_type: self.item_type, - serialization_type: self.serialization_type, + item_type: PhantomData, + serialization_type: PhantomData, } } } From 28ed6984de2cad302c61659365ba4356693364c1 Mon Sep 17 00:00:00 2001 From: srdtrk Date: Mon, 22 Aug 2022 03:20:56 +0300 Subject: [PATCH 05/11] fixed a new serde bug in keymap, should be more efficient now too --- packages/storage/src/keymap.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/storage/src/keymap.rs b/packages/storage/src/keymap.rs index 7bc94e3..9645e4e 100644 --- a/packages/storage/src/keymap.rs +++ b/packages/storage/src/keymap.rs @@ -20,7 +20,7 @@ fn _page_from_position(position: u32) -> u32 { } #[derive(Serialize, Deserialize)] -struct InternalItem +struct InternalItem where T: Serialize + DeserializeOwned, Ser: Serde, @@ -175,7 +175,7 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: &self, storage: &S, key: &K, - ) -> StdResult> { + ) -> StdResult> { let key_vec = self.serialize_key(key)?; self.load_impl(storage, &key_vec) } @@ -423,7 +423,7 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: } impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: Serde> - PrefixedTypedStorage, Ser> for Keymap<'a, K, T, Ser> + PrefixedTypedStorage, Bincode2> for Keymap<'a, K, T, Ser> { fn as_slice(&self) -> &[u8] { if let Some(prefix) = &self.prefix { From 9edbe9e9c5c9a993090615b642c67ab79c318218 Mon Sep 17 00:00:00 2001 From: srdtrk Date: Mon, 22 Aug 2022 03:42:10 +0300 Subject: [PATCH 06/11] put the correct version of storage in cargo.toml, releases.md was auto-formatted (no actual change in display) --- Releases.md | 22 ++++++++++++++++------ packages/storage/src/keymap.rs | 6 +++--- packages/toolkit/Cargo.toml | 2 +- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Releases.md b/Releases.md index 0d61b54..a03ca2a 100644 --- a/Releases.md +++ b/Releases.md @@ -5,12 +5,14 @@ * BUGFIX: `Item::is_empty` was returning the opposite value from what you'd expect. ## v0.4.0 + This release mostly includes the work of @srdtrk in #53. Thanks Srdtrk! It revamps the `secret-toolkit-storage` package to make it more similar to `cw-storage-plus` and much easier to use. It also removes the `Cashmap` type from the incubator in favor of `KeyMap` in `secret-toolkit-storage`. This is a summary of the changes and additions in this release: + * Minimum Rust version is bumped to the latest v1.63. This is because we want to use `Mutex::new` in a `const fn`. * No more distinction between `Readonly*` and `*Mut` types. Instead, methods take references or mutable references to the storage every time. * Usage of `PrefixedStore` is made mostly unnecessary. @@ -23,20 +25,24 @@ A full guide to using the new `storage` types can be found [in the package's readme file](https://github.com/srdtrk/secret-toolkit/blob/3725530aebe149d14f7f3f1662844340eb27e015/packages/storage/Readme.md). ## secret-toolkit-incubator v0.3.1 + * Fixed compilation issue with Rust v1.61 (#46, #48) * Removed Siphasher dependency (#46, #48) ## secret-toolkit-utils v0.3.1 ### Security + * BUGFIX: `secret-toolkit::utils::FeatureToggle::handle_pause` had an inverse authorization check: only non-pausers could pause features. ## secret-toolkit-permit v0.3.1 + * Removed the `ecc-secp256k1` feature from `secret-toolkit-crypto` dependency of `secret-toolkit-permit`. - * This tiny change significantly reduces the size of binaries that only use the permit feature. + * This tiny change significantly reduces the size of binaries that only use the permit feature. ## v0.3.0 + * Added `clear` method to `AppendStore` and `DequeStore` to quickly reset the collections (#34) * docs.rs documentation now includes all sub-crates. * BUGFIX: `secret-toolkit::snip721::Metadata` was severely out of date with the SNIP-721 specification, and not useful. @@ -49,8 +55,9 @@ A full guide to using the new `storage` types can be found * Added `secret-toolkit::utils::feature_toggle` which allow managing feature flags in your contract. ### Breaking -* `secret-toolkit::permit::validate()` Now supports validating any type of Cosmos address. -Interface changes: Now takes a reference to the current token address instead + +* `secret-toolkit::permit::validate()` Now supports validating any type of Cosmos address. +Interface changes: Now takes a reference to the current token address instead of taking it by value and an optional hrp string. In addition, it returns a String and not HumanAddr. * Renamed `secret-toolkit::permit::Permission` to `secret-toolkit::permit::TokenPermission`. @@ -64,6 +71,7 @@ In addition, it returns a String and not HumanAddr. * `secret-toolkit-incubator` now has features `["cashmap", "generational-store"]` which are all off by default. ## v0.2.0 + This release includes a ton of new features, and a few breaking changes in various interfaces. This version is also the first released to [crates.io](https://crates.io)! @@ -73,7 +81,7 @@ This version is also the first released to [crates.io](https://crates.io)! * Added support for SNIP-22 messages (batch operations) * Added support for SNIP-23 messages (improved Send operations) which broke some interfaces * Added support for SNIP-24 permits -* Added `Base64Of`, `Base64JsonOf`, and `Base64Bincode2Of`, +* Added `Base64Of`, `Base64JsonOf`, and `Base64Bincode2Of`, which are wrappers that automatically deserializes base64 strings to `T`. It can be used in message types' fields instead of `Binary` when the contents of the string should have more specific contents. @@ -85,9 +93,11 @@ This version is also the first released to [crates.io](https://crates.io)! while `["crypto", "permit", "incubator"]` are left disabled by default. ## v0.1.1 + * Removed unused dev-dependency that was slowing down test compilation times. ## v0.1.0 + This is the first release of `secret-toolkit`. It supports: * `secret-toolkit::snip20` - Helper types and functions for interaction with @@ -102,6 +112,6 @@ This is the first release of `secret-toolkit`. It supports: * `secret-toolkit::serialization` - marker types for overriding the storage format used by types in `secret-toolkit::storage`. `Json` and `Bincode2`. * `secret-toolkit::utils` - General utilities for writing contract code. - * `padding` - tools for padding queries and responses. - * `calls` - Tools for marking types as messages in queries and callbacks + * `padding` - tools for padding queries and responses. + * `calls` - Tools for marking types as messages in queries and callbacks to other contracts. diff --git a/packages/storage/src/keymap.rs b/packages/storage/src/keymap.rs index 9645e4e..eae3ee7 100644 --- a/packages/storage/src/keymap.rs +++ b/packages/storage/src/keymap.rs @@ -25,7 +25,7 @@ where T: Serialize + DeserializeOwned, Ser: Serde, { - item: Vec, + item_vec: Vec, index_pos: u32, item_type: PhantomData, serialization_type: PhantomData, @@ -34,14 +34,14 @@ where impl InternalItem { fn new(index_pos: u32, item: &T) -> StdResult { Ok(Self { - item: Ser::serialize(item)?, + item_vec: Ser::serialize(item)?, index_pos, item_type: PhantomData, serialization_type: PhantomData, }) } fn get_item(&self) -> StdResult { - Ser::deserialize(&self.item) + Ser::deserialize(&self.item_vec) } } diff --git a/packages/toolkit/Cargo.toml b/packages/toolkit/Cargo.toml index ae51848..837cefe 100644 --- a/packages/toolkit/Cargo.toml +++ b/packages/toolkit/Cargo.toml @@ -33,6 +33,6 @@ secret-toolkit-permit = { version = "0.3.0", path = "../permit", optional = true secret-toolkit-serialization = { version = "0.3", path = "../serialization", optional = true } secret-toolkit-snip20 = { version = "0.3", path = "../snip20", optional = true } secret-toolkit-snip721 = { version = "0.3", path = "../snip721", optional = true } -secret-toolkit-storage = { version = "0.4", path = "../storage", optional = true } +secret-toolkit-storage = { version = "0.4.1", path = "../storage", optional = true } secret-toolkit-utils = { version = "0.3", path = "../utils", optional = true } secret-toolkit-viewing-key = { version = "0.3", path = "../viewing_key", optional = true } From d66e570b2f336a872446b5a326d5d4bd3ffc7900 Mon Sep 17 00:00:00 2001 From: srdtrk Date: Tue, 30 Aug 2022 17:19:59 +0300 Subject: [PATCH 07/11] fixed some clippy errors and took back an api changing update --- packages/storage/Readme.md | 4 +- packages/storage/src/append_store.rs | 2 +- packages/storage/src/deque_store.rs | 2 +- packages/storage/src/item.rs | 2 +- packages/storage/src/keymap.rs | 56 ++++++++++++++-------------- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/packages/storage/Readme.md b/packages/storage/Readme.md index caa53f9..aaedf4d 100644 --- a/packages/storage/Readme.md +++ b/packages/storage/Readme.md @@ -31,7 +31,7 @@ This is the simplest storage object in this toolkit. It based on the similarly n This object is meant to be initialized as a static constant in `state.rs`. However, it would also work perfectly fine if it was initialized during run time with a variable key (in this case though, you'd have to remind it what type of object is stored and its serde). Import it using the following lines: ```ignore -use secret_toolkit_storage::{Item} +use secret_toolkit::storage::{Item} ``` And initialize it using the following lines: @@ -178,7 +178,7 @@ use secret_toolkit::storage::{Keymap} ```ignore pub static ADDR_VOTE: Keymap = Keymap::new(b"vote"); -pub static BET_STORE: Keymap = Keymap::new(b"vote"); +pub static BET_STORE: Keymap = Keymap::new(b"bet"); ``` > ❗ Initializing the object as const instead of static will also work but be less efficient since the variable won't be able to cache length data. diff --git a/packages/storage/src/append_store.rs b/packages/storage/src/append_store.rs index 3050a59..095251d 100644 --- a/packages/storage/src/append_store.rs +++ b/packages/storage/src/append_store.rs @@ -221,7 +221,7 @@ impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> AppendStore<'a, T, Ser> { Ser::deserialize( &storage .get(&prefixed_key) - .ok_or(StdError::not_found(type_name::()))?, + .ok_or_else(|| StdError::not_found(type_name::()))?, ) } diff --git a/packages/storage/src/deque_store.rs b/packages/storage/src/deque_store.rs index 93565ad..d835532 100644 --- a/packages/storage/src/deque_store.rs +++ b/packages/storage/src/deque_store.rs @@ -280,7 +280,7 @@ impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> DequeStore<'a, T, Ser> { Ser::deserialize( &storage .get(&prefixed_key) - .ok_or(StdError::not_found(type_name::()))?, + .ok_or_else(|| StdError::not_found(type_name::()))?, ) } diff --git a/packages/storage/src/item.rs b/packages/storage/src/item.rs index 8ea9b28..2de3374 100644 --- a/packages/storage/src/item.rs +++ b/packages/storage/src/item.rs @@ -84,7 +84,7 @@ where Ser::deserialize( &storage .get(self.as_slice()) - .ok_or(StdError::not_found(type_name::()))?, + .ok_or_else(|| StdError::not_found(type_name::()))?, ) } diff --git a/packages/storage/src/keymap.rs b/packages/storage/src/keymap.rs index eae3ee7..42df00c 100644 --- a/packages/storage/src/keymap.rs +++ b/packages/storage/src/keymap.rs @@ -212,9 +212,9 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: let max_page = _page_from_position(len); if max_page == page { // last page indexes is the same as indexes - let last_key = indexes.pop().ok_or(StdError::generic_err( - "Last item's key not found - should never happen", - ))?; + let last_key = indexes.pop().ok_or_else(|| { + StdError::generic_err("Last item's key not found - should never happen") + })?; // modify last item let mut last_internal_item = self.load_impl(storage, &last_key)?; last_internal_item.index_pos = removed_pos; @@ -224,9 +224,9 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: self._set_indexes_page(storage, page, &indexes)?; } else { let mut last_page_indexes = self._get_indexes(storage, max_page)?; - let last_key = last_page_indexes.pop().ok_or(StdError::generic_err( - "Last item's key not found - should never happen", - ))?; + let last_key = last_page_indexes.pop().ok_or_else(|| { + StdError::generic_err("Last item's key not found - should never happen") + })?; // modify last item let mut last_internal_item = self.load_impl(storage, &last_key)?; last_internal_item.index_pos = removed_pos; @@ -240,12 +240,12 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: Ok(()) } /// user facing insert function - pub fn insert(&self, storage: &mut S, key: &K, item: &T) -> StdResult<()> { + pub fn insert(&self, storage: &mut S, key: &K, item: T) -> StdResult<()> { let key_vec = self.serialize_key(key)?; match self.may_load_impl(storage, &key_vec)? { Some(existing_internal_item) => { // if item already exists - let new_internal_item = InternalItem::new(existing_internal_item.index_pos, item)?; + let new_internal_item = InternalItem::new(existing_internal_item.index_pos, &item)?; self.save_impl(storage, &key_vec, &new_internal_item) } None => { @@ -254,7 +254,7 @@ impl<'a, K: Serialize + DeserializeOwned, T: Serialize + DeserializeOwned, Ser: self.set_len(storage, pos + 1)?; let page = _page_from_position(pos); // save the item - let internal_item = InternalItem::new(pos, item)?; + let internal_item = InternalItem::new(pos, &item)?; self.save_impl(storage, &key_vec, &internal_item)?; // add index let mut indexes = self._get_indexes(storage, page)?; @@ -1073,7 +1073,7 @@ trait PrefixedTypedStorage { Ser::deserialize( &storage .get(&prefixed_key) - .ok_or(StdError::not_found(type_name::()))?, + .ok_or_else(|| StdError::not_found(type_name::()))?, ) } @@ -1140,7 +1140,7 @@ mod tests { for i in 0..total_items { let key: Vec = (i as i32).to_be_bytes().to_vec(); - keymap.insert(&mut storage, &key, &i)?; + keymap.insert(&mut storage, &key, i)?; } assert_eq!(keymap.get_len(&storage)?, 1000); @@ -1157,7 +1157,7 @@ mod tests { let keymap: Keymap = Keymap::new(b"test"); for i in 0..total_items { - keymap.insert(&mut storage, &i, &i)?; + keymap.insert(&mut storage, &i, i)?; } for i in 0..total_items { @@ -1179,7 +1179,7 @@ mod tests { for i in 0..total_items { let key: Vec = (i as i32).to_be_bytes().to_vec(); - keymap.insert(&mut storage, &key, &i)?; + keymap.insert(&mut storage, &key, i)?; } for i in 0..((total_items / page_size) - 1) { @@ -1207,7 +1207,7 @@ mod tests { let keymap: Keymap = Keymap::new(b"test"); for i in 0..total_items { - keymap.insert(&mut storage, &(i as i32), &i)?; + keymap.insert(&mut storage, &(i as i32), i)?; } let values = keymap.paging_keys(&storage, 0, page_size)?; @@ -1235,8 +1235,8 @@ mod tests { number: 1111, }; - keymap.insert(&mut storage, &b"key1".to_vec(), &foo1)?; - keymap.insert(&mut storage, &b"key2".to_vec(), &foo2)?; + keymap.insert(&mut storage, &b"key1".to_vec(), foo1.clone())?; + keymap.insert(&mut storage, &b"key2".to_vec(), foo2.clone())?; let read_foo1 = keymap.get(&storage, &b"key1".to_vec()).unwrap(); let read_foo2 = keymap.get(&storage, &b"key2".to_vec()).unwrap(); @@ -1256,7 +1256,7 @@ mod tests { number: 1111, }; - keymap.insert(&mut storage, &b"key1".to_vec(), &foo1)?; + keymap.insert(&mut storage, &b"key1".to_vec(), foo1)?; let contains_k1 = keymap.contains(&storage, &b"key1".to_vec()); assert_eq!(contains_k1, true); @@ -1278,8 +1278,8 @@ mod tests { number: 1111, }; - keymap.insert(&mut storage, &b"key1".to_vec(), &foo1)?; - keymap.insert(&mut storage, &b"key2".to_vec(), &foo2)?; + keymap.insert(&mut storage, &b"key1".to_vec(), foo1.clone())?; + keymap.insert(&mut storage, &b"key2".to_vec(), foo2.clone())?; let mut x = keymap.iter(&storage)?; let (len, _) = x.size_hint(); @@ -1309,8 +1309,8 @@ mod tests { let key1 = "key1".to_string(); let key2 = "key2".to_string(); - keymap.insert(&mut storage, &key1, &foo1)?; - keymap.insert(&mut storage, &key2, &foo2)?; + keymap.insert(&mut storage, &key1, foo1)?; + keymap.insert(&mut storage, &key2, foo2)?; let mut x = keymap.iter_keys(&storage)?; let (len, _) = x.size_hint(); @@ -1337,8 +1337,8 @@ mod tests { number: 2222, }; - keymap.insert(&mut storage, &b"key1".to_vec(), &foo1)?; - keymap.insert(&mut storage, &b"key1".to_vec(), &foo2)?; + keymap.insert(&mut storage, &b"key1".to_vec(), foo1)?; + keymap.insert(&mut storage, &b"key1".to_vec(), foo2.clone())?; let foo3 = keymap.get(&storage, &b"key1".to_vec()).unwrap(); @@ -1361,8 +1361,8 @@ mod tests { string: "string one".to_string(), number: 1111, }; - keymap.insert(&mut storage, &"key1".to_string(), &foo1)?; - keymap.insert(&mut storage, &"key2".to_string(), &foo2)?; + keymap.insert(&mut storage, &"key1".to_string(), foo1.clone())?; + keymap.insert(&mut storage, &"key2".to_string(), foo2.clone())?; let read_foo1 = keymap.get(&storage, &"key1".to_string()).unwrap(); let read_foo2 = keymap.get(&storage, &"key2".to_string()).unwrap(); @@ -1412,12 +1412,12 @@ mod tests { let key1 = "k1".to_string(); let key2 = "k2".to_string(); - keymap.insert(&mut storage, &key1, &foo1)?; + keymap.insert(&mut storage, &key1, foo1.clone())?; assert_eq!(keymap.get_len(&storage)?, 1); assert!(keymap.length.lock().unwrap().eq(&Some(1))); // add another item - keymap.insert(&mut storage, &key2, &foo2)?; + keymap.insert(&mut storage, &key2, foo2)?; assert_eq!(keymap.get_len(&storage)?, 2); assert!(keymap.length.lock().unwrap().eq(&Some(2))); @@ -1427,7 +1427,7 @@ mod tests { assert!(keymap.length.lock().unwrap().eq(&Some(1))); // override item (should not change length) - keymap.insert(&mut storage, &key2, &foo1)?; + keymap.insert(&mut storage, &key2, foo1)?; assert_eq!(keymap.get_len(&storage)?, 1); assert!(keymap.length.lock().unwrap().eq(&Some(1))); From e2262dc6b033b86e5333d64618d0b5b892b3f0f8 Mon Sep 17 00:00:00 2001 From: srdtrk Date: Tue, 30 Aug 2022 18:13:36 +0300 Subject: [PATCH 08/11] added add_suffix functionality to Item. And implemented Clone for Item --- packages/storage/src/append_store.rs | 1 - packages/storage/src/deque_store.rs | 1 - packages/storage/src/item.rs | 35 +++++++++++++++++++++++++++- packages/storage/src/keymap.rs | 1 - 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/storage/src/append_store.rs b/packages/storage/src/append_store.rs index 095251d..7edafd1 100644 --- a/packages/storage/src/append_store.rs +++ b/packages/storage/src/append_store.rs @@ -24,7 +24,6 @@ where /// prefix of the newly constructed Storage namespace: &'a [u8], /// needed if any suffixes were added to the original namespace. - /// therefore it is not necessarily same as the namespace. prefix: Option>, length: Mutex>, item_type: PhantomData, diff --git a/packages/storage/src/deque_store.rs b/packages/storage/src/deque_store.rs index d835532..f55a800 100644 --- a/packages/storage/src/deque_store.rs +++ b/packages/storage/src/deque_store.rs @@ -26,7 +26,6 @@ where /// prefix of the newly constructed Storage namespace: &'a [u8], /// needed if any suffixes were added to the original namespace. - /// therefore it is not necessarily same as the namespace. prefix: Option>, length: Mutex>, offset: Mutex>, diff --git a/packages/storage/src/item.rs b/packages/storage/src/item.rs index 2de3374..254e1dd 100644 --- a/packages/storage/src/item.rs +++ b/packages/storage/src/item.rs @@ -13,6 +13,8 @@ where Ser: Serde, { storage_key: &'a [u8], + /// needed if any suffixes were added to the original storage key. + prefix: Option>, item_type: PhantomData, serialization_type: PhantomData, } @@ -21,10 +23,26 @@ impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> Item<'a, T, Ser> { pub const fn new(key: &'a [u8]) -> Self { Self { storage_key: key, + prefix: None, item_type: PhantomData, serialization_type: PhantomData, } } + /// This is used to produce a new Item. This can be used when you want to associate an Item to each user + /// and you still get to define the Item as a static constant + pub fn add_suffix(&self, suffix: &[u8]) -> Self { + let prefix = if let Some(prefix) = &self.prefix { + [prefix.clone(), suffix.to_vec()].concat() + } else { + [self.storage_key.to_vec(), suffix.to_vec()].concat() + }; + Self { + storage_key: self.storage_key, + prefix: Some(prefix), + item_type: self.item_type, + serialization_type: self.serialization_type, + } + } } impl<'a, T, Ser> Item<'a, T, Ser> @@ -122,7 +140,22 @@ where } fn as_slice(&self) -> &[u8] { - self.storage_key + if let Some(prefix) = &self.prefix { + prefix + } else { + self.storage_key + } + } +} + +impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> Clone for Item<'a, T, Ser> { + fn clone(&self) -> Self { + Self { + storage_key: self.storage_key, + prefix: self.prefix.clone(), + item_type: PhantomData, + serialization_type: PhantomData, + } } } diff --git a/packages/storage/src/keymap.rs b/packages/storage/src/keymap.rs index 42df00c..9a749a1 100644 --- a/packages/storage/src/keymap.rs +++ b/packages/storage/src/keymap.rs @@ -54,7 +54,6 @@ where /// prefix of the newly constructed Storage namespace: &'a [u8], /// needed if any suffixes were added to the original namespace. - /// therefore it is not necessarily same as the namespace. prefix: Option>, length: Mutex>, key_type: PhantomData, From cea36e78d7a9c73e86f9a8e19047ea55cea61cee Mon Sep 17 00:00:00 2001 From: srdtrk Date: Tue, 30 Aug 2022 18:19:45 +0300 Subject: [PATCH 09/11] added extra tests to Item --- packages/storage/src/item.rs | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/packages/storage/src/item.rs b/packages/storage/src/item.rs index 254e1dd..065b7e2 100644 --- a/packages/storage/src/item.rs +++ b/packages/storage/src/item.rs @@ -187,6 +187,43 @@ mod tests { Ok(()) } + #[test] + fn test_suffix() -> StdResult<()> { + let mut storage = MockStorage::new(); + let item: Item = Item::new(b"test"); + let item1 = item.add_suffix(b"suffix1"); + let item2 = item.add_suffix(b"suffix2"); + + item.save(&mut storage, &0)?; + assert!(item1.is_empty(&storage)); + assert!(item2.is_empty(&storage)); + + item1.save(&mut storage, &1)?; + assert!(!item1.is_empty(&storage)); + assert!(item2.is_empty(&storage)); + assert_eq!(item.may_load(&storage)?, Some(0)); + assert_eq!(item1.may_load(&storage)?, Some(1)); + item2.save(&mut storage, &2)?; + assert_eq!(item.may_load(&storage)?, Some(0)); + assert_eq!(item1.may_load(&storage)?, Some(1)); + assert_eq!(item2.may_load(&storage)?, Some(2)); + + Ok(()) + } + + #[test] + fn test_update() -> StdResult<()> { + let mut storage = MockStorage::new(); + let item: Item = Item::new(b"test"); + + assert!(item.update(&mut storage, |x| Ok(x + 1)).is_err()); + item.save(&mut storage, &7)?; + assert!(item.update(&mut storage, |x| Ok(x + 1)).is_ok()); + assert_eq!(item.load(&storage), Ok(8)); + + Ok(()) + } + #[test] fn test_serializations() -> StdResult<()> { // Check the default behavior is Bincode2 From fa049e03d2a84f846380dd0704eb355ab4c151d8 Mon Sep 17 00:00:00 2001 From: srdtrk Date: Tue, 30 Aug 2022 18:29:45 +0300 Subject: [PATCH 10/11] storage version updated to 0.4.2, release notes added --- Releases.md | 6 ++++++ packages/storage/Cargo.toml | 2 +- packages/toolkit/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Releases.md b/Releases.md index a03ca2a..682fdb5 100644 --- a/Releases.md +++ b/Releases.md @@ -1,5 +1,11 @@ # Release notes for the Secret Toolkit +## secret-toolkit-storage v0.4.2 + +* BUGFIX: clippy errors resolved +* Added `.add_suffix` and `.clone` methods to `secret-toolkit::storage::Item` +* Minor performance updates to `secret-toolkit::storage::Keymap` + ## secret-toolkit-storage v0.4.1 * BUGFIX: `Item::is_empty` was returning the opposite value from what you'd expect. diff --git a/packages/storage/Cargo.toml b/packages/storage/Cargo.toml index eb225ff..59cec5b 100644 --- a/packages/storage/Cargo.toml +++ b/packages/storage/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "secret-toolkit-storage" -version = "0.4.1" +version = "0.4.2" edition = "2018" authors = ["SCRT Labs "] license-file = "../../LICENSE" diff --git a/packages/toolkit/Cargo.toml b/packages/toolkit/Cargo.toml index 837cefe..ae51848 100644 --- a/packages/toolkit/Cargo.toml +++ b/packages/toolkit/Cargo.toml @@ -33,6 +33,6 @@ secret-toolkit-permit = { version = "0.3.0", path = "../permit", optional = true secret-toolkit-serialization = { version = "0.3", path = "../serialization", optional = true } secret-toolkit-snip20 = { version = "0.3", path = "../snip20", optional = true } secret-toolkit-snip721 = { version = "0.3", path = "../snip721", optional = true } -secret-toolkit-storage = { version = "0.4.1", path = "../storage", optional = true } +secret-toolkit-storage = { version = "0.4", path = "../storage", optional = true } secret-toolkit-utils = { version = "0.3", path = "../utils", optional = true } secret-toolkit-viewing-key = { version = "0.3", path = "../viewing_key", optional = true } From 9cc3694cf0dce99bf654a6487ea8628930a3089c Mon Sep 17 00:00:00 2001 From: srdtrk Date: Tue, 30 Aug 2022 18:42:15 +0300 Subject: [PATCH 11/11] changed release notes --- Releases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Releases.md b/Releases.md index 682fdb5..60279cf 100644 --- a/Releases.md +++ b/Releases.md @@ -2,7 +2,7 @@ ## secret-toolkit-storage v0.4.2 -* BUGFIX: clippy errors resolved +* BUGFIX: implementation of `.clone` method fixed * Added `.add_suffix` and `.clone` methods to `secret-toolkit::storage::Item` * Minor performance updates to `secret-toolkit::storage::Keymap`