From e38b88655a4ec4ec066793335c61dd80522fbbff Mon Sep 17 00:00:00 2001 From: fro Date: Thu, 7 Sep 2017 21:12:03 +0300 Subject: [PATCH] - Fixed-size H* moved to a separate crate - changed interfaces of storage, ext and ParamsView to use H160, H256 and bignum::U256 primitives --- Cargo.toml | 7 +- demo/src/main.rs | 9 +- src/ext.rs | 38 +++-- src/hash.rs | 421 ----------------------------------------------- src/hex.rs | 199 ---------------------- src/lib.rs | 22 +-- src/storage.rs | 21 +-- 7 files changed, 56 insertions(+), 661 deletions(-) delete mode 100644 src/hash.rs delete mode 100644 src/hex.rs diff --git a/Cargo.toml b/Cargo.toml index 98152de..cc0371e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ authors = ["NikVolf "] [dependencies] wasm-alloc = { path = "alloc" } -rustc-hex = "1.0.0" [dependencies.bigint] version = "4" @@ -13,4 +12,8 @@ default-features = false [dependencies.byteorder] version = "1" -default-features = false \ No newline at end of file +default-features = false + +[dependencies.parity-hash] +version = "1" +default-features = false diff --git a/demo/src/main.rs b/demo/src/main.rs index 17004e9..7c88596 100644 --- a/demo/src/main.rs +++ b/demo/src/main.rs @@ -5,14 +5,15 @@ extern crate pwasm_std; use pwasm_std::{CallArgs, storage}; +use pwasm_std::hash::H256; #[no_mangle] pub fn call(descriptor: *mut u8) { let mut call_args = unsafe { CallArgs::from_raw(descriptor) }; - let k = [0u8; 32]; - let mut v = [0u8; 32]; - storage::read(&k, &mut v); + let _ = storage::write(&H256::from([1u8; 32]), &[1u8; 32]).expect("OK"); + let v = storage::read(&H256::from([1u8; 32])).expect("OK"); + let mut vec = vec![0u8; 16384]; vec[32..64].copy_from_slice(&v); @@ -20,4 +21,4 @@ pub fn call(descriptor: *mut u8) { *call_args.result_mut() = vec.into_boxed_slice(); unsafe { call_args.save(descriptor); } -} \ No newline at end of file +} diff --git a/src/ext.rs b/src/ext.rs index 1f388f2..7881cdd 100644 --- a/src/ext.rs +++ b/src/ext.rs @@ -1,3 +1,7 @@ +// use hash::H256; +use bigint::U256; +use hash::Address; + #[derive(Debug)] pub struct Error; @@ -66,14 +70,16 @@ mod external { } } -pub fn suicide(refund: &[u8; 20]) { +pub fn suicide(refund: &Address) { unsafe { external::suicide(refund.as_ptr()); } } -pub fn create(endowment: &[u8; 32], code: &[u8]) -> Result<[u8; 20], Error> { - let mut result = [0u8; 20]; +pub fn create(endowment: U256, code: &[u8]) -> Result { + let mut endowment_arr = [0u8; 32]; + endowment.to_big_endian(&mut endowment_arr); + let mut result = Address::new(); unsafe { - if external::create(endowment.as_ptr(), code.as_ptr(), code.len() as u32, (&mut result).as_mut_ptr()) == 0 { + if external::create(endowment_arr.as_ptr(), code.as_ptr(), code.len() as u32, (&mut result).as_mut_ptr()) == 0 { Ok(result) } else { Err(Error) @@ -81,16 +87,18 @@ pub fn create(endowment: &[u8; 32], code: &[u8]) -> Result<[u8; 20], Error> { } } -pub fn call(address: &[u8; 20], value: &[u8; 32], input: &[u8], result: &mut [u8]) -> Result<(), Error> { +pub fn call(address: &Address, value: U256, input: &[u8], result: &mut [u8]) -> Result<(), Error> { + let mut value_arr = [0u8; 32]; + value.to_big_endian(&mut value_arr); unsafe { - match external::ccall(address.as_ptr(), value.as_ptr(), input.as_ptr(), input.len() as u32, result.as_mut_ptr(), result.len() as u32) { + match external::ccall(address.as_ptr(), value_arr.as_ptr(), input.as_ptr(), input.len() as u32, result.as_mut_ptr(), result.len() as u32) { 0 => Ok(()), _ => Err(Error), } } } -pub fn call_code(address: &[u8; 20], input: &[u8], result: &mut [u8]) -> Result<(), Error> { +pub fn call_code(address: &Address, input: &[u8], result: &mut [u8]) -> Result<(), Error> { unsafe { match external::dcall(address.as_ptr(), input.as_ptr(), input.len() as u32, result.as_mut_ptr(), result.len() as u32) { 0 => Ok(()), @@ -99,7 +107,7 @@ pub fn call_code(address: &[u8; 20], input: &[u8], result: &mut [u8]) -> Result< } } -pub fn static_call(address: &[u8; 20], input: &[u8], result: &mut [u8]) -> Result<(), Error> { +pub fn static_call(address: &Address, input: &[u8], result: &mut [u8]) -> Result<(), Error> { unsafe { match external::scall(address.as_ptr(), input.as_ptr(), input.len() as u32, result.as_mut_ptr(), result.len() as u32) { 0 => Ok(()), @@ -118,8 +126,8 @@ pub fn block_hash(block_number: u64) -> Result<[u8; 32], Error> { } } -pub fn coinbase() -> [u8; 20] { - let mut res = [0u8; 20]; +pub fn coinbase() -> Address { + let mut res = Address::new(); unsafe { external::coinbase(res.as_mut_ptr()); } res } @@ -132,14 +140,14 @@ pub fn block_number() -> u64 { unsafe { external::blocknumber() as u64 } } -pub fn difficulty() -> [u8; 32] { +pub fn difficulty() -> U256 { let mut res = [0u8; 32]; unsafe { external::difficulty(res.as_mut_ptr()); } - res + U256::from_big_endian(&res) } -pub fn gas_limit() -> [u8; 32] { +pub fn gas_limit() -> U256 { let mut res = [0u8; 32]; unsafe { external::gaslimit(res.as_mut_ptr()); } - res -} \ No newline at end of file + U256::from_big_endian(&res) +} diff --git a/src/hash.rs b/src/hash.rs deleted file mode 100644 index 00a51c9..0000000 --- a/src/hash.rs +++ /dev/null @@ -1,421 +0,0 @@ -use alloc::string::ToString; -use alloc::string::String; -use core::{ops, fmt, cmp, str}; -use core::cmp::{min, Ordering}; -use core::ops::{Deref, DerefMut, BitXor, BitAnd, BitOr, IndexMut, Index}; -use core::hash::{Hash, Hasher}; -use bigint::U256; -use hex::*; - -#[allow(non_camel_case_types)] -#[repr(u8)] -pub enum c_void { - // Two dummy variants so the #[repr] attribute can be used. - #[doc(hidden)] - __variant1, - #[doc(hidden)] - __variant2, -} - -#[allow(non_camel_case_types)] -extern { - fn memcmp(cx: *const c_void, ct: *const c_void, n: usize) -> i32; -} - -/// Return `s` without the `0x` at the beginning of it, if any. -fn clean_0x(s: &str) -> &str { - if s.starts_with("0x") { - &s[2..] - } else { - s - } -} - -macro_rules! impl_hash { - ($from: ident, $size: expr) => { - #[repr(C)] - /// Unformatted binary data of fixed length. - pub struct $from (pub [u8; $size]); - - - impl From<[u8; $size]> for $from { - fn from(bytes: [u8; $size]) -> Self { - $from(bytes) - } - } - - impl From<$from> for [u8; $size] { - fn from(s: $from) -> Self { - s.0 - } - } - - impl Deref for $from { - type Target = [u8]; - - #[inline] - fn deref(&self) -> &[u8] { - &self.0 - } - } - - impl AsRef<[u8]> for $from { - #[inline] - fn as_ref(&self) -> &[u8] { - &self.0 - } - } - - impl DerefMut for $from { - #[inline] - fn deref_mut(&mut self) -> &mut [u8] { - &mut self.0 - } - } - - impl $from { - /// Create a new, zero-initialised, instance. - pub fn new() -> $from { - $from([0; $size]) - } - - /// Synonym for `new()`. Prefer to new as it's more readable. - pub fn zero() -> $from { - $from([0; $size]) - } - - /// Get the size of this object in bytes. - pub fn len() -> usize { - $size - } - - #[inline] - /// Assign self to be of the same value as a slice of bytes of length `len()`. - pub fn clone_from_slice(&mut self, src: &[u8]) -> usize { - let min = cmp::min($size, src.len()); - self.0[..min].copy_from_slice(&src[..min]); - min - } - - /// Convert a slice of bytes of length `len()` to an instance of this type. - pub fn from_slice(src: &[u8]) -> Self { - let mut r = Self::new(); - r.clone_from_slice(src); - r - } - - /// Copy the data of this object into some mutable slice of length `len()`. - pub fn copy_to(&self, dest: &mut[u8]) { - let min = cmp::min($size, dest.len()); - dest[..min].copy_from_slice(&self.0[..min]); - } - - /// Returns `true` if all bits set in `b` are also set in `self`. - pub fn contains<'a>(&'a self, b: &'a Self) -> bool { - &(b & self) == b - } - - /// Returns `true` if no bits are set. - pub fn is_zero(&self) -> bool { - self.eq(&Self::new()) - } - - /// Returns the lowest 8 bytes interpreted as a BigEndian integer. - pub fn low_u64(&self) -> u64 { - let mut ret = 0u64; - for i in 0..min($size, 8) { - ret |= (self.0[$size - 1 - i] as u64) << (i * 8); - } - ret - } - } - - impl str::FromStr for $from { - type Err = FromHexError; - - fn from_str(s: &str) -> Result<$from, FromHexError> { - let a = s.from_hex()?; - if a.len() != $size { - return Err(FromHexError::InvalidHexLength); - } - - let mut ret = [0;$size]; - ret.copy_from_slice(&a); - Ok($from(ret)) - } - } - - impl fmt::Debug for $from { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - for i in &self.0[..] { - write!(f, "{:02x}", i)?; - } - Ok(()) - } - } - - impl fmt::Display for $from { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - for i in &self.0[..] { - write!(f, "{:02x}", i)?; - } - Ok(()) - } - } - - impl Copy for $from {} - - impl Clone for $from { - fn clone(&self) -> $from { - let mut ret = $from::new(); - ret.0.copy_from_slice(&self.0); - ret - } - } - - impl Eq for $from {} - - impl PartialEq for $from { - fn eq(&self, other: &Self) -> bool { - unsafe { memcmp(self.0.as_ptr() as *const c_void, other.0.as_ptr() as *const c_void, $size) == 0 } - } - } - - impl Ord for $from { - fn cmp(&self, other: &Self) -> Ordering { - let r = unsafe { memcmp(self.0.as_ptr() as *const c_void, other.0.as_ptr() as *const c_void, $size) }; - if r < 0 { return Ordering::Less } - if r > 0 { return Ordering::Greater } - return Ordering::Equal; - } - } - - impl PartialOrd for $from { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } - } - - impl Hash for $from { - fn hash(&self, state: &mut H) where H: Hasher { - state.write(&self.0); - state.finish(); - } - } - - impl Index for $from { - type Output = u8; - - fn index(&self, index: usize) -> &u8 { - &self.0[index] - } - } - impl IndexMut for $from { - fn index_mut(&mut self, index: usize) -> &mut u8 { - &mut self.0[index] - } - } - impl Index> for $from { - type Output = [u8]; - - fn index(&self, index: ops::Range) -> &[u8] { - &self.0[index] - } - } - impl IndexMut> for $from { - fn index_mut(&mut self, index: ops::Range) -> &mut [u8] { - &mut self.0[index] - } - } - impl Index for $from { - type Output = [u8]; - - fn index(&self, _index: ops::RangeFull) -> &[u8] { - &self.0 - } - } - impl IndexMut for $from { - fn index_mut(&mut self, _index: ops::RangeFull) -> &mut [u8] { - &mut self.0 - } - } - - /// `BitOr` on references - impl<'a> BitOr for &'a $from { - type Output = $from; - - fn bitor(self, rhs: Self) -> Self::Output { - let mut ret: $from = $from::default(); - for i in 0..$size { - ret.0[i] = self.0[i] | rhs.0[i]; - } - ret - } - } - - /// Moving `BitOr` - impl BitOr for $from { - type Output = $from; - - fn bitor(self, rhs: Self) -> Self::Output { - &self | &rhs - } - } - - /// `BitAnd` on references - impl <'a> BitAnd for &'a $from { - type Output = $from; - - fn bitand(self, rhs: Self) -> Self::Output { - let mut ret: $from = $from::default(); - for i in 0..$size { - ret.0[i] = self.0[i] & rhs.0[i]; - } - ret - } - } - - /// Moving `BitAnd` - impl BitAnd for $from { - type Output = $from; - - fn bitand(self, rhs: Self) -> Self::Output { - &self & &rhs - } - } - - /// `BitXor` on references - impl <'a> BitXor for &'a $from { - type Output = $from; - - fn bitxor(self, rhs: Self) -> Self::Output { - let mut ret: $from = $from::default(); - for i in 0..$size { - ret.0[i] = self.0[i] ^ rhs.0[i]; - } - ret - } - } - - /// Moving `BitXor` - impl BitXor for $from { - type Output = $from; - - fn bitxor(self, rhs: Self) -> Self::Output { - &self ^ &rhs - } - } - - impl $from { - /// Get a hex representation. - pub fn hex(&self) -> String { - format!("{:?}", self) - } - } - - impl Default for $from { - fn default() -> Self { $from::new() } - } - - impl From for $from { - fn from(mut value: u64) -> $from { - let mut ret = $from::new(); - for i in 0..8 { - if i < $size { - ret.0[$size - i - 1] = (value & 0xff) as u8; - value >>= 8; - } - } - ret - } - } - - impl From<&'static str> for $from { - fn from(s: &'static str) -> $from { - let s = clean_0x(s); - if s.len() % 2 == 1 { - ("0".to_string() + s).parse().unwrap() - } else { - s.parse().unwrap() - } - } - } - - impl<'a> From<&'a [u8]> for $from { - fn from(s: &'a [u8]) -> $from { - $from::from_slice(s) - } - } - } -} - -impl From for H256 { - fn from(value: U256) -> H256 { - let mut ret = H256::new(); - value.to_big_endian(&mut ret); - ret - } -} - -impl<'a> From<&'a U256> for H256 { - fn from(value: &'a U256) -> H256 { - let mut ret: H256 = H256::new(); - value.to_big_endian(&mut ret); - ret - } -} - -impl From for U256 { - fn from(value: H256) -> U256 { - U256::from(&value) - } -} - -impl<'a> From<&'a H256> for U256 { - fn from(value: &'a H256) -> U256 { - U256::from(value.as_ref() as &[u8]) - } -} - -impl From for H160 { - fn from(value: H256) -> H160 { - let mut ret = H160::new(); - ret.0.copy_from_slice(&value[12..32]); - ret - } -} - -impl From for H64 { - fn from(value: H256) -> H64 { - let mut ret = H64::new(); - ret.0.copy_from_slice(&value[20..28]); - ret - } -} - -impl From for H256 { - fn from(value: H160) -> H256 { - let mut ret = H256::new(); - ret.0[12..32].copy_from_slice(&value); - ret - } -} - -impl<'a> From<&'a H160> for H256 { - fn from(value: &'a H160) -> H256 { - let mut ret = H256::new(); - ret.0[12..32].copy_from_slice(value); - ret - } -} - -impl_hash!(H32, 4); -impl_hash!(H64, 8); -impl_hash!(H128, 16); -impl_hash!(H160, 20); -impl_hash!(H256, 32); -impl_hash!(H264, 33); -impl_hash!(H512, 64); -impl_hash!(H520, 65); -impl_hash!(H1024, 128); -impl_hash!(H2048, 256); diff --git a/src/hex.rs b/src/hex.rs deleted file mode 100644 index 92c36da..0000000 --- a/src/hex.rs +++ /dev/null @@ -1,199 +0,0 @@ -pub use self::FromHexError::*; - -use core::fmt; -use alloc::string::String; -use alloc::vec::Vec; - -/// A trait for converting a value to hexadecimal encoding -pub trait ToHex { - /// Converts the value of `self` to a hex value, returning the owned - /// string. - fn to_hex(&self) -> String; -} - -static CHARS: &'static[u8] = b"0123456789abcdef"; - -impl ToHex for [u8] { - /// Turn a vector of `u8` bytes into a hexadecimal string. - /// - /// # Example - /// - /// ```rust - /// extern crate rustc_hex; - /// use rustc_hex::ToHex; - /// - /// fn main () { - /// let str = [52,32].to_hex(); - /// println!("{}", str); - /// } - /// ``` - fn to_hex(&self) -> String { - let mut v = Vec::with_capacity(self.len() * 2); - for &byte in self.iter() { - v.push(CHARS[(byte >> 4) as usize]); - v.push(CHARS[(byte & 0xf) as usize]); - } - - unsafe { - String::from_utf8_unchecked(v) - } - } -} - -impl<'a, T: ?Sized + ToHex> ToHex for &'a T { - fn to_hex(&self) -> String { - (**self).to_hex() - } -} - -/// A trait for converting hexadecimal encoded values -pub trait FromHex { - /// Converts the value of `self`, interpreted as hexadecimal encoded data, - /// into an owned vector of bytes, returning the vector. - fn from_hex(&self) -> Result, FromHexError>; -} - -/// Errors that can occur when decoding a hex encoded string -#[derive(Clone, Copy)] -pub enum FromHexError { - /// The input contained a character not part of the hex format - InvalidHexCharacter(char, usize), - /// The input had an invalid length - InvalidHexLength, -} - -impl fmt::Debug for FromHexError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - InvalidHexCharacter(ch, idx) => - write!(f, "Invalid character '{}' at position {}", ch, idx), - InvalidHexLength => write!(f, "Invalid input length"), - } - } -} - -impl fmt::Display for FromHexError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&self, f) - } -} - -impl FromHex for str { - /// Convert any hexadecimal encoded string (literal, `@`, `&`, or `~`) - /// to the byte values it encodes. - /// - /// You can use the `String::from_utf8` function to turn a - /// `Vec` into a string with characters corresponding to those values. - /// - /// # Example - /// - /// This converts a string literal to hexadecimal and back. - /// - /// ```rust - /// extern crate rustc_hex; - /// use rustc_hex::{FromHex, ToHex}; - /// - /// fn main () { - /// let hello_str = "Hello, World".as_bytes().to_hex(); - /// println!("{}", hello_str); - /// let bytes = hello_str.from_hex().unwrap(); - /// println!("{:?}", bytes); - /// let result_str = String::from_utf8(bytes).unwrap(); - /// println!("{}", result_str); - /// } - /// ``` - fn from_hex(&self) -> Result, FromHexError> { - // This may be an overestimate if there is any whitespace - let mut b = Vec::with_capacity(self.len() / 2); - let mut modulus = 0; - let mut buf = 0; - - for (idx, byte) in self.bytes().enumerate() { - buf <<= 4; - - match byte { - b'A'...b'F' => buf |= byte - b'A' + 10, - b'a'...b'f' => buf |= byte - b'a' + 10, - b'0'...b'9' => buf |= byte - b'0', - b' '|b'\r'|b'\n'|b'\t' => { - buf >>= 4; - continue - } - _ => { - let ch = self[idx..].chars().next().unwrap(); - return Err(InvalidHexCharacter(ch, idx)) - } - } - - modulus += 1; - if modulus == 2 { - modulus = 0; - b.push(buf); - } - } - - match modulus { - 0 => Ok(b.into_iter().collect()), - _ => Err(InvalidHexLength), - } - } -} - -impl<'a, T: ?Sized + FromHex> FromHex for &'a T { - fn from_hex(&self) -> Result, FromHexError> { - (**self).from_hex() - } -} - -#[cfg(test)] -mod tests { - use super::{FromHex, ToHex}; - - #[test] - pub fn test_to_hex() { - assert_eq!("foobar".as_bytes().to_hex(), "666f6f626172"); - } - - #[test] - pub fn test_from_hex_okay() { - assert_eq!("666f6f626172".from_hex().unwrap(), - b"foobar"); - assert_eq!("666F6F626172".from_hex().unwrap(), - b"foobar"); - } - - #[test] - pub fn test_from_hex_odd_len() { - assert!("666".from_hex().is_err()); - assert!("66 6".from_hex().is_err()); - } - - #[test] - pub fn test_from_hex_invalid_char() { - assert!("66y6".from_hex().is_err()); - } - - #[test] - pub fn test_from_hex_ignores_whitespace() { - assert_eq!("666f 6f6\r\n26172 ".from_hex().unwrap(), - b"foobar"); - } - - #[test] - pub fn test_to_hex_all_bytes() { - for i in 0..256 { - assert_eq!([i as u8].to_hex(), format!("{:02x}", i)); - } - } - - #[test] - pub fn test_from_hex_all_bytes() { - for i in 0..256 { - let ii: &[u8] = &[i as u8]; - assert_eq!(format!("{:02x}", i).from_hex().unwrap(), - ii); - assert_eq!(format!("{:02X}", i).from_hex().unwrap(), - ii); - } - } -} diff --git a/src/lib.rs b/src/lib.rs index 5cb2a59..7962176 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ extern crate wasm_alloc; extern crate byteorder; pub extern crate bigint; +pub extern crate parity_hash; use core::{slice, ptr, mem}; use byteorder::{LittleEndian, ByteOrder}; @@ -17,6 +18,9 @@ pub use alloc::string::String; pub use alloc::str; pub use alloc::vec::Vec; pub use wasm_alloc::WamsAllocator; +pub use parity_hash as hash; +use hash::Address; +use bigint::U256; /// Wrapper over storage read/write externs /// Storage api is a key-value storage where both key and value are 32 bytes in len @@ -29,8 +33,6 @@ pub mod logger; pub mod ext; /// Fixed-size structures -pub mod hash; -mod hex; #[link(name = "env")] extern { @@ -133,28 +135,28 @@ impl<'a> ParamsView<'a> { ParamsView { raw: raw } } - pub fn address(&self) -> [u8; 20] { + pub fn address(&self) -> Address { let mut addr = [0u8; 20]; addr.copy_from_slice(&self.raw[0..20]); - addr + Address::from(addr) } - pub fn sender(&self) -> [u8; 20] { + pub fn sender(&self) -> Address { let mut sender = [0u8; 20]; sender.copy_from_slice(&self.raw[20..40]); - sender + Address::from(sender) } - pub fn origin(&self) -> [u8; 20] { + pub fn origin(&self) -> Address { let mut origin = [0u8; 20]; origin.copy_from_slice(&self.raw[40..60]); - origin + Address::from(origin) } - pub fn value(&self) -> [u8; 32] { + pub fn value(&self) -> U256 { let mut value = [0u8; 32]; value.copy_from_slice(&self.raw[60..92]); - value + U256::from_big_endian(&value) } pub fn args(&self) -> &[u8] { diff --git a/src/storage.rs b/src/storage.rs index 9edc555..0f3afb9 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -1,3 +1,5 @@ +use hash::H256; + #[derive(Debug)] pub struct Error; @@ -6,25 +8,24 @@ extern { fn storage_read(key: *const u8, dst: *mut u8) -> i32; fn storage_write(key: *const u8, src: *const u8) -> i32; } - -/// Performs read from storage to the specified slice `dst` +/// Performs read from storage /// Can return `Error` if data is read from outside of the storage boundaries -pub fn read(key: &[u8; 32], dst: &mut [u8; 32]) -> Result<(), Error> { +pub fn read(key: &H256) -> Result<[u8; 32], Error> { + let mut dst = [0u8; 32]; match unsafe { - let dst = dst; - storage_read(key.as_ptr(), dst.as_mut_ptr()) + storage_read(key.as_ptr(), (&mut dst).as_mut_ptr()) } { x if x < 0 => Err(Error), - _ => Ok(()), + _ => Ok(dst), } } -/// Performs write to the storage from the specified `src` -pub fn write(key: &[u8; 32], src: &[u8; 32]) -> Result<(), Error> { +/// Performs write to the storage +pub fn write(key: &H256, val: &[u8; 32]) -> Result<(), Error> { match unsafe { - storage_write(key.as_ptr(), src.as_ptr()) + storage_write(key.as_ptr(), val.as_ptr()) } { x if x < 0 => Err(Error), _ => Ok(()), } -} \ No newline at end of file +}