Skip to content

Commit

Permalink
feat(zink): introduce double key mapping (#234)
Browse files Browse the repository at this point in the history
* feat(codegen): introduce storage parser

* refactor(zink): meta list for storage types

* feat(zink): sync all examples

* feat(zink): interface of double key mapping

* feat(zink/codegen): share getter for all storage

* feat(zink): tests with double key mapping

* chore(zink): clean typos
  • Loading branch information
clearloop authored Sep 27, 2024
1 parent f03cab8 commit 40c491a
Show file tree
Hide file tree
Showing 15 changed files with 344 additions and 155 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ cargo_metadata = "0.18.1"
ccli = "0.0.1"
colored = "2.1.0"
etc = "0.1.19"
heck = "0.5.0"
hex = "0.4.3"
indexmap = "2.2.2"
paste = "1.0.14"
Expand All @@ -41,7 +42,7 @@ semver = "1.0.21"
serde = { version = "1.0.196", default-features = false }
serde_json = "1.0.113"
smallvec = "1.13.1"
syn = { version = "2.0.48", features = [ "full" ] }
syn = { version = "2.0.77", features = [ "full" ] }
thiserror = "1.0.56"
tiny-keccak = { version = "2.0.2", features = ["keccak"], default-features = false }
toml = "0.8.9"
Expand Down
8 changes: 1 addition & 7 deletions examples/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ use zink::Storage;
#[zink::storage(i32)]
pub struct Counter;

/// Get value from the storage.
#[zink::external]
pub fn get() -> i32 {
Counter::get()
}

#[cfg(not(target_arch = "wasm32"))]
fn main() {}

Expand Down Expand Up @@ -61,7 +55,7 @@ fn init_storage() -> anyhow::Result<()> {
.bytecode()?,
)?;
info = evm
.calldata(&contract.encode(&["get()"])?)
.calldata(&contract.encode(&["counter()"])?)
.call(info.address)?;

assert_eq!(info.ret, value.to_bytes32());
Expand Down
59 changes: 59 additions & 0 deletions examples/dkmapping.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//! Storage example.
#![cfg_attr(target_arch = "wasm32", no_std)]
#![cfg_attr(target_arch = "wasm32", no_main)]

extern crate zink;

use zink::DoubleKeyMapping as _;

/// Counter with value type `i32`
#[zink::storage(i32, i32, i32)]
pub struct DoubleKeyMapping;

/// Set the mapping
#[zink::external]
pub fn mset(key1: i32, key2: i32, value: i32) {
DoubleKeyMapping::set(key1, key2, value);
}

#[cfg(not(target_arch = "wasm32"))]
fn main() {}

#[test]
fn storage_double_key_mapping() -> anyhow::Result<()> {
use zint::{Bytes32, Contract};

let mut contract = Contract::search("dkmapping")?.compile()?;
let mut evm = contract.deploy()?.commit(true);

let key1 = 0x00;
let key2 = 0x01;
let value: i32 = 0x42;

// set value to storage
let calldata = contract.encode(&[
b"mset(int32,int32,int32)".to_vec(),
value.to_bytes32().to_vec(),
key2.to_bytes32().to_vec(),
key1.to_bytes32().to_vec(),
])?;
let info = evm.calldata(&calldata).call(contract.address)?;
assert!(info.ret.is_empty());

// verify result with database
let storage_key = zint::keccak256(&[[0; 32], [0; 32], 1.to_bytes32()].concat());
assert_eq!(
evm.storage(contract.address, storage_key)?,
value.to_bytes32(),
);

// get value from storage
let calldata = contract.encode(&[
b"double_key_mapping(int32,int32)".to_vec(),
key2.to_bytes32().to_vec(),
key1.to_bytes32().to_vec(),
])?;
let info = evm.calldata(&calldata).call(contract.address)?;
assert_eq!(info.ret, value.to_bytes32(), "{info:#?}",);
Ok(())
}
13 changes: 3 additions & 10 deletions examples/mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ extern crate zink;
use zink::Mapping as _;

/// Counter with value type `i32`
#[zink::storage(i32 => i32)]
#[zink::storage(i32, i32)]
pub struct Mapping;

/// Set the mapping
Expand All @@ -16,17 +16,11 @@ pub fn mset(key: i32, value: i32) {
Mapping::set(key, value);
}

/// Get from ampping
#[zink::external]
pub fn mget(key: i32) -> i32 {
Mapping::get(key)
}

#[cfg(not(target_arch = "wasm32"))]
fn main() {}

#[test]
fn mapping() -> anyhow::Result<()> {
fn storage_mapping() -> anyhow::Result<()> {
use zint::{Bytes32, Contract};

let mut contract = Contract::search("mapping")?.compile()?;
Expand All @@ -44,7 +38,6 @@ fn mapping() -> anyhow::Result<()> {
let info = evm.calldata(&calldata).call(contract.address)?;
assert!(info.ret.is_empty());

tracing::debug!("{info:?}");
// verify result with database
let storage_key = zint::keccak256(&[0; 0x40]);
assert_eq!(
Expand All @@ -53,7 +46,7 @@ fn mapping() -> anyhow::Result<()> {
);

// get value from storage
let calldata = contract.encode(&[b"mget(int32)".to_vec(), key.to_bytes32().to_vec()])?;
let calldata = contract.encode(&[b"mapping(int32)".to_vec(), key.to_bytes32().to_vec()])?;
let info = evm.calldata(&calldata).call(contract.address)?;
assert_eq!(info.ret, value.to_bytes32(), "{info:#?}",);
Ok(())
Expand Down
8 changes: 1 addition & 7 deletions examples/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ pub fn set(value: i32) {
Counter::set(value);
}

/// Get value from the storage.
#[zink::external]
pub fn get() -> i32 {
Counter::get()
}

#[cfg(not(target_arch = "wasm32"))]
fn main() {}

Expand All @@ -40,7 +34,7 @@ fn value() -> anyhow::Result<()> {
}

{
let info = contract.execute(&["get()"])?;
let info = contract.execute(&["counter()"])?;
assert_eq!(info.ret, 0.to_bytes32());
}

Expand Down
1 change: 1 addition & 0 deletions zink/codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ repository.workspace = true
proc-macro = true

[dependencies]
heck.workspace = true
proc-macro2.workspace = true
quote.workspace = true
syn.workspace = true
Expand Down
8 changes: 5 additions & 3 deletions zink/codegen/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Code generation library for the zink API
#![allow(unused)]
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput, ItemFn, ItemStruct};
use syn::{parse_macro_input, Attribute, DeriveInput, ItemFn, ItemStruct};

mod event;
mod selector;
Expand Down Expand Up @@ -45,13 +46,14 @@ pub fn event(input: TokenStream) -> TokenStream {
/// pub struct Counter;
///
/// /// storage mapping
/// #[zink::storage(i32 => i32)]
/// #[zink::storage(i32, i32)]
/// pub struct Mapping;
/// ```
#[proc_macro_attribute]
pub fn storage(attr: TokenStream, input: TokenStream) -> TokenStream {
let ty = storage::StorageType::from(attr);
let input = parse_macro_input!(input as ItemStruct);
storage::parse(attr.into(), input)
storage::Storage::parse(ty, input)
}

/// Mark the function as an external entry point.
Expand Down
Loading

0 comments on commit 40c491a

Please sign in to comment.