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"
[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",
......
......@@ -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::<Balance>(&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::<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