Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
b7a2e81
Added and implemented all primitives of a new storage. Implemented `s…
xgreenx Apr 11, 2022
2c06fcc
Simplified storage straits, moved check for atomic to separate trait.
xgreenx Apr 12, 2022
992706e
Refactored StorageLayout.
xgreenx Apr 15, 2022
17b433a
Updated key to be more readble
xgreenx Apr 15, 2022
09fb544
BE looks better than LE=)
xgreenx Apr 15, 2022
184c550
Fix comment
xgreenx Apr 15, 2022
58c21ac
Removed all storage collections
xgreenx May 6, 2022
2a1dea4
Merge branch 'master' into features/storage-rework
xgreenx May 6, 2022
5644402
Merged with master. Added tests that `StorageValue` and `StorageMappi…
xgreenx May 6, 2022
7e4b56d
Removed `SpreadLayout` and all related stuff and traits.
xgreenx May 9, 2022
4ab1b5f
Updated all examples to use the latest changes.
xgreenx May 11, 2022
76c50ee
Removed `StorageType2`. `StorageType` is used everywhere now.
xgreenx May 12, 2022
750bce2
Merge branch 'master' into features/storage-rework
xgreenx May 12, 2022
e8bf915
Make clippy happy
xgreenx May 12, 2022
6f868fb
Make clippy happy.
xgreenx May 12, 2022
b74b9fd
Update comment
xgreenx May 12, 2022
02f478f
Unified metadata and storage key generation. The metadata contains al…
xgreenx May 17, 2022
414d0c0
Merge branch 'master' into features/storage-rework
xgreenx May 17, 2022
b8e74bd
Update metadata to version 4
xgreenx May 17, 2022
da38d41
Fixed tests
xgreenx May 17, 2022
145850f
Merge branch 'master' into features/storage-rework
xgreenx May 17, 2022
f107ca1
Implement `TypeInfo` and `StorageLayout` in `storage_item` macro by d…
xgreenx May 17, 2022
078a04a
Fix tests
xgreenx May 17, 2022
f719a74
Merge branch 'master' into features/storage-rework
xgreenx May 18, 2022
6fe995c
Merge with new release
xgreenx May 18, 2022
ca8a270
Temporary use version 3 for metadata
xgreenx May 18, 2022
294ffc3
Fix ink-waterfall
xgreenx May 18, 2022
9ff2b0c
Size improvements
xgreenx May 18, 2022
52d4070
Merge branch 'master' into features/storage-rework
xgreenx May 18, 2022
44ec9e7
Merge mother
xgreenx May 18, 2022
58c969f
More inline)
xgreenx May 18, 2022
8c93461
Revert back optimization with encode. Better to do it in follow up
xgreenx May 18, 2022
099442b
More size improvements
xgreenx May 19, 2022
377a26d
Revert back panic on pull)
xgreenx May 19, 2022
97fa7b3
One more optimization. When it will be end???=)
xgreenx May 19, 2022
07d3619
Merge branch 'master' into features/storage-rework
xgreenx May 19, 2022
3db8e6d
Added comments why we don't need `extract_from_slice`
xgreenx May 19, 2022
e88d535
Removed `V4` of metadata. It will be updated in follow-up PR.
xgreenx May 19, 2022
c34e67c
We need to pass len...)
xgreenx May 19, 2022
0e136cf
Make clippy happy
xgreenx May 19, 2022
358c00d
Removed `Key`. Prepared the api for transparent hashing.
xgreenx May 20, 2022
2aeb623
Remove bench
xgreenx May 20, 2022
2d34b1d
Improve of dns example by adding one ref=DDDDDD
xgreenx May 20, 2022
88977bc
Merge branch 'master' into features/storage-rework
xgreenx May 21, 2022
45390a6
Merge branch 'master' into features/storage-rework
xgreenx May 25, 2022
9502e34
Renamed everything. Introduces `Storable`
xgreenx May 26, 2022
6441dfc
Make clippy happy
xgreenx May 27, 2022
7fa8cd0
Fixed storable tests
xgreenx Jun 3, 2022
334160c
Fixed storable tests and clippy
xgreenx Jun 3, 2022
d6bfac6
Fix spellcheck
xgreenx Jun 3, 2022
5f05846
Merge branch 'master' into features/storage-rework
xgreenx Jul 11, 2022
e1fe78e
Merge branch 'master' into features/storage-rework
xgreenx Jul 12, 2022
11c86dd
Use unstable functions(with transparent hashing) to work with storage.
xgreenx Jul 12, 2022
345ca79
Fix clippy
xgreenx Jul 12, 2022
b8e46bd
Fix readme
xgreenx Jul 12, 2022
eae9152
Apply suggestions from code review
xgreenx Jul 13, 2022
2b35bd5
Update crates/lang/ir/src/ir/storage_item/config.rs
xgreenx Jul 13, 2022
1873108
Added suggested panic on unwrap
xgreenx Jul 13, 2022
9436889
Merge branch 'master' into features/storage-rework
xgreenx Jul 20, 2022
188d46d
Update to 4.0.0
xgreenx Jul 20, 2022
e6f77d8
Merge branch 'master' into features/storage-rework
xgreenx Jul 20, 2022
9b022f3
Updated errors.
xgreenx Jul 20, 2022
07698e0
Fixed strerr text
xgreenx Jul 20, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Unified metadata and storage key generation. The metadata contains al…
…l names that are used during the calculation of the storage key. The updated key calculation for tuples.

Introduced `StorageKeyComposer` to manage all rules for storage creation.
Used a `SHA2` instead of `Blake2b` to calculate the storage key hash. It is because `SHA2` supports const calculation. It is required for tuples.
Implemented UI tests for `#[ink_lang::storage_item]` and fixes bugs.
  • Loading branch information
xgreenx committed May 17, 2022
commit 02f478f63e62b0c04c4a6959f9a7be4604f1cdfb
16 changes: 9 additions & 7 deletions crates/env/src/engine/off_chain/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ use ink_engine::{
};
use ink_primitives::{
Key,
OldStorageKey,
StorageKey,
StorageKeyComposer,
};

/// The capacity of the static buffer.
Expand Down Expand Up @@ -225,18 +225,19 @@ impl EnvBackend for EnvInstance {
V: scale::Encode,
{
let v = scale::Encode::encode(value);
self.engine.set_storage(key.old_key().as_ref(), &v[..]);
self.engine
.set_storage(StorageKeyComposer::old_key(key).as_ref(), &v[..]);
}

fn get_storage_value<R>(&mut self, key: &StorageKey) -> Result<Option<R>>
where
R: scale::Decode,
{
let mut output: [u8; 9600] = [0; 9600];
match self
.engine
.get_storage(key.old_key().as_ref(), &mut &mut output[..])
{
match self.engine.get_storage(
StorageKeyComposer::old_key(key).as_ref(),
&mut &mut output[..],
) {
Ok(_) => (),
Err(ext::Error::KeyNotFound) => return Ok(None),
Err(_) => panic!("encountered unexpected error"),
Expand All @@ -246,7 +247,8 @@ impl EnvBackend for EnvInstance {
}

fn clear_storage_value(&mut self, key: &StorageKey) {
self.engine.clear_storage(key.old_key().as_ref())
self.engine
.clear_storage(StorageKeyComposer::old_key(key).as_ref())
}

fn decode_input<T>(&mut self) -> Result<T>
Expand Down
8 changes: 4 additions & 4 deletions crates/env/src/engine/on_chain/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ use crate::{
};
use ink_primitives::{
Key,
OldStorageKey,
StorageKey,
StorageKeyComposer,
};

impl CryptoHash for Blake2x128 {
Expand Down Expand Up @@ -258,15 +258,15 @@ impl EnvBackend for EnvInstance {
V: scale::Encode,
{
let buffer = self.scoped_buffer().take_encoded(value);
ext::set_storage(key.old_key().as_ref(), buffer);
ext::set_storage(StorageKeyComposer::old_key(key).as_ref(), buffer);
}

fn get_storage_value<R>(&mut self, key: &StorageKey) -> Result<Option<R>>
where
R: scale::Decode,
{
let output = &mut self.scoped_buffer().take_rest();
match ext::get_storage(key.old_key().as_ref(), output) {
match ext::get_storage(StorageKeyComposer::old_key(key).as_ref(), output) {
Ok(_) => (),
Err(ExtError::KeyNotFound) => return Ok(None),
Err(_) => panic!("encountered unexpected error"),
Expand All @@ -276,7 +276,7 @@ impl EnvBackend for EnvInstance {
}

fn clear_storage_value(&mut self, key: &StorageKey) {
ext::clear_storage(key.old_key().as_ref())
ext::clear_storage(StorageKeyComposer::old_key(key).as_ref())
}

fn decode_input<T>(&mut self) -> Result<T>
Expand Down
1 change: 1 addition & 0 deletions crates/lang/codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"]
name = "ink_lang_codegen"

[dependencies]
ink_primitives = { version = "3.0.1", path = "../../primitives" }
ir = { version = "3.0.1", package = "ink_lang_ir", path = "../ir", default-features = false }
quote = "1"
syn = { version = "1.0", features = ["parsing", "full", "extra-traits"] }
Expand Down
19 changes: 15 additions & 4 deletions crates/lang/codegen/src/generator/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,12 @@ impl GenerateCode for Metadata<'_> {
const _: () = {
#[no_mangle]
pub fn __ink_generate_metadata() -> ::ink_metadata::MetadataVersioned {
let layout = #layout;
::ink_metadata::layout::ValidateLayout::validate(&layout).unwrap_or_else(|error| {
::core::panic!("metadata ink! generation failed: {}", error)
});
<::ink_metadata::InkProject as ::core::convert::Into<::ink_metadata::MetadataVersioned>>::into(
::ink_metadata::InkProject::new(#layout, #contract)
::ink_metadata::InkProject::new(layout, #contract)
)
}
};
Expand All @@ -59,10 +63,17 @@ impl Metadata<'_> {
fn generate_layout(&self) -> TokenStream2 {
let storage_span = self.contract.module().storage().span();
let storage_ident = self.contract.module().storage().ident();
let storage_key =
quote! { <#storage_ident as ::ink_storage::traits::StorageKeyHolder>::KEY };
quote_spanned!(storage_span=>
<#storage_ident as ::ink_storage::traits::StorageLayout>::layout(
&<#storage_ident as ::ink_storage::traits::StorageKeyHolder>::KEY,
)
// Wrap the layout of the contract into the `RootLayout`, because
// contract storage key is reserved for all atomic fields
::ink_metadata::layout::Layout::Root(::ink_metadata::layout::RootLayout::new(
::ink_metadata::layout::LayoutKey::from(&#storage_key),
<#storage_ident as ::ink_storage::traits::StorageLayout>::layout(
&#storage_key,
),
))
)
}

Expand Down
78 changes: 29 additions & 49 deletions crates/lang/codegen/src/generator/storage_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,12 @@

use crate::GenerateCode;
use derive_more::From;
use ir::Selector;
use proc_macro2::{
Ident,
TokenStream as TokenStream2,
TokenStream,
};
use quote::{
format_ident,
quote,
};
use quote::quote;
use syn::{
parse2,
Data,
Expand Down Expand Up @@ -89,9 +85,20 @@ impl<'a> StorageItem<'a> {
convert_into_storage_field(struct_ident, None, &salt, i, field)
});

quote! {
#vis struct #struct_ident #generics {
#(#fields),*
match struct_item.fields {
Fields::Unnamed(_) => {
quote! {
#vis struct #struct_ident #generics (
#(#fields),*
);
}
}
_ => {
quote! {
#vis struct #struct_ident #generics {
#(#fields),*
}
}
}
}
}
Expand Down Expand Up @@ -195,57 +202,30 @@ impl<'a> StorageItem<'a> {
}
}

/// # Note
///
/// - `variant_ident` is `None` for structures and unions.
/// - if the field is unnamed then `field_ident` is `field_{}` where `{}` is a number of the field.
///
/// Evaluates the storage key of the field in the structure, variant or union.
///
/// 1. Compute the ASCII byte representation of `struct_ident` and call it `S`.
/// 1. If `variant_ident` is `Some` then computes the ASCII byte representation and call it `V`.
/// 1. Compute the ASCII byte representation of `field_ident` and call it `F`.
/// 1. Concatenate (`S` and `F`) or (`S`, `V` and `F`) using `::` as separator and call it `C`.
/// 1. Apply the `BLAKE2` 256-bit hash `H` of `C`.
/// 1. The first 4 bytes of `H` make up the storage key.
fn compute_storage_key(
struct_ident: &syn::Ident,
variant_ident: Option<&syn::Ident>,
field_ident: &syn::Ident,
) -> u32 {
let separator = &b"::"[..];
let composed_key = if let Some(variant) = variant_ident {
[
&struct_ident.to_string().into_bytes()[..],
&variant.to_string().into_bytes()[..],
&field_ident.to_string().into_bytes()[..],
]
.join(separator)
} else {
[
&struct_ident.to_string().into_bytes()[..],
&field_ident.to_string().into_bytes()[..],
]
.join(separator)
};

Selector::compute(&composed_key).into_be_u32()
}

fn convert_into_storage_field(
struct_ident: &Ident,
variant_ident: Option<&syn::Ident>,
salt: &TokenStream,
index: usize,
field: &Field,
) -> Field {
let field_ident = if let Some(field_ident) = &field.ident {
field_ident.clone()
let field_name = if let Some(field_ident) = &field.ident {
field_ident.to_string()
} else {
index.to_string()
};

let variant_name = if let Some(variant_ident) = variant_ident {
variant_ident.to_string()
} else {
format_ident!("field_{}", index)
"".to_string()
};

let key = compute_storage_key(struct_ident, variant_ident, &field_ident);
let key = ink_primitives::StorageKeyComposer::compute_storage_key(
struct_ident.to_string().as_str(),
variant_name.as_str(),
field_name.as_str(),
);

let mut new_field = field.clone();
let ty = field.ty.clone();
Expand Down
17 changes: 10 additions & 7 deletions crates/lang/codegen/src/generator/trait_def/call_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,16 @@ impl CallBuilder<'_> {
__key: &::ink_primitives::StorageKey,
) -> ::ink_metadata::layout::Layout {
::ink_metadata::layout::Layout::Struct(
::ink_metadata::layout::StructLayout::new([
::ink_metadata::layout::FieldLayout::new(
::core::option::Option::Some("account_id"),
<<E as ::ink_env::Environment>::AccountId
as ::ink_storage::traits::StorageLayout>::layout(__key)
)
])
::ink_metadata::layout::StructLayout::new(
::core::stringify!(#call_builder_ident),
[
::ink_metadata::layout::FieldLayout::new(
"account_id",
<<E as ::ink_env::Environment>::AccountId
as ::ink_storage::traits::StorageLayout>::layout(__key)
)
]
)
)
}
}
Expand Down
3 changes: 3 additions & 0 deletions crates/lang/tests/compile_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ fn ui_tests() {
t.pass("tests/ui/contract/pass/*.rs");
t.compile_fail("tests/ui/contract/fail/*.rs");

t.pass("tests/ui/storage_item/pass/*.rs");
t.compile_fail("tests/ui/storage_item/fail/*.rs");

t.pass("tests/ui/trait_def/pass/*.rs");
t.compile_fail("tests/ui/trait_def/fail/*.rs");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#[ink_lang::storage_item(derive = "false")]
#[derive(Default)]
struct Contract<KEY: StorageKeyHolder = ManualKey<123>> {
a: u16,
b: u64,
c: u128,
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: expected a bool literal for `derive` ink! storage item configuration argument
--> tests/ui/storage_item/fail/argument_derive_invalid_type.rs:1:26
|
1 | #[ink_lang::storage_item(derive = "false")]
| ^^^^^^^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#[ink_lang::storage_item(derive)]
#[derive(Default)]
struct Contract<KEY: StorageKeyHolder = ManualKey<123>> {
a: u16,
b: u64,
c: u128,
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: ink! config options require an argument separated by '='
--> tests/ui/storage_item/fail/argument_derive_missing_arg.rs:1:26
|
1 | #[ink_lang::storage_item(derive)]
| ^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use ink_storage::{
traits::AtomicGuard,
StorageValue,
};

#[ink_lang::storage_item]
#[derive(Default)]
struct NonAtomic {
a: StorageValue<u128>,
}

fn main() {
let _: &dyn AtomicGuard<true> = &NonAtomic::default();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error[E0277]: the trait bound `NonAtomic: AtomicGuard<true>` is not satisfied
--> tests/ui/storage_item/fail/atomic_guard_is_false_for_non_atomic.rs:13:37
|
13 | let _: &dyn AtomicGuard<true> = &NonAtomic::default();
| ^^^^^^^^^^^^^^^^^^^^^ the trait `AtomicGuard<true>` is not implemented for `NonAtomic`
|
= help: the trait `AtomicGuard<false>` is implemented for `NonAtomic`
= note: required for the cast to the object type `dyn AtomicGuard<true>`
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use ink_prelude::vec::Vec;
use ink_storage::StorageValue;

#[ink_lang::storage_item]
struct NonAtomic {
a: StorageValue<u128>,
}

#[ink_lang::storage_item]
struct Contract {
a: Vec<NonAtomic>,
}

fn main() {}
Loading