Skip to content

Commit

Permalink
Merge pull request #57 from srdtrk/master
Browse files Browse the repository at this point in the history
Fixed clippy errors and made minor bugfixes to storage readme
  • Loading branch information
toml01 authored Aug 30, 2022
2 parents 2492182 + 9cc3694 commit 6f06d3d
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 68 deletions.
28 changes: 22 additions & 6 deletions Releases.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
# Release notes for the Secret Toolkit

## secret-toolkit-storage v0.4.2

* 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`

## secret-toolkit-storage v0.4.1

* 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.
Expand All @@ -23,20 +31,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.
Expand All @@ -49,8 +61,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`.
Expand All @@ -64,6 +77,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)!

Expand All @@ -73,7 +87,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<S: Serde, T>`, `Base64JsonOf<T>`, and `Base64Bincode2Of<T>`,
* Added `Base64Of<S: Serde, T>`, `Base64JsonOf<T>`, and `Base64Bincode2Of<T>`,
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.
Expand All @@ -85,9 +99,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
Expand All @@ -102,6 +118,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.
2 changes: 1 addition & 1 deletion packages/storage/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "secret-toolkit-storage"
version = "0.4.1"
version = "0.4.2"
edition = "2018"
authors = ["SCRT Labs <[email protected]>"]
license-file = "../../LICENSE"
Expand Down
22 changes: 11 additions & 11 deletions packages/storage/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand All @@ -43,7 +43,7 @@ pub static OWNER: Item<HumanAddr> = 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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -173,12 +173,12 @@ 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
pub static ADDR_VOTE: Keymap<HumanAddr, Foo> = Keymap::new(b"vote");
pub static BET_STORE: Keymap<u32, BetInfo> = Keymap::new(b"vote");
pub static BET_STORE: Keymap<u32, BetInfo> = 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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
9 changes: 4 additions & 5 deletions packages/storage/src/append_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<u8>>,
length: Mutex<Option<u32>>,
item_type: PhantomData<T>,
Expand Down Expand Up @@ -191,11 +190,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: PhantomData,
serialization_type: PhantomData,
}
}
}
Expand All @@ -221,7 +220,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::<T>()))?,
.ok_or_else(|| StdError::not_found(type_name::<T>()))?,
)
}

Expand Down
11 changes: 5 additions & 6 deletions packages/storage/src/deque_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,14 @@ 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<Vec<u8>>,
length: Mutex<Option<u32>>,
offset: Mutex<Option<u32>>,
item_type: PhantomData<T>,
serialization_type: PhantomData<Ser>,
}

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 {
Expand Down Expand Up @@ -280,7 +279,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::<T>()))?,
.ok_or_else(|| StdError::not_found(type_name::<T>()))?,
)
}

Expand All @@ -301,12 +300,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: PhantomData,
serialization_type: PhantomData,
}
}
}
Expand Down
79 changes: 73 additions & 6 deletions packages/storage/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ where
Ser: Serde,
{
storage_key: &'a [u8],
/// needed if any suffixes were added to the original storage key.
prefix: Option<Vec<u8>>,
item_type: PhantomData<T>,
serialization_type: PhantomData<Ser>,
}
Expand All @@ -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>
Expand Down Expand Up @@ -55,10 +73,7 @@ where

/// efficient way to see if any object is currently saved.
pub fn is_empty<S: ReadonlyStorage>(&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
Expand Down Expand Up @@ -87,7 +102,7 @@ where
Ser::deserialize(
&storage
.get(self.as_slice())
.ok_or(StdError::not_found(type_name::<T>()))?,
.ok_or_else(|| StdError::not_found(type_name::<T>()))?,
)
}

Expand Down Expand Up @@ -125,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,
}
}
}

Expand Down Expand Up @@ -157,6 +187,43 @@ mod tests {
Ok(())
}

#[test]
fn test_suffix() -> StdResult<()> {
let mut storage = MockStorage::new();
let item: Item<i32> = 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<i32> = 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
Expand Down
Loading

0 comments on commit 6f06d3d

Please sign in to comment.