Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
stabilize 4 storage host funcs (#12611) (#12669)
Browse files Browse the repository at this point in the history
Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>
  • Loading branch information
athei and agryaznov authored Nov 10, 2022
1 parent b0e994c commit 2bafa7d
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 144 deletions.
18 changes: 9 additions & 9 deletions frame/contracts/src/benchmarking/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -919,7 +919,7 @@ benchmarks! {
let code = WasmModule::<T>::from(ModuleDefinition {
memory: Some(ImportedMemory::max::<T>()),
imported_functions: vec![ImportedFunction {
module: "__unstable__",
module: "seal2",
name: "set_storage",
params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
return_type: Some(ValueType::I32),
Expand Down Expand Up @@ -967,7 +967,7 @@ benchmarks! {
let code = WasmModule::<T>::from(ModuleDefinition {
memory: Some(ImportedMemory::max::<T>()),
imported_functions: vec![ImportedFunction {
module: "__unstable__",
module: "seal2",
name: "set_storage",
params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
return_type: Some(ValueType::I32),
Expand Down Expand Up @@ -1015,7 +1015,7 @@ benchmarks! {
let code = WasmModule::<T>::from(ModuleDefinition {
memory: Some(ImportedMemory::max::<T>()),
imported_functions: vec![ImportedFunction {
module: "__unstable__",
module: "seal2",
name: "set_storage",
params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
return_type: Some(ValueType::I32),
Expand Down Expand Up @@ -1067,7 +1067,7 @@ benchmarks! {
let code = WasmModule::<T>::from(ModuleDefinition {
memory: Some(ImportedMemory::max::<T>()),
imported_functions: vec![ImportedFunction {
module: "__unstable__",
module: "seal1",
name: "clear_storage",
params: vec![ValueType::I32, ValueType::I32],
return_type: Some(ValueType::I32),
Expand Down Expand Up @@ -1114,7 +1114,7 @@ benchmarks! {
let code = WasmModule::<T>::from(ModuleDefinition {
memory: Some(ImportedMemory::max::<T>()),
imported_functions: vec![ImportedFunction {
module: "__unstable__",
module: "seal1",
name: "clear_storage",
params: vec![ValueType::I32, ValueType::I32],
return_type: Some(ValueType::I32),
Expand Down Expand Up @@ -1162,7 +1162,7 @@ benchmarks! {
let code = WasmModule::<T>::from(ModuleDefinition {
memory: Some(ImportedMemory::max::<T>()),
imported_functions: vec![ImportedFunction {
module: "__unstable__",
module: "seal1",
name: "get_storage",
params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
return_type: Some(ValueType::I32),
Expand Down Expand Up @@ -1216,7 +1216,7 @@ benchmarks! {
let code = WasmModule::<T>::from(ModuleDefinition {
memory: Some(ImportedMemory::max::<T>()),
imported_functions: vec![ImportedFunction {
module: "__unstable__",
module: "seal1",
name: "get_storage",
params: vec![ValueType::I32, ValueType::I32, ValueType::I32, ValueType::I32],
return_type: Some(ValueType::I32),
Expand Down Expand Up @@ -1271,7 +1271,7 @@ benchmarks! {
let code = WasmModule::<T>::from(ModuleDefinition {
memory: Some(ImportedMemory::max::<T>()),
imported_functions: vec![ImportedFunction {
module: "__unstable__",
module: "seal1",
name: "contains_storage",
params: vec![ValueType::I32, ValueType::I32],
return_type: Some(ValueType::I32),
Expand Down Expand Up @@ -1318,7 +1318,7 @@ benchmarks! {
let code = WasmModule::<T>::from(ModuleDefinition {
memory: Some(ImportedMemory::max::<T>()),
imported_functions: vec![ImportedFunction {
module: "__unstable__",
module: "seal1",
name: "contains_storage",
params: vec![ValueType::I32, ValueType::I32],
return_type: Some(ValueType::I32),
Expand Down
135 changes: 4 additions & 131 deletions frame/contracts/src/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,73 +859,12 @@ mod tests {
}

#[test]
#[cfg(not(feature = "unstable-interface"))]
fn contains_storage_works() {
const CODE: &str = r#"
(module
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_contains_storage" (func $seal_contains_storage (param i32) (result i32)))
(import "env" "memory" (memory 1 1))
;; [0, 4) size of input buffer (32 bytes as we copy the key here)
(data (i32.const 0) "\20")
;; [4, 36) input buffer
;; [36, inf) output buffer
(func (export "call")
;; Receive key
(call $seal_input
(i32.const 4) ;; Pointer to the input buffer
(i32.const 0) ;; Size of the length buffer
)
;; Load the return value into the output buffer
(i32.store (i32.const 36)
(call $seal_contains_storage
(i32.const 4) ;; The pointer to the storage key to fetch
)
)
;; Return the contents of the buffer
(call $seal_return
(i32.const 0) ;; flags
(i32.const 36) ;; output buffer ptr
(i32.const 4) ;; result is integer (4 bytes)
)
)
(func (export "deploy"))
)
"#;

let mut ext = MockExt::default();

ext.storage.insert(vec![1u8; 32], vec![42u8]);
ext.storage.insert(vec![2u8; 32], vec![]);

// value does not exist -> sentinel value returned
let result = execute(CODE, [3u8; 32].encode(), &mut ext).unwrap();
assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), crate::SENTINEL);

// value did exist -> success
let result = execute(CODE, [1u8; 32].encode(), &mut ext).unwrap();
assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 1,);

// value did exist -> success (zero sized type)
let result = execute(CODE, [2u8; 32].encode(), &mut ext).unwrap();
assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 0,);
}

#[test]
#[cfg(feature = "unstable-interface")]
fn contains_storage_works() {
const CODE: &str = r#"
(module
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "__unstable__" "contains_storage" (func $contains_storage (param i32 i32) (result i32)))
(import "seal1" "contains_storage" (func $contains_storage (param i32 i32) (result i32)))
(import "env" "memory" (memory 1 1))
Expand Down Expand Up @@ -2320,76 +2259,12 @@ mod tests {
}

#[test]
#[cfg(not(feature = "unstable-interface"))]
fn set_storage_works() {
const CODE: &str = r#"
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "seal1" "seal_set_storage" (func $seal_set_storage (param i32 i32 i32) (result i32)))
(import "env" "memory" (memory 1 1))
;; 0x1000 = 4k in little endian
;; size of input buffer
(data (i32.const 0) "\00\10")
(func (export "call")
;; Receive (key ++ value_to_write)
(call $seal_input
(i32.const 4) ;; Pointer to the input buffer
(i32.const 0) ;; Size of the length buffer
)
;; Store the passed value to the passed key and store result to memory
(i32.store (i32.const 0)
(call $seal_set_storage
(i32.const 4) ;; key_ptr
(i32.const 36) ;; value_ptr
(i32.sub ;; value_len (input_size - key_size)
(i32.load (i32.const 0))
(i32.const 32)
)
)
)
(call $seal_return
(i32.const 0) ;; flags
(i32.const 0) ;; pointer to returned value
(i32.const 4) ;; length of returned value
)
)
(func (export "deploy"))
)
"#;

let mut ext = MockExt::default();

// value did not exist before -> sentinel returned
let input = ([1u8; 32], [42u8, 48]).encode();
let result = execute(CODE, input, &mut ext).unwrap();
assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), crate::SENTINEL);
assert_eq!(ext.storage.get(&[1u8; 32].to_vec()).unwrap(), &[42u8, 48]);

// value do exist -> length of old value returned
let input = ([1u8; 32], [0u8; 0]).encode();
let result = execute(CODE, input, &mut ext).unwrap();
assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 2);
assert_eq!(ext.storage.get(&[1u8; 32].to_vec()).unwrap(), &[0u8; 0]);

// value do exist -> length of old value returned (test for zero sized val)
let input = ([1u8; 32], [99u8]).encode();
let result = execute(CODE, input, &mut ext).unwrap();
assert_eq!(u32::from_le_bytes(result.data.try_into().unwrap()), 0);
assert_eq!(ext.storage.get(&[1u8; 32].to_vec()).unwrap(), &[99u8]);
}

#[test]
#[cfg(feature = "unstable-interface")]
fn set_storage_works() {
const CODE: &str = r#"
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "__unstable__" "set_storage" (func $set_storage (param i32 i32 i32 i32) (result i32)))
(import "seal2" "set_storage" (func $set_storage (param i32 i32 i32 i32) (result i32)))
(import "env" "memory" (memory 1 1))
;; [0, 4) size of input buffer
Expand Down Expand Up @@ -2454,13 +2329,12 @@ mod tests {
}

#[test]
#[cfg(feature = "unstable-interface")]
fn get_storage_works() {
const CODE: &str = r#"
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "__unstable__" "get_storage" (func $get_storage (param i32 i32 i32 i32) (result i32)))
(import "seal1" "get_storage" (func $get_storage (param i32 i32 i32 i32) (result i32)))
(import "env" "memory" (memory 1 1))
;; [0, 4) size of input buffer (160 bytes as we copy the key+len here)
Expand Down Expand Up @@ -2548,13 +2422,12 @@ mod tests {
}

#[test]
#[cfg(feature = "unstable-interface")]
fn clear_storage_works() {
const CODE: &str = r#"
(module
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "__unstable__" "clear_storage" (func $clear_storage (param i32 i32) (result i32)))
(import "seal1" "clear_storage" (func $clear_storage (param i32 i32) (result i32)))
(import "env" "memory" (memory 1 1))
;; size of input buffer
Expand Down
8 changes: 4 additions & 4 deletions frame/contracts/src/wasm/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,7 @@ pub mod env {
///
/// Returns the size of the pre-existing value at the specified key if any. Otherwise
/// `SENTINEL` is returned as a sentinel value.
#[unstable]
#[version(2)]
#[prefixed_alias]
fn set_storage(
ctx: Runtime<E>,
Expand Down Expand Up @@ -1053,7 +1053,7 @@ pub mod env {
///
/// Returns the size of the pre-existing value at the specified key if any. Otherwise
/// `SENTINEL` is returned as a sentinel value.
#[unstable]
#[version(1)]
#[prefixed_alias]
fn clear_storage(ctx: Runtime<E>, key_ptr: u32, key_len: u32) -> Result<u32, TrapReason> {
ctx.clear_storage(KeyType::Variable(key_len), key_ptr)
Expand Down Expand Up @@ -1102,7 +1102,7 @@ pub mod env {
/// # Errors
///
/// `ReturnCode::KeyNotFound`
#[unstable]
#[version(1)]
#[prefixed_alias]
fn get_storage(
ctx: Runtime<E>,
Expand Down Expand Up @@ -1145,7 +1145,7 @@ pub mod env {
///
/// Returns the size of the pre-existing value at the specified key if any. Otherwise
/// `SENTINEL` is returned as a sentinel value.
#[unstable]
#[version(1)]
#[prefixed_alias]
fn contains_storage(ctx: Runtime<E>, key_ptr: u32, key_len: u32) -> Result<u32, TrapReason> {
ctx.contains_storage(KeyType::Variable(key_len), key_ptr)
Expand Down

0 comments on commit 2bafa7d

Please sign in to comment.