From 74139d98da704a63a10e4a5ac284bd774bc74305 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 30 Jan 2018 20:52:59 +0100 Subject: [PATCH] test state root calculation. --- substrate/Cargo.lock | 1 + substrate/native-runtime/Cargo.toml | 1 + substrate/wasm-runtime/polkadot/src/lib.rs | 3 + .../polkadot/src/runtime/system.rs | 118 +++++++++++++++++- 4 files changed, 117 insertions(+), 6 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index d025b1556d..7ae006d75a 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -570,6 +570,7 @@ dependencies = [ name = "native-runtime" version = "0.1.0" dependencies = [ + "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "runtime-std 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/substrate/native-runtime/Cargo.toml b/substrate/native-runtime/Cargo.toml index 25091c2cef..5ee1706e9c 100644 --- a/substrate/native-runtime/Cargo.toml +++ b/substrate/native-runtime/Cargo.toml @@ -11,3 +11,4 @@ without-std = [] [dependencies] runtime-std = { path = "./std", version = "0.1" } rustc-hex = "1.0" +hex-literal = "0.1.0" diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 1eeff3c649..6769ce9146 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -25,6 +25,9 @@ extern crate runtime_std; #[cfg(feature = "with-std")] extern crate rustc_hex; +#[macro_use] +extern crate hex_literal; + pub mod codec; #[macro_use] pub mod support; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 8ca1704c20..dccf747929 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -20,7 +20,7 @@ use runtime_std::prelude::*; use runtime_std::{mem, print, storage_root}; use codec::KeyedVec; -use support::{Hashable, storage, with_env}; +use support::{self, Hashable, storage, with_env}; use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder}; use runtime::{staking, session}; @@ -78,10 +78,6 @@ pub mod internal { // this requires non-trivial changes to the externals API or compiling trie rooting into wasm // so will wait until a little later. - // store the header hash in storage. - let header_hash_key = header.number.to_keyed_vec(BLOCK_HASH_AT); - storage::put(&header_hash_key, &header.blake2_256()); - // execute transactions block.transactions.iter().for_each(execute_transaction); @@ -91,8 +87,15 @@ pub mod internal { // any final checks final_checks(&block); + println!("SR: {}", super::support::HexDisplay::from(&storage_root())); + // check storage root. assert!(header.state_root == storage_root(), "Storage root must match that calculated."); + + // store the header hash in storage; we can't do it before otherwise there would be a + // cyclic dependency. + let header_hash_key = header.number.to_keyed_vec(BLOCK_HASH_AT); + storage::put(&header_hash_key, &header.blake2_256()); } /// Execute a given transaction. @@ -129,7 +132,7 @@ mod tests { use runtime_std::{with_externalities, twox_128, TestExternalities}; use codec::{Joiner, KeyedVec, Slicable}; use support::{StaticHexInto, HexDisplay, one, two}; - use primitives::{UncheckedTransaction, Transaction, Function}; + use primitives::{UncheckedTransaction, Transaction, Function, Header, Digest}; use runtime::staking; #[test] @@ -161,4 +164,107 @@ mod tests { assert_eq!(staking::balance(&two), 69); }); } + + fn new_test_ext() -> TestExternalities { + let one = one(); + let two = two(); + let three = [3u8; 32]; + + TestExternalities { storage: map![ + twox_128(&0u64.to_keyed_vec(b"sys:old:")).to_vec() => [69u8; 32].to_vec(), + twox_128(b"gov:apr").to_vec() => vec![].join(&667u32), + twox_128(b"ses:len").to_vec() => vec![].join(&2u64), + twox_128(b"ses:val:len").to_vec() => vec![].join(&3u32), + twox_128(&0u32.to_keyed_vec(b"ses:val:")).to_vec() => one.to_vec(), + twox_128(&1u32.to_keyed_vec(b"ses:val:")).to_vec() => two.to_vec(), + twox_128(&2u32.to_keyed_vec(b"ses:val:")).to_vec() => three.to_vec(), + twox_128(b"sta:wil:len").to_vec() => vec![].join(&3u32), + twox_128(&0u32.to_keyed_vec(b"sta:wil:")).to_vec() => one.to_vec(), + twox_128(&1u32.to_keyed_vec(b"sta:wil:")).to_vec() => two.to_vec(), + twox_128(&2u32.to_keyed_vec(b"sta:wil:")).to_vec() => three.to_vec(), + twox_128(b"sta:spe").to_vec() => vec![].join(&2u64), + twox_128(b"sta:vac").to_vec() => vec![].join(&3u64), + twox_128(b"sta:era").to_vec() => vec![].join(&0u64), + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], } + } + + #[test] + fn block_import_works() { + let one = one(); + let two = two(); + + let mut t = new_test_ext(); + + let tx = UncheckedTransaction { + transaction: Transaction { + signed: one.clone(), + nonce: 0, + function: Function::StakingTransfer, + input_data: vec![].join(&two).join(&69u64), + }, + signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(), + }; + // tx: 2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000 + // sig: 679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a + + let h = Header { + parent_hash: [69u8; 32], + number: 1, + state_root: hex!("2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db"), + transaction_root: [0u8; 32], // Unchecked currently. + digest: Digest { logs: vec![], }, + }; + + let b = Block { + header: h, + transactions: vec![tx], + }; + + with_externalities(&mut t, || { + execute_block(b); + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 69); + }); + } + + #[test] + #[should_panic] + fn block_import_of_bad_state_root_fails() { + let one = one(); + let two = two(); + + let mut t = new_test_ext(); + + let tx = UncheckedTransaction { + transaction: Transaction { + signed: one.clone(), + nonce: 0, + function: Function::StakingTransfer, + input_data: vec![].join(&two).join(&69u64), + }, + signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(), + }; + // tx: 2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000 + // sig: 679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a + + let h = Header { + parent_hash: [69u8; 32], + number: 1, + state_root: [0u8; 32], + transaction_root: [0u8; 32], // Unchecked currently. + digest: Digest { logs: vec![], }, + }; + + let b = Block { + header: h, + transactions: vec![tx], + }; + + with_externalities(&mut t, || { + execute_block(b); + assert_eq!(staking::balance(&one), 42); + assert_eq!(staking::balance(&two), 69); + }); + } }