Skip to content

Commit

Permalink
Apply suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan770 committed Apr 12, 2023
1 parent fd9df0a commit 873a05b
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 119 deletions.
9 changes: 9 additions & 0 deletions integration-tests/complex-storage-structures/.gitignore
@@ -0,0 +1,9 @@
# Ignore build artifacts from the local tests sub-crate.
/target/

# Ignore backup files creates by cargo fmt.
**/*.rs.bk

# Remove Cargo.lock when creating an executable, leave it for libraries
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
Cargo.lock
@@ -1,6 +1,6 @@
[package]
name = "complex_storage_structures"
version = "4.0.0-beta"
version = "4.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
publish = false
Expand All @@ -9,7 +9,7 @@ publish = false
ink = { path = "../../crates/ink", default-features = false }

scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] }
scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true }
scale-info = { version = "2.5", default-features = false, features = ["derive"], optional = true }

[dev-dependencies]
ink_e2e = { path = "../../crates/e2e" }
Expand Down
@@ -1,81 +1,8 @@
# Storage refactoring

In ink! v4.0.0-beta the way storage works was refactored.
In ink! v4 the way storage works was refactored.

## Pre-ink! v4.0.0-beta storage

Previously, your custom data structures were relying on `SpreadLayout` and `PackedLayout`
traits. These traits described how your custom data structures should be persisted
in storage cells.

However, the storage keys that these data structures would occupy are determined in
runtime. Storage keys for individual fields in structs, that were deriving
`SpreadLayout` were determined by simple iteration on the fields of a parent struct.

For example, consider the following structure:

```rust
#[derive(SpreadLayout)]
struct TestStruct {
first: Mapping<u32, u32>,
second: Mapping<u64, u64>
}
```

The struct has two fields, and both fields need their own storage cell.

A (shortened) result of a macro expansion on this struct looks like this:

```rust
impl ::ink_storage::traits::SpreadLayout for TestStruct {
// ...

fn push_spread(&self, __key_ptr: &mut ::ink_storage::traits::KeyPtr) {
match self {
TestStruct { first: __binding_0, second: __binding_1 } => {
{
::ink_storage::traits::SpreadLayout::push_spread(
__binding_0,
__key_ptr,
);
}
{
::ink_storage::traits::SpreadLayout::push_spread(
__binding_1,
__key_ptr,
);
}
}
}
}

// ...
}
```

Every single operation on `KeyPtr` would advance it further, allowing us
to read multiple storage cells, thus processing every single storage key operation
in runtime.

If you wanted to created a packed struct (which stores its fields under a single storage key)
you had to implement a `PackedLayout` trait for your struct. Only some eligible
fields could be stored using `PackedLayout`. For example, you could
store `i32` or `AccountId` using `PackedLayout`, but you were unable to do the same with `Mapping`.

In order to implement `PackedLayout` automatically, you could just derive `PackedLayout` macro:

```rust
#[derive(PackedLayout)]
struct TestStruct {
first: u32,
second: u64
}
```

It would generate a code similar to that of a `SpreadLayout`, but with the usage
of a single storage cell instead of a variety of those cells.

## Post-ink! 4.0.0-beta storage
## ink! v4 storage

First of all, new version of ink!'s storage substantially changes
the way you can interact with "spread structs" (structs that span multiple
Expand Down
Expand Up @@ -3,29 +3,19 @@
#[ink::contract]
pub mod complex_structures {
use ink::storage::{
traits::{
AutoKey,
ManualKey,
Packed,
Storable,
StorableHint,
StorageKey,
},
traits::{AutoKey, ManualKey, Storable, StorableHint, StorageKey},
Mapping,
};

/// Non-packed type with
/// Non-packed type usage
#[ink::storage_item(derive = false)]
#[derive(Storable, StorableHint, StorageKey, Default, Debug)]
#[cfg_attr(
feature = "std",
derive(scale_info::TypeInfo, ink::storage::traits::StorageLayout)
)]
pub struct TokenManagement<
KEY: StorageKey,
T: Packed + BalancesStateManagement = Balances,
> {
balances_state: T,
pub struct TokenManagement {
balances: Balances,
allowances: Allowances<ManualKey<100>>,
}

Expand All @@ -44,12 +34,6 @@ pub mod complex_structures {
pub balance_state: u128,
}

pub trait BalancesStateManagement {
fn increase_balance_state(&mut self, amount: u128);
fn decrease_balance_state(&mut self, amount: u128);
fn get_balance_state(&self) -> u128;
}

impl<KEY: StorageKey> Allowances<KEY> {
fn get_allowance(&self, owner: AccountId, spender: AccountId) -> Balance {
self.allowances.get(&(owner, spender)).unwrap_or(0)
Expand All @@ -65,24 +49,10 @@ pub mod complex_structures {
}
}

impl BalancesStateManagement for Balances {
fn increase_balance_state(&mut self, amount: u128) {
self.balance_state += amount;
}

fn decrease_balance_state(&mut self, amount: u128) {
self.balance_state -= amount;
}

fn get_balance_state(&self) -> u128 {
self.balance_state
}
}

#[ink(storage)]
#[derive(Default)]
pub struct Contract {
pub token_management: TokenManagement<ManualKey<123>>,
pub token_management: TokenManagement,
}

impl Contract {
Expand All @@ -93,21 +63,17 @@ pub mod complex_structures {

#[ink(message)]
pub fn increase_balances_state(&mut self, amount: u128) {
self.token_management
.balances_state
.increase_balance_state(amount);
self.token_management.balances.balance_state += amount;
}

#[ink(message)]
pub fn decrease_balances_state(&mut self, amount: u128) {
self.token_management
.balances_state
.decrease_balance_state(amount);
self.token_management.balances.balance_state -= amount;
}

#[ink(message)]
pub fn get_balances_state(&self) -> u128 {
self.token_management.balances_state.get_balance_state()
self.token_management.balances.balance_state
}

#[ink(message)]
Expand Down

0 comments on commit 873a05b

Please sign in to comment.