diff --git a/examples/runtime-storage/Cargo.toml b/examples/runtime-storage/Cargo.toml index a849cc01aeae90379b8dc2f3fbc77cbafe301226..2ec277950a105d7ccbe8654a66bc4d5fcbbcc0fd 100755 --- a/examples/runtime-storage/Cargo.toml +++ b/examples/runtime-storage/Cargo.toml @@ -6,12 +6,12 @@ edition = "2018" [dependencies] ink_primitives = { version = "2.0.0", path = "../../primitives", default-features = false } +ink_prelude = { version = "2.0.0", path = "../../prelude", default-features = false } ink_abi = { version = "2.0.0", path = "../../abi", default-features = false, features = ["derive"], optional = true } ink_core = { version = "2.0.0", path = "../../core", default-features = false } ink_lang = { version = "2.0.0", path = "../../lang", default-features = false } scale = { package = "parity-scale-codec", version = "1.2", default-features = false, features = ["derive"] } -blake2-rfc = { version = "0.2.18", default-features = false } [dependencies.type-metadata] git = "https://github.com/type-metadata/type-metadata.git" @@ -33,7 +33,6 @@ crate-type = [ default = ["test-env"] std = [ "ink_primitives/std", - "blake2-rfc/std", "ink_abi/std", "ink_core/std", "scale/std", diff --git a/examples/runtime-storage/src/lib.rs b/examples/runtime-storage/src/lib.rs index 3013e3b8d77d733da53084d8aaf69f0c05e63637..88345fbd192901453798a9830389efdb64a007ce 100755 --- a/examples/runtime-storage/src/lib.rs +++ b/examples/runtime-storage/src/lib.rs @@ -16,24 +16,40 @@ use ink_lang as ink; -mod crypto { - /// Do a Blake2 256-bit hash and place result in `dest`. - pub fn blake2_256_into(data: &[u8], dest: &mut [u8; 32]) { - dest.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); - } +#[ink::contract(version = "0.1.0")] +mod runtime { + use ink_core::{ + env, + hash::Blake2x128, + }; + use ink_prelude::{ + format, + vec, + vec::Vec, + }; + use scale::{ + Decode, + Encode, + }; - /// Do a Blake2 256-bit hash and return result. - pub fn blake2_256(data: &[u8]) -> [u8; 32] { - let mut r = [0; 32]; - blake2_256_into(data, &mut r); - r + /// All balance information for an account, mirroring the structure defined in the runtime. + /// Copied from [substrate](https://github.com/paritytech/substrate/blob/2c87fe171bc341755a43a3b32d67560469f8daac/frame/system/src/lib.rs#L307) + #[derive(Decode)] + pub struct AccountData { + free: Balance, + _reserved: Balance, + _misc_frozen: Balance, + _fee_frozen: Balance, } -} -#[ink::contract(version = "0.1.0")] -mod runtime { - use super::crypto; - use scale::KeyedVec as _; + /// Information of an account, mirroring the structure defined in the runtime + /// Copied from [substrate](https://github.com/paritytech/substrate/blob/2c87fe171bc341755a43a3b32d67560469f8daac/frame/system/src/lib.rs#L307) + #[derive(Decode)] + pub struct AccountInfo { + _nonce: u32, + _refcount: u8, + data: AccountData, + } /// This simple contract reads a value from runtime storage #[ink(storage)] @@ -43,13 +59,52 @@ mod runtime { #[ink(constructor)] fn new(&mut self) {} - /// Returns the account balance, read directly from runtime storage + /// Returns an account's free balance, read directly from runtime storage + /// + /// # Key Scheme + /// + /// A key for the [substrate storage map] + /// (https://github.com/paritytech/substrate/blob/dd97b1478b31a4715df7e88a5ebc6664425fb6c6/frame/support/src/storage/generator/map.rs#L28) + /// is constructed with: + /// + /// ```nocompile + /// Twox128(module_prefix) ++ Twox128(storage_prefix) ++ Hasher(encode(key)) + /// ``` + /// + /// For the `System` module's `Account` map, the [hasher implementation] + /// (https://github.com/paritytech/substrate/blob/2c87fe171bc341755a43a3b32d67560469f8daac/frame/system/src/lib.rs#L349) + /// is `blake2_128_concat`. #[ink(message)] fn get_balance(&self, account: AccountId) -> Balance { - const BALANCE_OF: &[u8] = b"Balances FreeBalance"; - let key = crypto::blake2_256(&account.to_keyed_vec(BALANCE_OF)); - let result = self.env().get_runtime_storage::(&key[..]); - result.unwrap_or_else(|| Ok(0)).unwrap_or_default() + let mut key = vec![ + // Precomputed: Twox128("System") + 38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247, + // Precomputed: Twox128("Account") + 185, 157, 136, 14, 198, 129, 121, 156, 12, 243, 14, 136, 134, 55, 29, 169, + ]; + + let encoded_account = &account.encode(); + + let mut blake2_128 = Blake2x128::from(Vec::new()); + let hashed_account = blake2_128.hash_raw(&encoded_account); + + // The hasher is `Blake2_128Concat` which appends the unhashed account to the hashed account + key.extend_from_slice(&hashed_account); + key.extend_from_slice(&encoded_account); + + // fetch from runtime storage + let result = self.env().get_runtime_storage::(&key[..]); + match result { + Some(Ok(account_info)) => account_info.data.free, + Some(Err(err)) => { + env::println(&format!("Error reading AccountInfo {:?}", err)); + 0 + } + None => { + env::println(&format!("No data at key {:?}", key)); + 0 + } + } } }