Unverified Commit 2b796bd6 authored by Andrew Jones's avatar Andrew Jones Committed by GitHub

Update runtime storage example (#365)

* WIP: build storage key with new hashing API

* Attempt to build up correct key

* Fmt

* Update to new hashing API

* WIP: precalculate prefix hashes

* Precalculate prefix hashes

* Fmt

* Remove redundant local hashing buffers

* Fix hasher name

* Add comment re: blake2_128_concat

* Apply suggestions from code review
Co-Authored-By: default avatarHero Bird <robin.freyler@gmail.com>

* Explicit prelude imports
Co-authored-by: default avatarHero Bird <robin.freyler@gmail.com>
parent b5a693bb
Pipeline #84666 passed with stages
in 7 minutes and 32 seconds
...@@ -6,12 +6,12 @@ edition = "2018" ...@@ -6,12 +6,12 @@ edition = "2018"
[dependencies] [dependencies]
ink_primitives = { version = "2.0.0", path = "../../primitives", default-features = false } 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_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_core = { version = "2.0.0", path = "../../core", default-features = false }
ink_lang = { version = "2.0.0", path = "../../lang", 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"] } 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] [dependencies.type-metadata]
git = "https://github.com/type-metadata/type-metadata.git" git = "https://github.com/type-metadata/type-metadata.git"
...@@ -33,7 +33,6 @@ crate-type = [ ...@@ -33,7 +33,6 @@ crate-type = [
default = ["test-env"] default = ["test-env"]
std = [ std = [
"ink_primitives/std", "ink_primitives/std",
"blake2-rfc/std",
"ink_abi/std", "ink_abi/std",
"ink_core/std", "ink_core/std",
"scale/std", "scale/std",
......
...@@ -16,24 +16,40 @@ ...@@ -16,24 +16,40 @@
use ink_lang as ink; use ink_lang as ink;
mod crypto { #[ink::contract(version = "0.1.0")]
/// Do a Blake2 256-bit hash and place result in `dest`. mod runtime {
pub fn blake2_256_into(data: &[u8], dest: &mut [u8; 32]) { use ink_core::{
dest.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); env,
} hash::Blake2x128,
};
use ink_prelude::{
format,
vec,
vec::Vec,
};
use scale::{
Decode,
Encode,
};
/// Do a Blake2 256-bit hash and return result. /// All balance information for an account, mirroring the structure defined in the runtime.
pub fn blake2_256(data: &[u8]) -> [u8; 32] { /// Copied from [substrate](https://github.com/paritytech/substrate/blob/2c87fe171bc341755a43a3b32d67560469f8daac/frame/system/src/lib.rs#L307)
let mut r = [0; 32]; #[derive(Decode)]
blake2_256_into(data, &mut r); pub struct AccountData {
r free: Balance,
_reserved: Balance,
_misc_frozen: Balance,
_fee_frozen: Balance,
} }
}
#[ink::contract(version = "0.1.0")] /// Information of an account, mirroring the structure defined in the runtime
mod runtime { /// Copied from [substrate](https://github.com/paritytech/substrate/blob/2c87fe171bc341755a43a3b32d67560469f8daac/frame/system/src/lib.rs#L307)
use super::crypto; #[derive(Decode)]
use scale::KeyedVec as _; pub struct AccountInfo {
_nonce: u32,
_refcount: u8,
data: AccountData,
}
/// This simple contract reads a value from runtime storage /// This simple contract reads a value from runtime storage
#[ink(storage)] #[ink(storage)]
...@@ -43,13 +59,52 @@ mod runtime { ...@@ -43,13 +59,52 @@ mod runtime {
#[ink(constructor)] #[ink(constructor)]
fn new(&mut self) {} 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)] #[ink(message)]
fn get_balance(&self, account: AccountId) -> Balance { fn get_balance(&self, account: AccountId) -> Balance {
const BALANCE_OF: &[u8] = b"Balances FreeBalance"; let mut key = vec![
let key = crypto::blake2_256(&account.to_keyed_vec(BALANCE_OF)); // Precomputed: Twox128("System")
let result = self.env().get_runtime_storage::<Balance>(&key[..]); 38, 170, 57, 78, 234, 86, 48, 224, 124, 72, 174, 12, 149, 88, 206, 247,
result.unwrap_or_else(|| Ok(0)).unwrap_or_default() // 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::<AccountInfo>(&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
}
}
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment