Skip to content

Commit 6f06d3d

Browse files
authored
Merge pull request #57 from srdtrk/master
Fixed clippy errors and made minor bugfixes to storage readme
2 parents 2492182 + 9cc3694 commit 6f06d3d

File tree

7 files changed

+162
-68
lines changed

7 files changed

+162
-68
lines changed

Releases.md

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
# Release notes for the Secret Toolkit
22

3+
## secret-toolkit-storage v0.4.2
4+
5+
* BUGFIX: implementation of `.clone` method fixed
6+
* Added `.add_suffix` and `.clone` methods to `secret-toolkit::storage::Item`
7+
* Minor performance updates to `secret-toolkit::storage::Keymap`
8+
39
## secret-toolkit-storage v0.4.1
410

511
* BUGFIX: `Item::is_empty` was returning the opposite value from what you'd expect.
612

713
## v0.4.0
14+
815
This release mostly includes the work of @srdtrk in #53. Thanks Srdtrk!
916

1017
It revamps the `secret-toolkit-storage` package to make it more similar to `cw-storage-plus` and much easier
1118
to use. It also removes the `Cashmap` type from the incubator in favor of `KeyMap` in `secret-toolkit-storage`.
1219

1320
This is a summary of the changes and additions in this release:
21+
1422
* Minimum Rust version is bumped to the latest v1.63. This is because we want to use `Mutex::new` in a `const fn`.
1523
* No more distinction between `Readonly*` and `*Mut` types. Instead, methods take references or mutable references to the storage every time.
1624
* Usage of `PrefixedStore` is made mostly unnecessary.
@@ -23,20 +31,24 @@ A full guide to using the new `storage` types can be found
2331
[in the package's readme file](https://github.com/srdtrk/secret-toolkit/blob/3725530aebe149d14f7f3f1662844340eb27e015/packages/storage/Readme.md).
2432

2533
## secret-toolkit-incubator v0.3.1
34+
2635
* Fixed compilation issue with Rust v1.61 (#46, #48)
2736
* Removed Siphasher dependency (#46, #48)
2837

2938
## secret-toolkit-utils v0.3.1
3039

3140
### Security
41+
3242
* BUGFIX: `secret-toolkit::utils::FeatureToggle::handle_pause` had an inverse authorization check: only non-pausers
3343
could pause features.
3444

3545
## secret-toolkit-permit v0.3.1
46+
3647
* Removed the `ecc-secp256k1` feature from `secret-toolkit-crypto` dependency of `secret-toolkit-permit`.
37-
* This tiny change significantly reduces the size of binaries that only use the permit feature.
48+
* This tiny change significantly reduces the size of binaries that only use the permit feature.
3849

3950
## v0.3.0
51+
4052
* Added `clear` method to `AppendStore` and `DequeStore` to quickly reset the collections (#34)
4153
* docs.rs documentation now includes all sub-crates.
4254
* BUGFIX: `secret-toolkit::snip721::Metadata` was severely out of date with the SNIP-721 specification, and not useful.
@@ -49,8 +61,9 @@ A full guide to using the new `storage` types can be found
4961
* Added `secret-toolkit::utils::feature_toggle` which allow managing feature flags in your contract.
5062

5163
### Breaking
52-
* `secret-toolkit::permit::validate()` Now supports validating any type of Cosmos address.
53-
Interface changes: Now takes a reference to the current token address instead
64+
65+
* `secret-toolkit::permit::validate()` Now supports validating any type of Cosmos address.
66+
Interface changes: Now takes a reference to the current token address instead
5467
of taking it by value and an optional hrp string.
5568
In addition, it returns a String and not HumanAddr.
5669
* Renamed `secret-toolkit::permit::Permission` to `secret-toolkit::permit::TokenPermission`.
@@ -64,6 +77,7 @@ In addition, it returns a String and not HumanAddr.
6477
* `secret-toolkit-incubator` now has features `["cashmap", "generational-store"]` which are all off by default.
6578

6679
## v0.2.0
80+
6781
This release includes a ton of new features, and a few breaking changes in various interfaces.
6882
This version is also the first released to [crates.io](https://crates.io)!
6983

@@ -73,7 +87,7 @@ This version is also the first released to [crates.io](https://crates.io)!
7387
* Added support for SNIP-22 messages (batch operations)
7488
* Added support for SNIP-23 messages (improved Send operations) which broke some interfaces
7589
* Added support for SNIP-24 permits
76-
* Added `Base64Of<S: Serde, T>`, `Base64JsonOf<T>`, and `Base64Bincode2Of<T>`,
90+
* Added `Base64Of<S: Serde, T>`, `Base64JsonOf<T>`, and `Base64Bincode2Of<T>`,
7791
which are wrappers that automatically deserializes base64 strings to `T`.
7892
It can be used in message types' fields instead of `Binary` when the contents of the string
7993
should have more specific contents.
@@ -85,9 +99,11 @@ This version is also the first released to [crates.io](https://crates.io)!
8599
while `["crypto", "permit", "incubator"]` are left disabled by default.
86100

87101
## v0.1.1
102+
88103
* Removed unused dev-dependency that was slowing down test compilation times.
89104

90105
## v0.1.0
106+
91107
This is the first release of `secret-toolkit`. It supports:
92108

93109
* `secret-toolkit::snip20` - Helper types and functions for interaction with
@@ -102,6 +118,6 @@ This is the first release of `secret-toolkit`. It supports:
102118
* `secret-toolkit::serialization` - marker types for overriding the storage
103119
format used by types in `secret-toolkit::storage`. `Json` and `Bincode2`.
104120
* `secret-toolkit::utils` - General utilities for writing contract code.
105-
* `padding` - tools for padding queries and responses.
106-
* `calls` - Tools for marking types as messages in queries and callbacks
121+
* `padding` - tools for padding queries and responses.
122+
* `calls` - Tools for marking types as messages in queries and callbacks
107123
to other contracts.

packages/storage/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "secret-toolkit-storage"
3-
version = "0.4.1"
3+
version = "0.4.2"
44
edition = "2018"
55
authors = ["SCRT Labs <[email protected]>"]
66
license-file = "../../LICENSE"

packages/storage/Readme.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ This package contains many tools related to storage access patterns. This readme
99
To import this package, add one of the following lines to your `Cargo.toml` file
1010

1111
```toml
12-
secret-toolkit = { version = "0.3", default-features = false, features = ["utils", "storage", "serialization"] }
12+
secret-toolkit = { version = "0.4", default-features = false, features = ["utils", "storage", "serialization"] }
1313
```
1414

1515
for the release versions, or
@@ -31,7 +31,7 @@ This is the simplest storage object in this toolkit. It based on the similarly n
3131
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:
3232

3333
```ignore
34-
use secret_toolkit_storage::{Item}
34+
use secret_toolkit::storage::{Item}
3535
```
3636

3737
And initialize it using the following lines:
@@ -43,7 +43,7 @@ pub static OWNER: Item<HumanAddr> = Item::new(b"owner");
4343
This uses Bincode2 to serde HumanAddr by default. To specify the Serde algorithm as Json, first import it from `secret-toolkit-serialization`
4444

4545
```ignore
46-
use secret_toolkit_serialization::{Bincode2, Json};
46+
use secret_toolkit::serialization::{Bincode2, Json};
4747
```
4848

4949
then
@@ -144,7 +144,7 @@ This is a storage wrapper based on AppendStore that replicates a double ended li
144144
To import and intialize this storage object as a static constant in `state.rs`, do the following:
145145

146146
```ignore
147-
use secret_toolkit_storage::{DequeStore}
147+
use secret_toolkit::storage::{DequeStore}
148148
```
149149

150150
```ignore
@@ -173,12 +173,12 @@ be returned in each page.
173173
To import and intialize this storage object as a static constant in `state.rs`, do the following:
174174

175175
```ignore
176-
use secret_toolkit_storage::{Keymap}
176+
use secret_toolkit::storage::{Keymap}
177177
```
178178

179179
```ignore
180180
pub static ADDR_VOTE: Keymap<HumanAddr, Foo> = Keymap::new(b"vote");
181-
pub static BET_STORE: Keymap<u32, BetInfo> = Keymap::new(b"vote");
181+
pub static BET_STORE: Keymap<u32, BetInfo> = Keymap::new(b"bet");
182182
```
183183

184184
> ❗ 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.
@@ -208,7 +208,7 @@ let foo = Foo {
208208
votes: 1111,
209209
};
210210
211-
ADDR_VOTE.insert(&mut deps.storage, &user_addr, foo.clone())?;
211+
ADDR_VOTE.insert(&mut deps.storage, &user_addr, &foo)?;
212212
// Compiler knows that this is Foo
213213
let read_foo = ADDR_VOTE.get(&deps.storage, &user_addr).unwrap();
214214
assert_eq!(read_foo, foo1);
@@ -241,8 +241,8 @@ fn test_keymap_iter_keys() -> StdResult<()> {
241241
let key1 = "key1".to_string();
242242
let key2 = "key2".to_string();
243243
244-
keymap.insert(&mut storage, &key1, foo1.clone())?;
245-
keymap.insert(&mut storage, &key2, foo2.clone())?;
244+
keymap.insert(&mut storage, &key1, &foo1)?;
245+
keymap.insert(&mut storage, &key2, &foo2)?;
246246
247247
let mut x = keymap.iter_keys(&storage)?;
248248
let (len, _) = x.size_hint();
@@ -270,8 +270,8 @@ fn test_keymap_iter() -> StdResult<()> {
270270
number: 1111,
271271
};
272272
273-
keymap.insert(&mut storage, &b"key1".to_vec(), foo1.clone())?;
274-
keymap.insert(&mut storage, &b"key2".to_vec(), foo2.clone())?;
273+
keymap.insert(&mut storage, &b"key1".to_vec(), &foo1)?;
274+
keymap.insert(&mut storage, &b"key2".to_vec(), &foo2)?;
275275
276276
let mut x = keymap.iter(&storage)?;
277277
let (len, _) = x.size_hint();

packages/storage/src/append_store.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ where
2424
/// prefix of the newly constructed Storage
2525
namespace: &'a [u8],
2626
/// needed if any suffixes were added to the original namespace.
27-
/// therefore it is not necessarily same as the namespace.
2827
prefix: Option<Vec<u8>>,
2928
length: Mutex<Option<u32>>,
3029
item_type: PhantomData<T>,
@@ -191,11 +190,11 @@ impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> AppendStore<'a, T, Ser> {
191190
impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> Clone for AppendStore<'a, T, Ser> {
192191
fn clone(&self) -> Self {
193192
Self {
194-
namespace: self.namespace.clone(),
193+
namespace: self.namespace,
195194
prefix: self.prefix.clone(),
196195
length: Mutex::new(None),
197-
item_type: self.item_type.clone(),
198-
serialization_type: self.serialization_type.clone(),
196+
item_type: PhantomData,
197+
serialization_type: PhantomData,
199198
}
200199
}
201200
}
@@ -221,7 +220,7 @@ impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> AppendStore<'a, T, Ser> {
221220
Ser::deserialize(
222221
&storage
223222
.get(&prefixed_key)
224-
.ok_or(StdError::not_found(type_name::<T>()))?,
223+
.ok_or_else(|| StdError::not_found(type_name::<T>()))?,
225224
)
226225
}
227226

packages/storage/src/deque_store.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,14 @@ where
2626
/// prefix of the newly constructed Storage
2727
namespace: &'a [u8],
2828
/// needed if any suffixes were added to the original namespace.
29-
/// therefore it is not necessarily same as the namespace.
3029
prefix: Option<Vec<u8>>,
3130
length: Mutex<Option<u32>>,
3231
offset: Mutex<Option<u32>>,
3332
item_type: PhantomData<T>,
3433
serialization_type: PhantomData<Ser>,
3534
}
3635

37-
impl<'a, 'b, T: Serialize + DeserializeOwned, Ser: Serde> DequeStore<'a, T, Ser> {
36+
impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> DequeStore<'a, T, Ser> {
3837
/// constructor
3938
pub const fn new(prefix: &'a [u8]) -> Self {
4039
Self {
@@ -280,7 +279,7 @@ impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> DequeStore<'a, T, Ser> {
280279
Ser::deserialize(
281280
&storage
282281
.get(&prefixed_key)
283-
.ok_or(StdError::not_found(type_name::<T>()))?,
282+
.ok_or_else(|| StdError::not_found(type_name::<T>()))?,
284283
)
285284
}
286285

@@ -301,12 +300,12 @@ impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> DequeStore<'a, T, Ser> {
301300
impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> Clone for DequeStore<'a, T, Ser> {
302301
fn clone(&self) -> Self {
303302
Self {
304-
namespace: self.namespace.clone(),
303+
namespace: self.namespace,
305304
prefix: self.prefix.clone(),
306305
length: Mutex::new(None),
307306
offset: Mutex::new(None),
308-
item_type: self.item_type.clone(),
309-
serialization_type: self.serialization_type.clone(),
307+
item_type: PhantomData,
308+
serialization_type: PhantomData,
310309
}
311310
}
312311
}

packages/storage/src/item.rs

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ where
1313
Ser: Serde,
1414
{
1515
storage_key: &'a [u8],
16+
/// needed if any suffixes were added to the original storage key.
17+
prefix: Option<Vec<u8>>,
1618
item_type: PhantomData<T>,
1719
serialization_type: PhantomData<Ser>,
1820
}
@@ -21,10 +23,26 @@ impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> Item<'a, T, Ser> {
2123
pub const fn new(key: &'a [u8]) -> Self {
2224
Self {
2325
storage_key: key,
26+
prefix: None,
2427
item_type: PhantomData,
2528
serialization_type: PhantomData,
2629
}
2730
}
31+
/// This is used to produce a new Item. This can be used when you want to associate an Item to each user
32+
/// and you still get to define the Item as a static constant
33+
pub fn add_suffix(&self, suffix: &[u8]) -> Self {
34+
let prefix = if let Some(prefix) = &self.prefix {
35+
[prefix.clone(), suffix.to_vec()].concat()
36+
} else {
37+
[self.storage_key.to_vec(), suffix.to_vec()].concat()
38+
};
39+
Self {
40+
storage_key: self.storage_key,
41+
prefix: Some(prefix),
42+
item_type: self.item_type,
43+
serialization_type: self.serialization_type,
44+
}
45+
}
2846
}
2947

3048
impl<'a, T, Ser> Item<'a, T, Ser>
@@ -55,10 +73,7 @@ where
5573

5674
/// efficient way to see if any object is currently saved.
5775
pub fn is_empty<S: ReadonlyStorage>(&self, storage: &S) -> bool {
58-
match storage.get(self.as_slice()) {
59-
Some(_) => false,
60-
None => true,
61-
}
76+
storage.get(self.as_slice()).is_none()
6277
}
6378

6479
/// Loads the data, perform the specified action, and store the result
@@ -87,7 +102,7 @@ where
87102
Ser::deserialize(
88103
&storage
89104
.get(self.as_slice())
90-
.ok_or(StdError::not_found(type_name::<T>()))?,
105+
.ok_or_else(|| StdError::not_found(type_name::<T>()))?,
91106
)
92107
}
93108

@@ -125,7 +140,22 @@ where
125140
}
126141

127142
fn as_slice(&self) -> &[u8] {
128-
self.storage_key
143+
if let Some(prefix) = &self.prefix {
144+
prefix
145+
} else {
146+
self.storage_key
147+
}
148+
}
149+
}
150+
151+
impl<'a, T: Serialize + DeserializeOwned, Ser: Serde> Clone for Item<'a, T, Ser> {
152+
fn clone(&self) -> Self {
153+
Self {
154+
storage_key: self.storage_key,
155+
prefix: self.prefix.clone(),
156+
item_type: PhantomData,
157+
serialization_type: PhantomData,
158+
}
129159
}
130160
}
131161

@@ -157,6 +187,43 @@ mod tests {
157187
Ok(())
158188
}
159189

190+
#[test]
191+
fn test_suffix() -> StdResult<()> {
192+
let mut storage = MockStorage::new();
193+
let item: Item<i32> = Item::new(b"test");
194+
let item1 = item.add_suffix(b"suffix1");
195+
let item2 = item.add_suffix(b"suffix2");
196+
197+
item.save(&mut storage, &0)?;
198+
assert!(item1.is_empty(&storage));
199+
assert!(item2.is_empty(&storage));
200+
201+
item1.save(&mut storage, &1)?;
202+
assert!(!item1.is_empty(&storage));
203+
assert!(item2.is_empty(&storage));
204+
assert_eq!(item.may_load(&storage)?, Some(0));
205+
assert_eq!(item1.may_load(&storage)?, Some(1));
206+
item2.save(&mut storage, &2)?;
207+
assert_eq!(item.may_load(&storage)?, Some(0));
208+
assert_eq!(item1.may_load(&storage)?, Some(1));
209+
assert_eq!(item2.may_load(&storage)?, Some(2));
210+
211+
Ok(())
212+
}
213+
214+
#[test]
215+
fn test_update() -> StdResult<()> {
216+
let mut storage = MockStorage::new();
217+
let item: Item<i32> = Item::new(b"test");
218+
219+
assert!(item.update(&mut storage, |x| Ok(x + 1)).is_err());
220+
item.save(&mut storage, &7)?;
221+
assert!(item.update(&mut storage, |x| Ok(x + 1)).is_ok());
222+
assert_eq!(item.load(&storage), Ok(8));
223+
224+
Ok(())
225+
}
226+
160227
#[test]
161228
fn test_serializations() -> StdResult<()> {
162229
// Check the default behavior is Bincode2

0 commit comments

Comments
 (0)