From ead42293bc08c8a044f68d0c1fd17dc94f31880e Mon Sep 17 00:00:00 2001 From: Gav Date: Thu, 25 Jan 2018 19:28:28 +0100 Subject: [PATCH] Tests for native/wasm runtime --- substrate/Cargo.lock | 7 +++ substrate/executor/Cargo.toml | 1 + substrate/executor/src/lib.rs | 2 + substrate/executor/src/native_executor.rs | 50 ++++++++++++++++++ substrate/executor/src/wasm_executor.rs | 26 ++++----- substrate/wasm-runtime/polkadot/src/lib.rs | 17 ++++-- .../polkadot/src/runtime/system.rs | 3 ++ .../polkadot/src/support/function.rs | 2 +- .../wasm-runtime/polkadot/src/support/mod.rs | 4 +- .../polkadot/src/support/primitives.rs | 14 ++--- .../polkadot/src/support/proposal.rs | 4 +- substrate/wasm-runtime/pwasm-libc/src/lib.rs | 7 +++ .../release/runtime_polkadot.compact.wasm | Bin 42933 -> 42937 bytes .../release/runtime_polkadot.wasm | Bin 42990 -> 43015 bytes .../release/runtime_test.wasm | Bin 1905 -> 1943 bytes 15 files changed, 105 insertions(+), 32 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 1595bc0272..a7047446eb 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -498,6 +498,11 @@ dependencies = [ "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memcmp" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memorydb" version = "0.1.1" @@ -726,6 +731,7 @@ dependencies = [ "assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memcmp 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-runtime 0.1.0", "parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-primitives 0.1.0", @@ -1333,6 +1339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" +"checksum memcmp 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9a1b44fee357b6a05a9e22554ded6c1bbe57844b58190295257ac0ad4c5944e1" "checksum memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "013b7e4c5e10c764936ebc6bd3662d8e3c92292d267bf6a42ef3f5cad9c793ee" "checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" "checksum mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0e8411968194c7b139e9105bc4ae7db0bae232af087147e72f0616ebf5fdb9cb" diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index dbdef883cc..6164bb1c51 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -15,6 +15,7 @@ byteorder = "1.1" rustc-hex = "1.0.0" native-runtime = { path = "../native-runtime", version = "0.1" } runtime-support = { path = "../native-runtime/support", version = "0.1" } +memcmp = { version = "0.0.6" } [dev-dependencies] assert_matches = "1.1" diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index 56c39e5b49..17b1ec9025 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -34,8 +34,10 @@ extern crate serde; extern crate parity_wasm; extern crate byteorder; extern crate rustc_hex; +#[macro_use] extern crate native_runtime; extern crate runtime_support; +extern crate memcmp; #[macro_use] extern crate error_chain; diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 28146a46ea..e195e8f8d7 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -33,3 +33,53 @@ impl CodeExecutor for NativeExecutor { } } } + +#[cfg(test)] +mod tests { + use super::*; + use primitives::twox_128; + use native_runtime::testing::{TestExternalities, one, two}; + use native_runtime::statichex::StaticHexInto; + use native_runtime::keyedvec::KeyedVec; + use native_runtime::runtime::staking::balance; + + fn tx() -> Vec { "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000".convert() } + + #[test] + fn execution_with_native_equivalent_code_runs_native_ok() { + let one = one(); + let two = two(); + + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let native_equivalent_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); + NativeExecutor.call(&mut t, &native_equivalent_code[..], "execute_transaction", &CallData(tx())); + + runtime_support::with_externalities(&mut t, || { + assert_eq!(balance(&one), 42); + assert_eq!(balance(&two), 69); + }); + } + + #[test] + fn execution_with_foreign_code_runs_wasm_ok() { + let one = one(); + let two = two(); + + let mut t = TestExternalities { storage: map![ + twox_128(&one.to_keyed_vec(b"sta:bal:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + ], }; + + let mut foreign_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); + NativeExecutor.call(&mut t, &foreign_code[..], "execute_transaction", &CallData(tx())); + + runtime_support::with_externalities(&mut t, || { + assert_eq!(balance(&one), 42); + assert_eq!(balance(&two), 69); + }); + } + + // TODO: test panics. +} diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 561e557ad9..f7d922d6fb 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -87,6 +87,15 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, ext_print_num(number: u64) => { println!("Runtime: {}", number); }, + ext_memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 => { + if let (Ok(sl1), Ok(sl2)) + = (this.memory.get(s1, n as usize), this.memory.get(s2, n as usize)) { + use memcmp::Memcmp; + (&sl1).memcmp(&sl2) as i32 + } else { + 0 + } + }, ext_memcpy(dest: *mut u8, src: *const u8, count: usize) -> *mut u8 => { let _ = this.memory.copy_nonoverlapping(src as usize, dest as usize, count as usize); println!("memcpy {} from {}, {} bytes", dest, src, count); @@ -242,22 +251,7 @@ mod tests { use super::*; use rustc_hex::FromHex; use state_machine::ExternalitiesError; - - #[derive(Debug, Default)] - struct TestExternalities { - storage: HashMap, Vec>, - } - impl Externalities for TestExternalities { - fn storage(&self, key: &[u8]) -> ::std::result::Result<&[u8], ExternalitiesError> { - Ok(self.storage.get(&key.to_vec()).map_or(&[] as &[u8], Vec::as_slice)) - } - - fn set_storage(&mut self, key: Vec, value: Vec) { - self.storage.insert(key, value); - } - - fn chain_id(&self) -> u64 { 42 } - } + use native_runtime::testing::{TestExternalities, one, two}; #[test] fn storage_should_work() { diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 3d52aa589f..1134d974a7 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -22,22 +22,28 @@ #[macro_use] extern crate runtime_support; -#[cfg(test)] +#[cfg(feature = "with-std")] extern crate rustc_hex; mod codec; #[macro_use] mod support; -mod runtime; +pub mod runtime; pub use codec::{endiansensitive, streamreader, joiner, slicable, keyedvec}; pub use support::{primitives, function, proposal, environment, storable}; -#[cfg(test)] +#[cfg(feature = "with-std")] pub use support::{testing, statichex}; use runtime_support::prelude::*; use slicable::Slicable; use primitives::{Block, UncheckedTransaction}; +/// A simple test. +pub fn simple_test(input: &[u8]) -> Vec { + println!("Executing block"); + Vec::new() +} + /// Execute a block, with `input` being the canonical serialisation of the block. Returns the /// empty vector. pub fn execute_block(input: &[u8]) -> Vec { @@ -47,7 +53,10 @@ pub fn execute_block(input: &[u8]) -> Vec { /// Execute a given, serialised, transaction. Returns the empty vector. pub fn execute_transaction(input: &[u8]) -> Vec { - runtime::system::execute_transaction(&UncheckedTransaction::from_slice(input).unwrap()); + println!("Deserialising... {:?}", input); + let utx = UncheckedTransaction::from_slice(input).unwrap(); + println!("Forwarding... {:?}", utx); + runtime::system::execute_transaction(&utx); Vec::new() } diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 042d1af2d7..70348574b1 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -84,6 +84,7 @@ pub fn execute_block(mut block: Block) { /// Execute a given transaction. pub fn execute_transaction(utx: &UncheckedTransaction) { + println!("Executing..."); // Verify the signature is good. assert!(utx.ed25519_verify(), "All transactions should be properly signed"); @@ -97,6 +98,8 @@ pub fn execute_transaction(utx: &UncheckedTransaction) { // increment nonce in storage (expected_nonce + 1).store(&nonce_key); + println!("Dispatching..."); + // decode parameters and dispatch tx.function.dispatch(&tx.signed, &tx.input_data); } diff --git a/substrate/wasm-runtime/polkadot/src/support/function.rs b/substrate/wasm-runtime/polkadot/src/support/function.rs index dd54ba1080..875bb98326 100644 --- a/substrate/wasm-runtime/polkadot/src/support/function.rs +++ b/substrate/wasm-runtime/polkadot/src/support/function.rs @@ -21,8 +21,8 @@ use streamreader::StreamReader; use runtime::{staking, session, timestamp, governance}; /// Public functions that can be dispatched to. -#[cfg_attr(test, derive(PartialEq, Debug))] #[derive(Clone, Copy)] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] pub enum Function { StakingStake, StakingUnstake, diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 384909d019..3730483b25 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -22,8 +22,8 @@ pub mod proposal; pub mod environment; pub mod storable; -#[cfg(test)] +#[cfg(feature = "with-std")] pub mod statichex; -#[cfg(test)] #[macro_use] +#[cfg(feature = "with-std")] pub mod testing; diff --git a/substrate/wasm-runtime/polkadot/src/support/primitives.rs b/substrate/wasm-runtime/polkadot/src/support/primitives.rs index fe5bb2ebbd..48fa91dd79 100644 --- a/substrate/wasm-runtime/polkadot/src/support/primitives.rs +++ b/substrate/wasm-runtime/polkadot/src/support/primitives.rs @@ -23,7 +23,7 @@ use slicable::{Slicable, NonTrivialSlicable}; use function::Function; use runtime_support::{mem, blake2_256, twox_128, twox_256, ed25519_verify}; -#[cfg(test)] +#[cfg(feature = "with-std")] use std::fmt; /// The Ed25519 pubkey that identifies an account. @@ -51,7 +51,7 @@ pub type TxOrder = u64; pub type Hash = [u8; 32]; #[derive(Clone, Default)] -#[cfg_attr(test, derive(PartialEq, Debug))] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] /// The digest of a block, useful for light-clients. pub struct Digest { /// All logs that have happened in the block. @@ -59,7 +59,7 @@ pub struct Digest { } #[derive(Clone)] -#[cfg_attr(test, derive(PartialEq, Debug))] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] /// The header for a block. pub struct Header { /// The parent block's "hash" (actually the Blake2-256 hash of its serialised header). @@ -108,8 +108,8 @@ impl Slicable for Header { impl NonTrivialSlicable for Header {} -#[cfg_attr(test, derive(PartialEq, Debug))] /// A vetted and verified transaction from the external world. +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] pub struct Transaction { /// Who signed it (note this is not a signature). pub signed: AccountID, @@ -187,14 +187,14 @@ impl UncheckedTransaction { } } -#[cfg(test)] +#[cfg(feature = "with-std")] impl PartialEq for UncheckedTransaction { fn eq(&self, other: &Self) -> bool { self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction } } -#[cfg(test)] +#[cfg(feature = "with-std")] impl fmt::Debug for UncheckedTransaction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "UncheckedTransaction({:?})", self.transaction) @@ -229,8 +229,8 @@ impl Slicable for UncheckedTransaction { impl NonTrivialSlicable for UncheckedTransaction {} -#[cfg_attr(test, derive(PartialEq, Debug))] /// A Polkadot relay chain block. +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] pub struct Block { /// The header of the block. pub header: Header, diff --git a/substrate/wasm-runtime/polkadot/src/support/proposal.rs b/substrate/wasm-runtime/polkadot/src/support/proposal.rs index ec02e32dfb..663692a4f7 100644 --- a/substrate/wasm-runtime/polkadot/src/support/proposal.rs +++ b/substrate/wasm-runtime/polkadot/src/support/proposal.rs @@ -25,8 +25,8 @@ use streamreader::StreamReader; use runtime::{system, governance, staking, session}; /// Internal functions that can be dispatched to. -#[cfg_attr(test, derive(PartialEq, Debug))] #[derive(Clone, Copy)] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] pub enum InternalFunction { SystemSetCode, StakingSetSessionsPerEra, @@ -52,7 +52,7 @@ impl InternalFunction { } /// An internal function. -#[cfg_attr(test, derive(PartialEq, Debug))] +#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] pub struct Proposal { /// The priviledged function to call. pub function: InternalFunction, diff --git a/substrate/wasm-runtime/pwasm-libc/src/lib.rs b/substrate/wasm-runtime/pwasm-libc/src/lib.rs index eed597e73b..0c2fd43fc6 100644 --- a/substrate/wasm-runtime/pwasm-libc/src/lib.rs +++ b/substrate/wasm-runtime/pwasm-libc/src/lib.rs @@ -8,6 +8,7 @@ extern "C" { fn ext_memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8; fn ext_memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8; fn ext_memset(dest: *mut u8, c: i32, n: usize) -> *mut u8; + fn ext_memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32; fn ext_malloc(size: usize) -> *mut u8; fn ext_free(ptr: *mut u8); } @@ -21,6 +22,12 @@ pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut ext_memcpy(dest, src, n) } +/// memcpy extern +#[no_mangle] +pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { + ext_memcmp(s1, s2, n) +} + /// memmove extern #[no_mangle] pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm index 84f659746094ead43a63d2c53ed6422c1ec6a879..688c7bcdb8250ae6b2dafcf249e880cdf929fd92 100644 GIT binary patch delta 788 zcmYjPZAep57~Yw?dei{5+Z;4b3Y3IM7`(QmVch}Jm-DhuXFFyIqkDK?SPBC z3A-=o`~i&+e(hkCOl}~0_91Uki${!_1w58Ec`}I}TFX8oZr>4CaTnWC-ilEORhAQx zy{t476u(WSC`xu4|BFD?3h}r)6C*5cZsvx#*~2ZL@clFDZ_E5wha0IRK(2&~h#It|F(b zZ|$!T`yF=d_03^HUQox!cGkskYshTaiGjTh0p#jHPY%4`Y154rc>k-h1$n)*56jLw zT_jCU4bb9r!u95MH6fSj4pwphkZTVSS@$7{7hM+fu5B1$;^C8goU?83wOGY`^c;7v zj-XCYMG7+=MH%uek%=U-)1Ld;=v;g86L&6N8c0XyLZljM#w4vI!n><|>P0U2f{*^O zlCC8C+4UtAwL@{YAJt4x6K)|zO;8jvpiU@-@Nh5-#zrIvhK{Fd*ul|rCgq<{OiMLS$SpJO?N(CE;Ugqy7jk)P3TqVbK5;X{%6)ZNoRUmC*XD)%qbpOEtt#Vhmuh zWz%LtliCoBqS2VZ;%bDT1Z62&W#Lj>xN+eEqsHIDxvx-RbMBluGiPS<-c(xkB&~{h z$z1%d=^S3mRMk=W-aM`pSOZYju!PBikLKg*JN$V$i+~5$rn=XY8lSw1rf#(k@D@R950yVHNqfLZI1EMYQaiV?z#+ zSiITH2fuEaLyWh!;G7SwHjGQ#_{N=WlXx)XJ9nYra0W3}mSMRErg`72s}63drHSne{stA6V?)NX3 zh&Nl{`oIeNHSk`^rx9<54~iPPWuE|sv0DASU`1k$kuF&RU!(#i68W$-EW_a7>8#cB zOdH-jK4#W`Tias7O;eGd{MO8FW|&RL?EBD?gegzbfx2PX&UH_+mQ5rc@;jA07=|n0 zRWh7yZ3cGhOqTH@*W)r;2&F>V>`RQ++yLz(I?VYZbwI-+OO9M2qC^X65ybi|%spDf wf2rWzxPm*Ne5^^S#=Y?z{?UCA9+yO_mz~bv`=J+g>jWxLLRGSw_1t%mfAa|gYXATM diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm index d758dcbb60ab7897654b228c382cf017239b01fe..861eb4c60800e920bc63aa8632272991c5c03d73 100644 GIT binary patch delta 975 zcmYjPT}YEr82--ZzJ2@l!?x0mg7TY%zx|MZRinrWz0ClyXbQxwENt4+~T z4o3cEkdx6xUYr6;G$RTE!RjJ*Q`kk3soex6(M9k1bkkit@AI7JJlza$cRTCr8*7+&SzWWs#Uu!bQLesaO(cL`grQh` zk1GOPNpFp$IxS+u{Y^bDjvDb>-`Eg_U20f(esx3gmK}fXsoqw{y>|TQ zMo=BP`7zY>4A_RZ7&Z|-boWSK93J#|L-*!GeqbsCclD~Io^;scb?+u!OFLdjwEai` zsvpjUoTZUC(ldOJdivp$5T?i4ejWLH*Gtz5_RL6Eo%qw}Wr=0u#}g5FWUN(E0l?r? z8F;|A^=cYfn7B^AujMN@g8B7HC)4oq$BL;1>7(ss&-?>8Qu XRv9^!k`WmZiL8#_p$alRos0ehM@t+t delta 1013 zcmYjPYivtl7(U-wFQ@Hlr%Wpn%{R$(#fZzWOLZr#ExJivMmE>kX`B3u^ns#mzoSNWnRTZWih+up>EK>H7+|MBnxT0N!_*=V$I9Q#oQpAvuYy<-{ zRBJGhai=(o=bc9ev-5+9XYx;Csc<4e1sqlnVzV`h_|w{oLbENQBL-%)e-bf#r*18V z`O{Q0F+k6}7l`5c_tLnCHI{5b6^6=6h{S%Exe1cein&OdDssojb=QC7^I|hs0*VTo zE5BjyfU--2g`uhe#BYJ+M1qtjAKrO%;I?Vuqo7`i3syqDMuhpeyNvx!KRc3)|WYGk2?IfsOQ<64X;nJGDILo%Sj^r7r ziCPrgNs&TML4Z`14<6NS9Wk=XbuQkoZT%7=u?OpAK6QlH>Svgm}aX7ki4p9W%k-qdL4s z7derxKg_7Es2>K7HDuVFa#W%A$_@^mOI^jY`G~;wd?`HKtY(y_3 z5_=i@#V;BeT+XI+5(B5*KJ4?R+sWdm?P~ zkf1-YJ6l}=ZRhqO8{M)T5=j&C;$$g$wJdf1ApeH`-g^G$ibp2G%03G`y}TpK>eFuA v8v?QN+&-e{sa@$JA(=PfxXa04P2+yRLn zDQDn7v@~G5f!EA?-)NrZtNm;~oeK}x*k0U|I0Iq(@pxqDa;=t7iC{ud1|SLuEcpc) zVZvy5A`Gk9Wg1nO!$b!hL{-*fGF8fB>{tprWrBknI${b{cGvhFBYpQn`Uq)d YU-~S+CCwH!73yOLQ~A%fN=XiX0Xj!X?*IS* delta 271 zcmbQv|B-KkJ@b1;o{3J?6VH{%@Nlz(00%QOGYb<73u6HT11mElgCP4tMxM#>jN(mYbTJTu{j%#13TS=9i^12!n)*Q%e{`*m4tda`FX} z8AMsqic(V<#5frlxE677Pv&Qm6y$JJaAZ|rP+%0`bkuNU7vPv|$)o@jHF0ECU;>L; qIC2VbY|dg@&&0?*xq