From a68b187f4da0f647c60f808b964f7d082c77347f Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 30 Jan 2018 18:51:12 +0100 Subject: [PATCH 01/21] extract out runtime-codec to a separate crate --- substrate/Cargo.lock | 6 ++++++ substrate/Cargo.toml | 1 + substrate/executor/Cargo.toml | 1 + substrate/executor/src/lib.rs | 1 + substrate/executor/src/native_executor.rs | 4 ++-- substrate/executor/src/wasm_executor.rs | 2 +- substrate/native-runtime/Cargo.toml | 11 ++++++----- substrate/runtime-codec/Cargo.toml | 11 +++++++++++ .../src}/endiansensitive.rs | 0 .../src/codec => runtime-codec/src}/joiner.rs | 15 ++++++++------- .../codec => runtime-codec/src}/keyedvec.rs | 9 +++++---- .../codec/mod.rs => runtime-codec/src/lib.rs} | 14 +++++++++++++- .../codec => runtime-codec/src}/slicable.rs | 17 +++++++++-------- .../src}/streamreader.rs | 2 +- substrate/wasm-runtime/Cargo.lock | 5 +++++ substrate/wasm-runtime/polkadot/Cargo.toml | 3 ++- substrate/wasm-runtime/polkadot/src/lib.rs | 4 ++-- .../polkadot/src/primitives/block.rs | 2 +- .../polkadot/src/primitives/header.rs | 2 +- .../polkadot/src/primitives/proposal.rs | 6 +++--- .../polkadot/src/primitives/transaction.rs | 2 +- .../src/primitives/uncheckedtransaction.rs | 2 +- .../polkadot/src/support/storage.rs | 2 +- .../release/runtime_polkadot.compact.wasm | Bin 64085 -> 65037 bytes .../release/runtime_polkadot.wasm | Bin 64134 -> 65086 bytes .../release/runtime_test.compact.wasm | Bin 13189 -> 13189 bytes .../release/runtime_test.wasm | Bin 13314 -> 13314 bytes 27 files changed, 82 insertions(+), 40 deletions(-) create mode 100644 substrate/runtime-codec/Cargo.toml rename substrate/{wasm-runtime/polkadot/src/codec => runtime-codec/src}/endiansensitive.rs (100%) rename substrate/{wasm-runtime/polkadot/src/codec => runtime-codec/src}/joiner.rs (69%) rename substrate/{wasm-runtime/polkadot/src/codec => runtime-codec/src}/keyedvec.rs (92%) rename substrate/{wasm-runtime/polkadot/src/codec/mod.rs => runtime-codec/src/lib.rs} (77%) rename substrate/{wasm-runtime/polkadot/src/codec => runtime-codec/src}/slicable.rs (88%) rename substrate/{wasm-runtime/polkadot/src/codec => runtime-codec/src}/streamreader.rs (98%) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index c741c845a5..3b715cee8d 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -553,6 +553,7 @@ dependencies = [ name = "native-runtime" version = "0.1.0" dependencies = [ + "polkadot-runtime-codec 0.1.0", "runtime-std 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -730,6 +731,7 @@ dependencies = [ "native-runtime 0.1.0", "parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-primitives 0.1.0", + "polkadot-runtime-codec 0.1.0", "polkadot-serializer 0.1.0", "polkadot-state-machine 0.1.0", "runtime-std 0.1.0", @@ -780,6 +782,10 @@ dependencies = [ "polkadot-rpc 0.1.0", ] +[[package]] +name = "polkadot-runtime-codec" +version = "0.1.0" + [[package]] name = "polkadot-serializer" version = "0.1.0" diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index 21232d39ef..f01f860386 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -18,6 +18,7 @@ members = [ "rpc", "rpc_servers", "native-runtime", + "runtime-codec", "serializer", "state_machine", "validator", diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index 5329eb7023..f27f7e2b26 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Parity Technologies "] [dependencies] error-chain = "0.11" +polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1" } polkadot-primitives = { path = "../primitives", version = "0.1" } polkadot-serializer = { path = "../serializer", version = "0.1" } polkadot-state-machine = { path = "../state_machine" , version = "0.1" } diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index 9935f8aec8..10684b1531 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -27,6 +27,7 @@ #![warn(missing_docs)] +extern crate polkadot_runtime_codec as codec; extern crate polkadot_primitives as primitives; extern crate polkadot_serializer as serializer; extern crate polkadot_state_machine as state_machine; diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index b8c90f2d9a..d47719662c 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -41,8 +41,8 @@ impl CodeExecutor for NativeExecutor { #[cfg(test)] mod tests { use super::*; - use native_runtime::codec::KeyedVec; - use native_runtime::support::{TestExternalities, one, two, StaticHexInto}; + use codec::KeyedVec; + use native_runtime::support::{one, two, TestExternalities, StaticHexInto}; use native_runtime::runtime::staking::balance; use primitives::twox_128; diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 439defd449..01601ac379 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -280,8 +280,8 @@ mod tests { use rustc_hex::FromHex; use primitives::{blake2_256, twox_128}; use runtime_std; + use codec::KeyedVec; use native_runtime::support::{one, two, StaticHexInto, TestExternalities}; - use native_runtime::codec::KeyedVec; use native_runtime::runtime::staking::balance; #[test] diff --git a/substrate/native-runtime/Cargo.toml b/substrate/native-runtime/Cargo.toml index 25091c2cef..60dbbe19c6 100644 --- a/substrate/native-runtime/Cargo.toml +++ b/substrate/native-runtime/Cargo.toml @@ -3,11 +3,12 @@ name = "native-runtime" version = "0.1.0" authors = ["Parity Technologies "] +[dependencies] +polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1" } +runtime-std = { path = "./std", version = "0.1" } +rustc-hex = "1.0" + [features] default = ["with-std"] with-std = [] -without-std = [] - -[dependencies] -runtime-std = { path = "./std", version = "0.1" } -rustc-hex = "1.0" +without-std = ["polkadot-runtime-codec/no-std"] diff --git a/substrate/runtime-codec/Cargo.toml b/substrate/runtime-codec/Cargo.toml new file mode 100644 index 0000000000..3221a55802 --- /dev/null +++ b/substrate/runtime-codec/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "polkadot-runtime-codec" +description = "Serialization and deserialization codec for runtime values" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] + +[features] +no-std = [] +default = [] diff --git a/substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs b/substrate/runtime-codec/src/endiansensitive.rs similarity index 100% rename from substrate/wasm-runtime/polkadot/src/codec/endiansensitive.rs rename to substrate/runtime-codec/src/endiansensitive.rs diff --git a/substrate/wasm-runtime/polkadot/src/codec/joiner.rs b/substrate/runtime-codec/src/joiner.rs similarity index 69% rename from substrate/wasm-runtime/polkadot/src/codec/joiner.rs rename to substrate/runtime-codec/src/joiner.rs index a7a9f618eb..1d19851243 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/joiner.rs +++ b/substrate/runtime-codec/src/joiner.rs @@ -14,19 +14,20 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! Vec serialiser. +//! Trait -use runtime_std::prelude::*; +use std::iter::Extend; use super::slicable::Slicable; -/// Trait to allow itself to be serialised into a `Vec` +/// Trait to allow itself to be serialised into a value which can be extended +/// by bytes. pub trait Joiner { - fn join(self, value: &T) -> Self; + fn join(self, value: &V) -> Self; } -impl Joiner for Vec { - fn join(mut self, value: &T) -> Vec { - value.as_slice_then(|s| self.extend_from_slice(s)); +impl Joiner for T where T: for<'a> Extend<&'a u8> { + fn join(mut self, value: &V) -> Self { + value.as_slice_then(|s| self.extend(s)); self } } diff --git a/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs b/substrate/runtime-codec/src/keyedvec.rs similarity index 92% rename from substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs rename to substrate/runtime-codec/src/keyedvec.rs index 2c55cb5648..2b4bc99fbd 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/keyedvec.rs +++ b/substrate/runtime-codec/src/keyedvec.rs @@ -16,8 +16,9 @@ //! Serialiser and prepender. -use runtime_std::prelude::*; -use super::slicable::Slicable; +use slicable::Slicable; +use std::iter::Extend; +use std::vec::Vec; /// Trait to allow itselg to be serialised and prepended by a given slice. pub trait KeyedVec { @@ -29,7 +30,7 @@ macro_rules! impl_non_endians { impl KeyedVec for $t { fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { let mut r = prepend_key.to_vec(); - r.extend_from_slice(&self[..]); + r.extend(&self[..]); r } } @@ -42,7 +43,7 @@ macro_rules! impl_endians { fn to_keyed_vec(&self, prepend_key: &[u8]) -> Vec { self.as_slice_then(|slice| { let mut r = prepend_key.to_vec(); - r.extend_from_slice(slice); + r.extend(slice); r }) } diff --git a/substrate/wasm-runtime/polkadot/src/codec/mod.rs b/substrate/runtime-codec/src/lib.rs similarity index 77% rename from substrate/wasm-runtime/polkadot/src/codec/mod.rs rename to substrate/runtime-codec/src/lib.rs index 94afc574c1..060df4e95c 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/mod.rs +++ b/substrate/runtime-codec/src/lib.rs @@ -14,7 +14,11 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! Codec utils. +//! Implements the serialization and deserialization codec for polkadot runtime +//! values. + +#![cfg_attr(feature = "no-std", no_std)] +#![cfg_attr(feature = "no-std", feature(alloc))] mod endiansensitive; mod slicable; @@ -27,3 +31,11 @@ pub use self::slicable::{Slicable, NonTrivialSlicable}; pub use self::streamreader::StreamReader; pub use self::joiner::Joiner; pub use self::keyedvec::KeyedVec; + +#[cfg(feature = "no-std")] +mod std { + extern crate alloc; + + pub use core::*; + pub use self::alloc::vec; +} diff --git a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs b/substrate/runtime-codec/src/slicable.rs similarity index 88% rename from substrate/wasm-runtime/polkadot/src/codec/slicable.rs rename to substrate/runtime-codec/src/slicable.rs index 0f1ef812a6..82b527c771 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/slicable.rs +++ b/substrate/runtime-codec/src/slicable.rs @@ -16,15 +16,16 @@ //! Serialisation. -use runtime_std::prelude::*; -use runtime_std::{mem, slice}; +use std::{mem, slice}; +use std::vec::Vec; use super::joiner::Joiner; use super::endiansensitive::EndianSensitive; /// Trait that allows zero-copy read/write of value-references to/from slices in LE format. pub trait Slicable: Sized { + /// Attempt to deserialise the value from a slice. fn from_slice(value: &[u8]) -> Option { - Self::set_as_slice(&|out, offset| if value.len() >= out.len() + offset { + Self::set_as_slice(|out, offset| if value.len() >= out.len() + offset { let value = &value[offset..]; let len = out.len(); out.copy_from_slice(&value[0..len]); @@ -36,7 +37,7 @@ pub trait Slicable: Sized { fn to_vec(&self) -> Vec { self.as_slice_then(|s| s.to_vec()) } - fn set_as_slice bool>(set_slice: &F) -> Option; + fn set_as_slice bool>(fill_slice: F) -> Option; fn as_slice_then R>(&self, f: F) -> R { f(&self.to_vec()) } @@ -47,7 +48,7 @@ pub trait Slicable: Sized { pub trait NonTrivialSlicable: Slicable {} impl Slicable for T { - fn set_as_slice bool>(fill_slice: &F) -> Option { + fn set_as_slice bool>(fill_slice: F) -> Option { let size = mem::size_of::(); assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type."); let mut result: T = unsafe { mem::zeroed() }; @@ -81,8 +82,8 @@ impl Slicable for Vec { fn from_slice(value: &[u8]) -> Option { Some(value[4..].to_vec()) } - fn set_as_slice bool>(fill_slice: &F) -> Option { - u32::set_as_slice(fill_slice).and_then(|len| { + fn set_as_slice bool>(fill_slice: F) -> Option { + u32::set_as_slice(&fill_slice).and_then(|len| { let mut v = Vec::with_capacity(len as usize); unsafe { v.set_len(len as usize); } if fill_slice(&mut v, 4) { @@ -117,7 +118,7 @@ impl Slicable for Vec { Some(r) } - fn set_as_slice bool>(_fill_slice: &F) -> Option { + fn set_as_slice bool>(_fill_slice: F) -> Option { unimplemented!(); } diff --git a/substrate/wasm-runtime/polkadot/src/codec/streamreader.rs b/substrate/runtime-codec/src/streamreader.rs similarity index 98% rename from substrate/wasm-runtime/polkadot/src/codec/streamreader.rs rename to substrate/runtime-codec/src/streamreader.rs index b745f8afd9..33056a5ac3 100644 --- a/substrate/wasm-runtime/polkadot/src/codec/streamreader.rs +++ b/substrate/runtime-codec/src/streamreader.rs @@ -16,7 +16,7 @@ //! Deserialiser. -use super::slicable::Slicable; +use slicable::Slicable; /// Simple deserialiser. pub struct StreamReader<'a> { diff --git a/substrate/wasm-runtime/Cargo.lock b/substrate/wasm-runtime/Cargo.lock index 15ccc67c64..93bc305136 100644 --- a/substrate/wasm-runtime/Cargo.lock +++ b/substrate/wasm-runtime/Cargo.lock @@ -1,3 +1,7 @@ +[[package]] +name = "polkadot-runtime-codec" +version = "0.1.0" + [[package]] name = "pwasm-alloc" version = "0.1.0" @@ -13,6 +17,7 @@ version = "0.1.0" name = "runtime-polkadot" version = "0.1.0" dependencies = [ + "polkadot-runtime-codec 0.1.0", "runtime-std 0.1.0", ] diff --git a/substrate/wasm-runtime/polkadot/Cargo.toml b/substrate/wasm-runtime/polkadot/Cargo.toml index 669ccac6fa..5cc45d4c01 100644 --- a/substrate/wasm-runtime/polkadot/Cargo.toml +++ b/substrate/wasm-runtime/polkadot/Cargo.toml @@ -7,9 +7,10 @@ authors = ["Parity Technologies "] crate-type = ["cdylib"] [dependencies] +polkadot-runtime-codec = { path = "../../runtime-codec", version = "0.1" } runtime-std = { path = "../std", version = "0.1" } [features] default = ["without-std"] with-std = [] -without-std = [] +without-std = ["polkadot-runtime-codec/no-std"] diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 1eeff3c649..ceec42af21 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -17,7 +17,6 @@ //! The Polkadot runtime. This can be compiled with #[no_std], ready for Wasm. #![cfg_attr(feature = "without-std", no_std)] -#![cfg_attr(feature = "strict", deny(warnings))] #[macro_use] extern crate runtime_std; @@ -25,7 +24,8 @@ extern crate runtime_std; #[cfg(feature = "with-std")] extern crate rustc_hex; -pub mod codec; +extern crate polkadot_runtime_codec as codec; + #[macro_use] pub mod support; pub mod primitives; diff --git a/substrate/wasm-runtime/polkadot/src/primitives/block.rs b/substrate/wasm-runtime/polkadot/src/primitives/block.rs index d33b51609c..a884bcccec 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/block.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/block.rs @@ -38,7 +38,7 @@ impl Slicable for Block { }) } - fn set_as_slice bool>(_fill_slice: &F) -> Option { + fn set_as_slice bool>(_fill_slice: F) -> Option { unimplemented!(); } diff --git a/substrate/wasm-runtime/polkadot/src/primitives/header.rs b/substrate/wasm-runtime/polkadot/src/primitives/header.rs index c97d5ebf29..4c1ec328ea 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/header.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/header.rs @@ -49,7 +49,7 @@ impl Slicable for Header { }) } - fn set_as_slice bool>(_fill_slice: &F) -> Option { + fn set_as_slice bool>(_fill_slice: F) -> Option { unimplemented!(); } diff --git a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs index 1b8aa6b13e..8eb050cf67 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs @@ -65,10 +65,10 @@ pub struct Proposal { } impl Slicable for Proposal { - fn set_as_slice bool>(fill_slice: &F) -> Option { + fn set_as_slice bool>(fill_slice: F) -> Option { Some(Proposal { - function: InternalFunction::from_u8(Slicable::set_as_slice(fill_slice)?)?, - input_data: Slicable::set_as_slice(&|s, o| fill_slice(s, o + 1))?, + function: InternalFunction::from_u8(Slicable::set_as_slice(&fill_slice)?)?, + input_data: Slicable::set_as_slice(|s, o| fill_slice(s, o + 1))?, }) } diff --git a/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs b/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs index 9c72e31d34..73ab9edd29 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs @@ -45,7 +45,7 @@ impl Slicable for Transaction { }) } - fn set_as_slice bool>(_fill_slice: &F) -> Option { + fn set_as_slice bool>(_fill_slice: F) -> Option { unimplemented!(); } diff --git a/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs b/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs index ec14befb55..83984e08a4 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs @@ -63,7 +63,7 @@ impl Slicable for UncheckedTransaction { }) } - fn set_as_slice bool>(_fill_slice: &F) -> Option { + fn set_as_slice bool>(_fill_slice: F) -> Option { unimplemented!(); } diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs index 3ff8b1c75d..bf9d605eb5 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -24,7 +24,7 @@ use codec::{Slicable, KeyedVec}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. pub fn get(key: &[u8]) -> Option { - Slicable::set_as_slice(&|out, offset| + Slicable::set_as_slice(|out, offset| runtime_std::read_storage(&twox_128(key)[..], out, offset) >= out.len() ) } 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 db7dab9917d324f143aea0837c0fdf2ee30504bc..898f194e802daf2caf927eb0e35beb50b42fd7ec 100644 GIT binary patch literal 65037 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

*KYYz}8m`^=XZpw0BwcPO~FEV!KOodfMNimu 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 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 a0dc5a2754ab33efa1b1deea73317bc369fdc975..a4c416d6daa03931da423279558aa10e2c582db7 100644 GIT binary patch literal 65086 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 literal 64134 zcmeFa3!Gimec!wHK94zb&Y77r@6pUiTIV2O1bU4gqZc;Xih0P`h9pix9oGnhY&Zf5 zB!Tg*V-1)%N{nrsx-p;Bag>w>lA0T(A1C3uG*(*2A*pMV`*CV+Zf>IHw^Pn*(~ zwzMVYet-Y9_C9+?LP+@4-cJx`*4}Hc$AA6b>%Z1sJG%Ag-EkB}@qyv}rQ^qs$H(_4 z_E$I2{xW}+7js?FwZBo$2P2gXMWX#tw7<^^Sdl3HAWtb$I{rb*sL2oRkK*IWgULYY zz@hsG4?J+}mUrKE>%jw?Z`r(UAxe}vqRa!gZ{D_Te&;RsA2@R7d)^Tbd zKvdT4m~P*D;Mgrkj~za8>w6E}a_6CAhog!f)%ED^TkpE-@NH4GmvP|k+wQ(6ik4*D z^M0Svuqp@czWea~2bLB&df=GP7*LUWj?m35hwi&O>Qg&50-tx^vG?qVYRVi^L8@ht zMg7WcD)-p?4nJ_q{N^1Db=S^vt(GMHpgpRV<2a7uxYi%X^`ypwMy**d50uO0B&jvy zIBC|C!6X?PY9;-(dbtwc6W8mNQXCEUy}w?)`@r3YkGwyLhL7BL6oejl@12Kkx$n^X z?mTpRG@^&MG0IW9VEki!!G8!-gfNH!-t|h{jE4kqelIjRnsdwD`wi;7wVt=-O|nV9v96ewN9+0*-5S) zh+LG`x-NE!iw~yzyXpRWyQ%9gBvHc`E?=WEb4k=n8jVj6ByWUSQre$O%IWF&VCU+E zr0lLvqlKjAuHGAOFGad@aci@?ny%V!q?uT4a2L5Zrj=ve_G*fpj=Jeow_W0LG47`2 zZd=Xhvf6D|!ezbNu7=BIx7`;m2fJa=P0d370Fn?a^>K*=>)7%ZYA#JY0@<+Y{k(tlORpm!sYGRJa`JwpWD9 z;ck06Tn=>GGvTt)ZO?|w{%(6^xa{k;SEW(gmG+Rasq0+&jj7gdyM{R6tz8%THnkI1 z+8b>Lj~;)mZs(HXeXZMB6YiDlapg4H9YwAJc}S}MuFog6G}=X`NEa=}uHWA#j;@5- zR+ChCrO}Y3%f{L$>g@3#oPmU7HJ!hASFfcZJvtkTBX$O z6Gs>cr@9?RzBY+`qv8O@)p3`EtcF{YJ*0<(W*2GRK%?qquAM!#EUIpBosd;`jqIVS zF2)`-gNM48xXZG~9z@XRHiWFEt7i{Y_at@qyLJv$Cx@!xn#F?q4Za>&uLaG(`Y38Q z+@O-C8&cACEhQZ{tmG0mqGXL5RdT7jOvz<#Ov&YLT*;i9P_oudD!IZQ*Xqo2x6SyH!dSLXoN! z*&gmHcDEzkmF;e)yLx@}_u}?0rN11v;q>*ejE60y8Xze4ra{Z)V0ZSz<4uG{Lb8eO-=Up2dKv%ebXx_N&!*maxy)lk=M z^jEE}+u*N;yKcR|8tJ-q{%W-AuJl)9U3Z1Q8t=Nb{%WG@=KR%U*In+frn>Gjf3>3P zF7;Q_UAM+x&2-%*{%W@CI{s>9*R}oCs;+DLtJPiC@K;XC-?-4>{PLH(z+ByZD|JT;( zudUNxTc^LaPO?+yw@&|!>EiKh=CtWxr;N!m|2RoYZH*_c`ljilw5*EoN^`I;uFNouXsK> zO<5=W5hn2b#`TJGQK+yl$pFRs-Z?o z$<`b|f7-P!iyHqVNvefuBZIGL*2oM*K-M&CY%zX6)hUs$@uX$OQv-bcnd;y@l{AT| zF^wtP;A(y-9U4-BilC`!FjeQTt+w(VwJ0;z>C<3pj)Y3SRHErsMa^>IO7vL;ZMy07 zK@T4g*$?3AwXUJEznAUSmnz#4UHgkGw>%S!LEuXkB% zR4Lmk`y^@9tY&Mv@pvO1EHdX17)md169WKl&Hg)4`si08+&1Nw_P8NAz>RLFmVU4c z*gU(Z)1Q7Lx+jf~rOocf*e0Gec$%5zH=;vJvKwSG=ZVr+e)sDeZ(uTS4IJw9w;At1 z)Jz(9hf%v8*oTe0ERPiPf+={crA7Io|C+g?{je56aY{(3IsD0B)q0 zyXauMKfN+tT>PTPcn8tDw^N%TRMAM2`?(=fVbDa~b|M5V{U-|5()c<6h{1$#S9Sdk zMj3qTKujC8dj}GjV(?(QlEOmkqfH&ike05UNlW*FXQDD?7hN+@auu5cRhktcq9*Q% z(^-oLG}Ox!m>ZG|t#d=Jv@2Sd#zG)@>$?!SWkm5!N4%*>ahwMNS8WQsueI(A%2f{#L z7#^Jo*42Q2Fi>iiZ5}M1g;nk+K0pF#?{8Q1K%5Nq=S)bY7hs-Oq8nh7AxCUy4nz%7 z*B(ddV(Ug&AZZVhU1iF|Ja~1xukd`atO6wpBov6-jr5EPMeV+Hs6AkU!(c}4PhW_S zsP!@>OO#9~xu}vcC9iG|2&}oT>pS8GDBryQURS3)0I1B>ZRl&y5#v6dSF`6n7bP2| zSKmuv)d_4);0nZLDDD%A>jA~hbD_BE+ZuHB9*U(?dVFGB-fJ^MWhO|_ZkZ4XjV44H z&CkUu&;325RuO&2dDP1nQ@yVxaN zZ(E7SD9B4-OfHD(P+|;AEi2YUWcgF;wpP35Trz9=^V)$vS5J>0ZPyt-{6Qp9YVDk5 z0jF6ry^ms3ufSuvF6f_nv(a$LHK<0Qv!(=MypC{We|r4QG@EEl1O!mjm39>)0>uDj zN}V!PXVGqw8{yE{)w@(pzks{N_zA2w2C8Vda9L?q3G2}hV`sF!$MuxI`d(VEw|Uy1 zz7pSygkTbda0p*fG`)!cYn-Z74K>QD;R#w6Xj$bKRGEfW-%Aj?toB^VTCE;C(k{JL zs}W8S5{M{TmCj46#Pkys@c*D@WlmO>z+pZ^7!Yf%Vca#AFuCTsFDH37qVepB@>(P5NC)%CFaylwYx_g7T|-Le!=F znmGAVZuKDvZ9-1Hg(iHclJsdtfhmJP@`ac>U7nc;6k(?{9IJOsnIBH^uL0hP)A!*S zrmHZR>5I$(MCrlR{ZW#Xl5_l5RbI8fk^UuRQB`#IrxC82E?#-1bb~}FeQqFKo1Pj> zPbKM@R{Eu+wRRwp75|T_V{TlGSmGB%6h1YYw$sJ2^ylLAtB45>(5N-^3VQ)%K=?|>y=lcd(+RnP`{3wU;T&ob<;Uz z|FchURlnh0{fAh{u2dUhHuUF__on!=eMg_#yU2gfMGqUtp_*V`^wVB<;)ynkLQk~& zggAI1&iKM35;cdjN<&h5=t;?5oR+Q|5c9?`RNuWRj(0gN-$2%%M(rBtEe}?ra-~|5 zS))*r{uMJW=yZ+gUh=BW@-@%0Z0TXEEYS4~4S*ZxAId$VquBM$&{$uZ9BVV_qF0!N zET&=Uru6GrU9tDQ_oqX0uIu||9A3X~ApzTPh#>hN86+`=1KCsFf6nsECc}VYG1Zg` zuQpl?+&D>p%B|VP$4hbTxM|&XKch8|tOQnUUh5ZIZ6aQhgcEKjF+y<8#(Xg&%M7pO8X z1FN!xAM|^rk<>0>G&Y$t>54rS#E~-A#F%(l5e)Lx%}5k%d@pJwrv! z7&Xm+@?2~|VqP%jR6fm~>xHJ0480B2$=W6=B^c#9N!OJ$FsrG7!BSQ44{2z6qQTWj ztOt=4^4IW_s`4F#VTM|j1cD|hEhB`hF`79>^DHa9&2EYtDF;V)IEvv8?7xLfu)mdB z{WzHm$xWnBlC#5d=E%98oJYyoWI0ph+)U0UYnE)9<(7sQ0M_#9z~`&bC(Er%nLXry zSRCivfKaIB`{Sy~6|it6sOXU^^}V0;8;l|h;cgy z#h?T29br-UM!SL0jx1>HAaSQ_JKlDh`gNiW%GOi^)&{9gys&HPi{}YVT{J_S!PJC2 zP{coTKW##dLO`soD#WLjHRJtPWB^d4=`{xxN0rq=pDPE204AAPBJ>p#dVtg&^FTZT zD#MZZBUZ65)PMn17Aw&cWvg@qJ1tSZ4!a1~AS~9T4M#W93K`?BL2_i?sUc5Uwp`aO zU6)corKR$|882Bx6k$A&A!4qB7=Z-?PXrbWH1I4)AvqUt8dqz$@{||%dCH3imQtRA zVuw3O|80*QUM9vUb|4WuJdTw2*ui3v=U`T!FLrpoPwbF>qoP=;kMm8XC+q1TcrHwV z8h_lE^cTXY&!N!j<{L@Wthu@poFyq3O?e2S0xjxGt{xc*tj-d#%o?^*DWM~Ly}fb- z7Rw67GU-=f))MDinpaSa!Se-SA)sw^zZxsYzNr{UUj9A@6gf*QbxIX~*f) z$1@Pv_fzHBX#!~SV|SowGM$&Dr9BFP;d{;{*LUz6=aRQv%N&pCTaZ=@*D84H_~YZL zA&iy4j4_mj6$v3wh0((uOj*e`*A(r$*XAKvZ!lSiIl-P@r!udg`y@@^RA2;g4zV=L zqae9FKh&q!9f&(Hq}A&ND!RfQV45ZNj?$OcSRkO^RaBL^XVZeoR4g6qcCu<1rMz0w zDAq(6_A*~U+Ht@I1zvpe)L!>t*Law{R_7Q-%R2lH597tWp2Ak!c5{5s`$PLm}>Ma2+DT2RxKditD9QrX2Ug1ij>xc=4} z$#yK+PQPXji{0FhZR9!{_P~cnxA>w6Db)ZgJd1a^T^kf!-N~i zbEMCa!xV`tDKba8Ca(+syj+*EIT0`I6fKDiDeNO>0~zKHhL>V7fyU|7(g`aZQnMul zTAf&KQ@N&R9O%hLxi_Ib&#Z*{c}U&4)2rmg)56IrHqQ=oAK3>ZAK|(c}hiYqyz!A7wYf!6iL7m6QVuyAm z8X?*#A4)5P{30l8VfUqhg#Xx;So$GJwwLBC-*ttlpI$~YqY}NT4yaO_Ns(sgF3}9n z&!{s;>d9sgntCAqNDKhEdIg%PlBZdc)65Dy-2Co>LL~EoK^YJzFC=l_ainlSIwbp- z$Cp@kk{cVPi{C2Uo7V0pLal9f=FQkTmO^~YJL2_Gj1uvIWpokzvR*D1K0NxMxle&i zr>QIqpa4JS$vf3@lR-X(Y1VveqN1)L-`|4zG^9y0au{vuh_BUdaaMG)Kb|oH~|H-A7D{@Fm0#Q$N=*qogW0>=Z;DDKJpOr@|ov zJ|e|(A`>@|#z)yMTTvC1to722G+Buhz~}M3D6kV#(pprkYcW?CXk8vP{$(>+Rd7Sj zAhYbwDzhi~a1du~X zV?=J4Y0pAtGHieIDi&qAoprHR;#a3^-Yt=^omazRgKvd|Ex%O~HUamMur0Vo!bahK z5OO(+dIoza z8Su%VPlkNb^2xAI46!-EgZ3R2#a9}hg>Di4og`Oje|Kj*8wR)4Zf7DJ1h@5WXR`3L z+3idfZU?)a6Aiy=O&IWmoiFc%ooBUOs_>^iY(Ka5r=@q^Dxby!fu{x zY&7qLYgQW9tV|%-T(U;-YugaI%4CP!m2Q=19@llN{08nKI##(b{xI$^-Z0Lk;|t?j z)f?BC>kZ=qz;`X!FhD8ZMn$ZGyYXeEXC=gNVXIkBEiw2U;eMrj~K# zwB<1R&dl=hcV;gP1E$IhNU5?>W6IG2QpA+pjs|YbSaIptzMa8LyB_SX33HSNRx~wh z0z;PEag!T3Jl)^zth7~6G0++Fo*U1^Nm4K|atpoBv=?VjJ`+U1LlP0z_`A#e-4#Ar zr({>O!6zHj7pGD`C&ZSpWxxzayf&KaBvJ%%Hm|Z9#{;Ja>@L6slWV5uN^p=+o|qEq ztSw>Upg^o?todGhBm9cK8)h00zdPA{JjuPolcj^5d6k$?@ohhskUo3GLUM`=E>CHv z)){32@Ci$KAETuE-OaUe2$L zPLw)ZG_ZLVrYz6j>CvJ+dMpMIGEc{u`?NF-HCv=75~dQufYjgodf>&F(dk1crWQQ# z57&1`k0h>@vT~$8so`3hit`!{Lt02Q#5o4sY00S{b|jH+q$D}>a%JPljp2OyGdwea zn@=Cj(UyhgMvdU2pST5D#GkfwA^uFb|K*TAZt1S*S3>$koUtY>X{_mC z>3{~kR+BL&av+AynUjw6=nTy$Q_>Mr8U_4aIfbne7iCz^P z6Ht{BUkEJkEUXu~PiaNT=VD&iEB^-NKAm7w{8N!ENW$yGC`1=J&H?&)A&%2;_PO*e5v)~iaAu4s6Qe<;#|XGur}zW!;0oK%H7dAB@3uxyW8xOtx9%9 z3qIM-c!aSz@rNkE%6<^f6U+H_uE-Q8R7*vA(kbms6B12^F>He!cI#bq7mI)2>^syR zJ8Mj>r`iGwD!SnoT1o@Ph46#I(Bs6bs-|(|J&njKFo}#D6GhWcTc~_K{S0Z1`(GyQ zCw-i>PWmgPLfjLiO*h7-DYZD!Zj~f*ic9k<+6e7U$tUufTDe3x&?Y2Ha&aBjlWYEy zm31w9em!k{)3=3AP}IXzzOra�Nt1ELwraSt$wP_1lv>XhJ*zI3+inJ@jm%cyF)O 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 Vh`g8tE^r*|JU?3RkP>^${{VD}fkprT delta 1747 zcmZ`(OKe+36rCAA$DiwGkCWK3oiv&JTIW-zO&co}pLPIMktl5z2qdZ!lK3?>B(`P0 z{yw9}V65fL%L{qKJfF`H z;k9$Q#Y}pc42JDsIh#qP&2%=ixVq3Jh5|ORw7U47F}*N7lO)5soiQ(FFWK?PQ}My+ zSu)yX^G0fVX6E3Lg$qVL-F5ad+3V3Mkpx`(x_DKK#s{GmlY-} zo$_bK_vp;0f&85eI(<%H#{`wdqWhFitVKu;%B_(6oXSR6K16YKz3WXzyVbqW1nsW6 z!!sHURR`TinX|0Pilz+jKi#*rB%2i;;gRuolWYzVi3>2RZ8~{WeFvw5b!UzfYJch7~v0!$lwN#=0 zV_oPQ5kwH_#(TsO?}Iwm-|z6@H5!4JV|tQt;gBrJe8PbX4P^qc=2NfnNg7q}^Y7J1 zffH<9S9b!#nE1_qyvN?fn!A|5%|bAVij#qH?VgU-|0}BdZPB(L`*a}qHtoI}wazbm z!pr**y+Y%?>h8!k^x&;(F^eSXlm0JgzZx8PoyOFKfkU|ddf+gPReu>UDF%NH9j;y* z%r}?6Vq$0b20lw8&v|>%&174wobP__2YJ>z42{sWTTbP}&BG$~F z!Z>8JWk-9@A>0$UvlRz)uBMlkvw36c?3y{XmQ5w{1tPZ`Dm^~+Qc;6oi_Ye(PsC=+ z8aPiU5{WYeCki4Jv;(v&I|&IRazw0)N4l-45BBBcrW1GxMb>%0aTDUP$+{Cn4yAsK ziijv6B}9(cws_!#5>+4WTUGOMO>M-7RvvY<-M&RP+=8XnT@Vqtv~E9-X!WFh`wbVw zTgR+np}oj95OKS0(1FmdS$Dza(=~-%`_|Zy+;z8W|M;YK$AKrAzHJ5bEbACMrlI@CwpS+I&khH#405ahit{CI?Q3cxfqf6P|!fO8;RhPdJX(H znTYsHe&}emx$IXrC-$DH`+?`s$ePI#qHY^*W47he({}Mg*lJhnT@}p5yjc*7rofH{ zKo?8cIPCS~R5_r=C*NR2Uj2A-hO$a$_16AZDJzCl$JBAQ6;daszGRJXb!Tdgin~#W WGZU diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index c1b257f3a313526e610ecdd3e0fb6fef413f1b6e..f8244dc3a212c0296dfacb270f11d42b948d1b73 100644 GIT binary patch delta 1626 zcmY*ZOKe+36rDGIwx2zAGI1O~f8u8BeCqt1zZ=v>&8SicqR=d=B2iGjuZ_X6Q~OnI zL9|xIj!GC!S}O6gM1;ZuNx!6)W!Ho(`Nb{YmvkeL zz-O70zYRFcHv(cx{TEJm!v74+SNwNietc-Ri5CJ4{B+=l?tPVE=Ai9HF;wHod`E?P zW0R?y;zDq`74rHSVu&m75;4GPKztrNW(h)B{_J>P8W3->^HNCs#>T+5MaHF2`D8?w zq=9lN`Wb*IMaRWEUEhNBZ1*P2e|4X92SBk3SEXPeVe8mYI)SMKX{bEX^Px1Dw-D>a zcs%|pf|n$tP@cEX7q{P|2)HLE7GNCmKLLT71P!MvM8#ZOawqbh{ zcvV37p&CpSu#pD(XRi0|%8s>>;sK-pInda%5`P{-`oSpywg8?3`8IQP-%4T>SmS&Q zum^As5W>*{pbfAg1daGy-#2{M-VplkNT_Bfo>X#aIg{0fa(Z@XEwd8O=AZ-$Axk%O zjV047+I4t?q9V@p_jPV7L}4*wB?n|xA+}zYxx^L_uPHkLKhB;p9gfq zrJ(r0PJ`zKM}^8Cl&j(--lJPUChh1RRVVQox$76n>5ExC#};*v&lBQiOILN{V24zJ z5L$wqHZ+V-1&pYvS_HbT+H#~?BE(iNPlbq227A;!*l3iWK^Oxx8UutxWuQA)bP z;N6YJr~p3Q7zNcVenmBkzp|qeN?iwsI1O!K?1k1+iGLVaBf|pV(;4=kh#7;Jm>E;> zH@f7~ntoK>lHb&;`VGBkK0t6hj^K}h&?;m$Mjj9w2K-TwS@>*b1IG7El==q59|lO5 b`DKZ}V-fG2AfXK2+BnwT!%~Zn#hM@NXbJUmnKk4DeXVU%cc)K5A*%k z@1Osl|6HEBJXL%bn;2u48+(XLbGf{P?tk(serL9=+Dc}v(d6u$wKzJTv=-*msNHMZ z=El;gadh0YmGMk^B4wpA>9Lv7Jx9cEI}$TvZzp?4dk5mE!>}#Z#mpsJ?|ec((L0E` zWQGJ-)MH>I5OqCOZw4C!b){vZJ7xID+EBqSIz*0%A`!(J@grd^2GKPten(-4?x19t zW0A|b&lpGv0TC8k0r4poWm7za;1aHVjo=3Py4i&rN*|a58a`UO?j9nJf+mWZ{LTA! z?Hw&n2DyiOL}WTnMgYO_hz@GE94sWe^>fvmjyUN7I|TLvJaEWsdQ5xlWTDcp`Y*V8 z#kJ>$Fy-HL$s4{H-F34NqGHL#xV+u)4cn%1a+-U^Cg6xzHss>bKd~XRjZee5-gpJh zXPT63H4VUdqv?mXLKP?6!nk*Ue1=a$FwEt9{p{R%; zaiYV0061t6G3@Wu?i)b#zd@TmJ80Vnqgt&xC>kIT2H0n4Pi^a|(SRxuMLOO-?f&(EF zkO4v+xWXNc&e)Rd=?lr`$cw|b9F*lDUR`zFjgZHV+jLMq2U$MQa)1zk@_-Dm!uG&H z^Kz}@>Le16ofVp!Km)N*ZplT197NUeSwJ<1O2;cM8acS?22^MVZy6BMZ2~7ir5LRD zYR7lMU3aC>_lJe@9y!-(9w~Y#O)OeTo=Q(7FTu)fc;x4uoh@Y#b@PbwWWkv8QfCLx zO!Bvo$a^UUD0uC0Zh6%>-z$5mFOj^EO7rKQ=gIU0k3bTono=Q!Qr5vQP9@VkJChnu zr7tL=0;MKTWqD@7Qq+meLV5x;yT}HmBo;&P3sSaYPX?h4K-dAKei`Z>R=uiEJfu`6 z`XY5YWgLuZVxLqU%(I}w{Y(>lXTit8HwUPm4mLtgMcZ&$eiW?>Eg6(C7eb1a10J&@ zmJK@c Date: Tue, 30 Jan 2018 19:28:57 +0100 Subject: [PATCH 02/21] more idiomatic std features --- substrate/Cargo.lock | 1 + substrate/native-runtime/Cargo.toml | 5 ++--- substrate/native-runtime/std/src/lib.rs | 2 +- substrate/primitives/Cargo.toml | 3 ++- substrate/runtime-codec/Cargo.toml | 4 ++-- substrate/runtime-codec/src/lib.rs | 6 +++--- substrate/wasm-runtime/polkadot/Cargo.toml | 7 +++---- substrate/wasm-runtime/polkadot/src/lib.rs | 4 ++-- .../polkadot/src/primitives/block.rs | 2 +- .../polkadot/src/primitives/digest.rs | 2 +- .../polkadot/src/primitives/function.rs | 2 +- .../polkadot/src/primitives/header.rs | 2 +- .../polkadot/src/primitives/proposal.rs | 4 ++-- .../polkadot/src/primitives/transaction.rs | 2 +- .../src/primitives/uncheckedtransaction.rs | 6 +++--- .../wasm-runtime/polkadot/src/support/mod.rs | 8 ++++---- .../release/runtime_polkadot.compact.wasm | Bin 65037 -> 65037 bytes .../release/runtime_polkadot.wasm | Bin 65086 -> 65086 bytes 18 files changed, 30 insertions(+), 30 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 3b715cee8d..e04172230f 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -748,6 +748,7 @@ dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fixed-hash 0.1.0 (git+https://github.com/paritytech/primitives.git)", + "polkadot-runtime-codec 0.1.0", "polkadot-serializer 0.1.0", "pretty_assertions 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/substrate/native-runtime/Cargo.toml b/substrate/native-runtime/Cargo.toml index 60dbbe19c6..6f446049f4 100644 --- a/substrate/native-runtime/Cargo.toml +++ b/substrate/native-runtime/Cargo.toml @@ -9,6 +9,5 @@ runtime-std = { path = "./std", version = "0.1" } rustc-hex = "1.0" [features] -default = ["with-std"] -with-std = [] -without-std = ["polkadot-runtime-codec/no-std"] +default = ["std"] +std = ["polkadot-runtime-codec/std"] diff --git a/substrate/native-runtime/std/src/lib.rs b/substrate/native-runtime/std/src/lib.rs index fb74093d18..7a46ce4615 100644 --- a/substrate/native-runtime/std/src/lib.rs +++ b/substrate/native-runtime/std/src/lib.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! The with-std support functions for the runtime. +//! The std support functions for the runtime. #[macro_use] extern crate environmental; diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index 77eccdea88..8b3782e545 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -15,6 +15,7 @@ untrusted = "0.5" twox-hash = "1.1.0" byteorder = "1.1" blake2-rfc = "0.2.18" +polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1" } [dev-dependencies] polkadot-serializer = { path = "../serializer", version = "0.1" } @@ -22,4 +23,4 @@ pretty_assertions = "0.4" [features] default = ["std"] -std = ["uint/std", "fixed-hash/std"] +std = ["uint/std", "fixed-hash/std", "polkadot-runtime-codec/std"] diff --git a/substrate/runtime-codec/Cargo.toml b/substrate/runtime-codec/Cargo.toml index 3221a55802..c85c9c0631 100644 --- a/substrate/runtime-codec/Cargo.toml +++ b/substrate/runtime-codec/Cargo.toml @@ -7,5 +7,5 @@ authors = ["Parity Technologies "] [dependencies] [features] -no-std = [] -default = [] +std = [] +default = ["std"] diff --git a/substrate/runtime-codec/src/lib.rs b/substrate/runtime-codec/src/lib.rs index 060df4e95c..f31fa3cf94 100644 --- a/substrate/runtime-codec/src/lib.rs +++ b/substrate/runtime-codec/src/lib.rs @@ -17,8 +17,8 @@ //! Implements the serialization and deserialization codec for polkadot runtime //! values. -#![cfg_attr(feature = "no-std", no_std)] -#![cfg_attr(feature = "no-std", feature(alloc))] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(alloc))] mod endiansensitive; mod slicable; @@ -32,7 +32,7 @@ pub use self::streamreader::StreamReader; pub use self::joiner::Joiner; pub use self::keyedvec::KeyedVec; -#[cfg(feature = "no-std")] +#[cfg(not(feature = "std"))] mod std { extern crate alloc; diff --git a/substrate/wasm-runtime/polkadot/Cargo.toml b/substrate/wasm-runtime/polkadot/Cargo.toml index 5cc45d4c01..053e704803 100644 --- a/substrate/wasm-runtime/polkadot/Cargo.toml +++ b/substrate/wasm-runtime/polkadot/Cargo.toml @@ -7,10 +7,9 @@ authors = ["Parity Technologies "] crate-type = ["cdylib"] [dependencies] -polkadot-runtime-codec = { path = "../../runtime-codec", version = "0.1" } +polkadot-runtime-codec = { path = "../../runtime-codec", version = "0.1", default-features = false} runtime-std = { path = "../std", version = "0.1" } [features] -default = ["without-std"] -with-std = [] -without-std = ["polkadot-runtime-codec/no-std"] +default = [] +std = ["polkadot-runtime-codec/std"] diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index ceec42af21..23e441e114 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -16,12 +16,12 @@ //! The Polkadot runtime. This can be compiled with #[no_std], ready for Wasm. -#![cfg_attr(feature = "without-std", no_std)] +#![cfg_attr(not(feature = "std"), no_std)] #[macro_use] extern crate runtime_std; -#[cfg(feature = "with-std")] +#[cfg(feature = "std")] extern crate rustc_hex; extern crate polkadot_runtime_codec as codec; diff --git a/substrate/wasm-runtime/polkadot/src/primitives/block.rs b/substrate/wasm-runtime/polkadot/src/primitives/block.rs index a884bcccec..3512133e53 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/block.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/block.rs @@ -21,7 +21,7 @@ use codec::{StreamReader, Joiner, Slicable, NonTrivialSlicable}; use primitives::{Header, UncheckedTransaction}; /// A Polkadot relay chain block. -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +#[cfg_attr(feature = "std", derive(PartialEq, Debug))] pub struct Block { /// The header of the block. pub header: Header, diff --git a/substrate/wasm-runtime/polkadot/src/primitives/digest.rs b/substrate/wasm-runtime/polkadot/src/primitives/digest.rs index 18107460b0..10f36aef4f 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/digest.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/digest.rs @@ -19,7 +19,7 @@ use runtime_std::prelude::*; #[derive(Clone, Default)] -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +#[cfg_attr(feature = "std", derive(PartialEq, Debug))] /// The digest of a block, useful for light-clients. pub struct Digest { /// All logs that have happened in the block. diff --git a/substrate/wasm-runtime/polkadot/src/primitives/function.rs b/substrate/wasm-runtime/polkadot/src/primitives/function.rs index e906cdc718..8aafbb5231 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/function.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/function.rs @@ -22,7 +22,7 @@ use runtime::{staking, session, timestamp, governance}; /// Public functions that can be dispatched to. #[derive(Clone, Copy)] -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +#[cfg_attr(feature = "std", derive(PartialEq, Debug))] #[repr(u8)] pub enum Function { StakingStake = 0, diff --git a/substrate/wasm-runtime/polkadot/src/primitives/header.rs b/substrate/wasm-runtime/polkadot/src/primitives/header.rs index 4c1ec328ea..7143ae7580 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/header.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/header.rs @@ -22,7 +22,7 @@ use runtime_std::mem; use primitives::{BlockNumber, Hash, Digest}; #[derive(Clone)] -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +#[cfg_attr(feature = "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). diff --git a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs index 8eb050cf67..a4c9b5f805 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs @@ -24,7 +24,7 @@ use runtime::{system, governance, staking, session}; /// Internal functions that can be dispatched to. #[derive(Clone, Copy)] -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +#[cfg_attr(feature = "std", derive(PartialEq, Debug))] #[repr(u8)] pub enum InternalFunction { SystemSetCode = 0, @@ -56,7 +56,7 @@ impl InternalFunction { } /// An internal function. -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +#[cfg_attr(feature = "std", derive(PartialEq, Debug))] pub struct Proposal { /// The priviledged function to call. pub function: InternalFunction, diff --git a/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs b/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs index 73ab9edd29..c31e63cfd9 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs @@ -22,7 +22,7 @@ use primitives::{AccountID, TxOrder, Function}; use runtime_std::mem; /// A vetted and verified transaction from the external world. -#[cfg_attr(feature = "with-std", derive(PartialEq, Debug))] +#[cfg_attr(feature = "std", derive(PartialEq, Debug))] pub struct Transaction { /// Who signed it (note this is not a signature). pub signed: AccountID, diff --git a/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs b/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs index 83984e08a4..1bbce40455 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs @@ -21,7 +21,7 @@ use runtime_std::prelude::*; use codec::{Slicable, NonTrivialSlicable, StreamReader, Joiner}; use primitives::Transaction; -#[cfg(feature = "with-std")] +#[cfg(feature = "std")] use std::fmt; /// A transactions right from the external world. Unchecked. @@ -40,14 +40,14 @@ impl UncheckedTransaction { } } -#[cfg(feature = "with-std")] +#[cfg(feature = "std")] impl PartialEq for UncheckedTransaction { fn eq(&self, other: &Self) -> bool { self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction } } -#[cfg(feature = "with-std")] +#[cfg(feature = "std")] impl fmt::Debug for UncheckedTransaction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "UncheckedTransaction({:?})", self.transaction) diff --git a/substrate/wasm-runtime/polkadot/src/support/mod.rs b/substrate/wasm-runtime/polkadot/src/support/mod.rs index 6bc60880a0..07c62c3a92 100644 --- a/substrate/wasm-runtime/polkadot/src/support/mod.rs +++ b/substrate/wasm-runtime/polkadot/src/support/mod.rs @@ -19,16 +19,16 @@ mod environment; pub mod storage; mod hashable; -#[cfg(feature = "with-std")] +#[cfg(feature = "std")] mod statichex; #[macro_use] -#[cfg(feature = "with-std")] +#[cfg(feature = "std")] mod testing; pub use self::environment::with_env; pub use self::storage::StorageVec; pub use self::hashable::Hashable; -#[cfg(feature = "with-std")] +#[cfg(feature = "std")] pub use self::statichex::{StaticHexConversion, StaticHexInto}; -#[cfg(feature = "with-std")] +#[cfg(feature = "std")] pub use self::testing::{AsBytesRef, HexDisplay, TestExternalities, one, two}; 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 898f194e802daf2caf927eb0e35beb50b42fd7ec..f6d352781bc22b76a0073e2d4b09f391003d6812 100644 GIT binary patch delta 2582 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 Qhj@FghzzV^#kVZ~12NSTO8@`> From 2c39e247d61b51ecf76ace81e2c859ad2616601b Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 30 Jan 2018 19:35:09 +0100 Subject: [PATCH 03/21] clean up workspaces a little --- substrate/Cargo.toml | 8 ++++---- substrate/cli/Cargo.toml | 2 +- substrate/client/Cargo.toml | 2 +- substrate/executor/Cargo.toml | 2 +- substrate/native-runtime/std/Cargo.toml | 2 +- substrate/{rpc_servers => rpc-servers}/Cargo.toml | 0 substrate/{rpc_servers => rpc-servers}/src/lib.rs | 0 substrate/rpc/Cargo.toml | 2 +- substrate/runtime-std/Cargo.toml | 6 ++++++ substrate/runtime-std/src/lib.rs | 7 +++++++ substrate/{state_machine => state-machine}/Cargo.toml | 0 substrate/{state_machine => state-machine}/src/backend.rs | 0 substrate/{state_machine => state-machine}/src/ext.rs | 0 substrate/{state_machine => state-machine}/src/lib.rs | 0 14 files changed, 22 insertions(+), 9 deletions(-) rename substrate/{rpc_servers => rpc-servers}/Cargo.toml (100%) rename substrate/{rpc_servers => rpc-servers}/src/lib.rs (100%) create mode 100644 substrate/runtime-std/Cargo.toml create mode 100644 substrate/runtime-std/src/lib.rs rename substrate/{state_machine => state-machine}/Cargo.toml (100%) rename substrate/{state_machine => state-machine}/src/backend.rs (100%) rename substrate/{state_machine => state-machine}/src/ext.rs (100%) rename substrate/{state_machine => state-machine}/src/lib.rs (100%) diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index f01f860386..6215e20ce8 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -14,13 +14,13 @@ members = [ "collator", "environmental", "executor", - "primitives", - "rpc", - "rpc_servers", "native-runtime", + "primitives", + "rpc-servers", + "rpc", "runtime-codec", "serializer", - "state_machine", + "state-machine", "validator", ] exclude = [ diff --git a/substrate/cli/Cargo.toml b/substrate/cli/Cargo.toml index 64305642bf..6d857023f7 100644 --- a/substrate/cli/Cargo.toml +++ b/substrate/cli/Cargo.toml @@ -12,4 +12,4 @@ log = "0.3" polkadot-client = { path = "../client", version = "0.1" } polkadot-executor = { path = "../executor", version = "0.1" } polkadot-primitives = { path = "../primitives", version = "0.1" } -polkadot-rpc-servers = { path = "../rpc_servers", version = "0.1" } +polkadot-rpc-servers = { path = "../rpc-servers", version = "0.1" } diff --git a/substrate/client/Cargo.toml b/substrate/client/Cargo.toml index 2142732b5d..399e2ca823 100644 --- a/substrate/client/Cargo.toml +++ b/substrate/client/Cargo.toml @@ -6,4 +6,4 @@ authors = ["Parity Technologies "] [dependencies] error-chain = "0.11" polkadot-primitives = { path = "../primitives", version = "0.1" } -polkadot-state-machine = { path = "../state_machine", version = "0.1" } +polkadot-state-machine = { path = "../state-machine", version = "0.1" } diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index f27f7e2b26..22fe96bdee 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -8,7 +8,7 @@ error-chain = "0.11" polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1" } polkadot-primitives = { path = "../primitives", version = "0.1" } polkadot-serializer = { path = "../serializer", version = "0.1" } -polkadot-state-machine = { path = "../state_machine" , version = "0.1" } +polkadot-state-machine = { path = "../state-machine" , version = "0.1" } serde = "1.0" serde_derive = "1.0" parity-wasm = "0.15.0" diff --git a/substrate/native-runtime/std/Cargo.toml b/substrate/native-runtime/std/Cargo.toml index 0976e4b378..d0d91352dd 100644 --- a/substrate/native-runtime/std/Cargo.toml +++ b/substrate/native-runtime/std/Cargo.toml @@ -9,6 +9,6 @@ strict = [] [dependencies] lazy_static = "1.0.0" parking_lot = "0.5" -polkadot-state-machine = { path = "../../state_machine" , version = "0.1" } +polkadot-state-machine = { path = "../../state-machine" , version = "0.1" } environmental = { path = "../../environmental", version = "0.1.0" } polkadot-primitives = { path = "../../primitives", version = "0.1.0" } diff --git a/substrate/rpc_servers/Cargo.toml b/substrate/rpc-servers/Cargo.toml similarity index 100% rename from substrate/rpc_servers/Cargo.toml rename to substrate/rpc-servers/Cargo.toml diff --git a/substrate/rpc_servers/src/lib.rs b/substrate/rpc-servers/src/lib.rs similarity index 100% rename from substrate/rpc_servers/src/lib.rs rename to substrate/rpc-servers/src/lib.rs diff --git a/substrate/rpc/Cargo.toml b/substrate/rpc/Cargo.toml index 66d11d94dd..8095f88fff 100644 --- a/substrate/rpc/Cargo.toml +++ b/substrate/rpc/Cargo.toml @@ -9,7 +9,7 @@ jsonrpc-core = { git="https://github.com/paritytech/jsonrpc.git" } jsonrpc-macros = { git="https://github.com/paritytech/jsonrpc.git" } polkadot-client = { path = "../client", version = "0.1" } polkadot-primitives = { path = "../primitives", version = "0.1" } -polkadot-state-machine = { path = "../state_machine", version = "0.1" } +polkadot-state-machine = { path = "../state-machine", version = "0.1" } [dev-dependencies] assert_matches = "1.1" diff --git a/substrate/runtime-std/Cargo.toml b/substrate/runtime-std/Cargo.toml new file mode 100644 index 0000000000..5507e12579 --- /dev/null +++ b/substrate/runtime-std/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "runtime-std" +version = "0.1.0" +authors = ["Robert Habermeier "] + +[dependencies] diff --git a/substrate/runtime-std/src/lib.rs b/substrate/runtime-std/src/lib.rs new file mode 100644 index 0000000000..31e1bb209f --- /dev/null +++ b/substrate/runtime-std/src/lib.rs @@ -0,0 +1,7 @@ +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} diff --git a/substrate/state_machine/Cargo.toml b/substrate/state-machine/Cargo.toml similarity index 100% rename from substrate/state_machine/Cargo.toml rename to substrate/state-machine/Cargo.toml diff --git a/substrate/state_machine/src/backend.rs b/substrate/state-machine/src/backend.rs similarity index 100% rename from substrate/state_machine/src/backend.rs rename to substrate/state-machine/src/backend.rs diff --git a/substrate/state_machine/src/ext.rs b/substrate/state-machine/src/ext.rs similarity index 100% rename from substrate/state_machine/src/ext.rs rename to substrate/state-machine/src/ext.rs diff --git a/substrate/state_machine/src/lib.rs b/substrate/state-machine/src/lib.rs similarity index 100% rename from substrate/state_machine/src/lib.rs rename to substrate/state-machine/src/lib.rs From 4b2bd5ec72755234dfc2ad1d6159c7508f54e04c Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 30 Jan 2018 23:47:29 +0100 Subject: [PATCH 04/21] fully refactor runtime-std to use conditional compilation --- substrate/Cargo.lock | 55 +- substrate/Cargo.toml | 1 + substrate/executor/Cargo.toml | 3 +- substrate/executor/src/lib.rs | 3 +- substrate/native-runtime/Cargo.toml | 4 +- substrate/native-runtime/std/Cargo.toml | 14 - substrate/runtime-std/Cargo.toml | 19 +- substrate/runtime-std/build.rs | 14 + substrate/runtime-std/src/lib.rs | 44 +- .../src/lib.rs => runtime-std/with_std.rs} | 12 +- .../src/lib.rs => runtime-std/without_std.rs} | 27 +- substrate/wasm-runtime/Cargo.lock | 790 +++++++++++++++++- substrate/wasm-runtime/polkadot/Cargo.toml | 6 +- substrate/wasm-runtime/polkadot/src/lib.rs | 2 +- substrate/wasm-runtime/pwasm-alloc/Cargo.toml | 5 + substrate/wasm-runtime/pwasm-alloc/build.rs | 14 + substrate/wasm-runtime/pwasm-alloc/src/lib.rs | 42 +- substrate/wasm-runtime/std/Cargo.toml | 11 - .../release/runtime_polkadot.compact.wasm | Bin 65037 -> 65037 bytes .../release/runtime_polkadot.wasm | Bin 65086 -> 65086 bytes substrate/wasm-runtime/test/Cargo.toml | 2 +- substrate/wasm-runtime/test/src/lib.rs | 2 +- 22 files changed, 946 insertions(+), 124 deletions(-) delete mode 100644 substrate/native-runtime/std/Cargo.toml create mode 100644 substrate/runtime-std/build.rs rename substrate/{native-runtime/std/src/lib.rs => runtime-std/with_std.rs} (95%) rename substrate/{wasm-runtime/std/src/lib.rs => runtime-std/without_std.rs} (90%) create mode 100644 substrate/wasm-runtime/pwasm-alloc/build.rs delete mode 100644 substrate/wasm-runtime/std/Cargo.toml diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index e04172230f..fc0129dbdb 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -470,11 +470,6 @@ name = "lazy_static" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "lazy_static" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "lazycell" version = "0.5.1" @@ -554,7 +549,7 @@ name = "native-runtime" version = "0.1.0" dependencies = [ "polkadot-runtime-codec 0.1.0", - "runtime-std 0.1.0", + "polkadot-runtime-std 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -620,15 +615,6 @@ dependencies = [ "parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot_core" version = "0.2.6" @@ -732,9 +718,9 @@ dependencies = [ "parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-primitives 0.1.0", "polkadot-runtime-codec 0.1.0", + "polkadot-runtime-std 0.1.0", "polkadot-serializer 0.1.0", "polkadot-state-machine 0.1.0", - "runtime-std 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -787,6 +773,18 @@ dependencies = [ name = "polkadot-runtime-codec" version = "0.1.0" +[[package]] +name = "polkadot-runtime-std" +version = "0.1.0" +dependencies = [ + "environmental 0.1.0", + "polkadot-primitives 0.1.0", + "polkadot-state-machine 0.1.0", + "pwasm-alloc 0.1.0", + "pwasm-libc 0.1.0", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "polkadot-serializer" version = "0.1.0" @@ -826,6 +824,18 @@ dependencies = [ "difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pwasm-alloc" +version = "0.1.0" +dependencies = [ + "pwasm-libc 0.1.0", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pwasm-libc" +version = "0.1.0" + [[package]] name = "quote" version = "0.3.15" @@ -922,17 +932,6 @@ dependencies = [ "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "runtime-std" -version = "0.1.0" -dependencies = [ - "environmental 0.1.0", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "polkadot-primitives 0.1.0", - "polkadot-state-machine 0.1.0", -] - [[package]] name = "rustc-demangle" version = "0.1.5" @@ -1336,7 +1335,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5" -"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" "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" @@ -1353,7 +1351,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum parity-wasm 0.15.4 (registry+https://github.com/rust-lang/crates.io-index)" = "235801e9531998c4bb307f4ea6833c9f40a4cf132895219ac8c2cd25a9b310f7" "checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" -"checksum parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3e7f7c9857874e54afeb950eebeae662b1e51a2493666d2ea4c0a5d91dcf0412" "checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595" "checksum patricia-trie 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e2f638d79aba5c4a71a4f373df6e3cd702250a53b7f0ed4da1e2a7be9737ae" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" diff --git a/substrate/Cargo.toml b/substrate/Cargo.toml index 6215e20ce8..55573fddec 100644 --- a/substrate/Cargo.toml +++ b/substrate/Cargo.toml @@ -19,6 +19,7 @@ members = [ "rpc-servers", "rpc", "runtime-codec", + "runtime-std", "serializer", "state-machine", "validator", diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index 22fe96bdee..19bab5c0d5 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -6,6 +6,7 @@ authors = ["Parity Technologies "] [dependencies] error-chain = "0.11" polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1" } +polkadot-runtime-std = { path = "../runtime-std", version = "0.1" } polkadot-primitives = { path = "../primitives", version = "0.1" } polkadot-serializer = { path = "../serializer", version = "0.1" } polkadot-state-machine = { path = "../state-machine" , version = "0.1" } @@ -15,7 +16,7 @@ parity-wasm = "0.15.0" byteorder = "1.1" rustc-hex = "1.0.0" native-runtime = { path = "../native-runtime", version = "0.1" } -runtime-std = { path = "../native-runtime/std", version = "0.1" } + libc = { version = "0.2.33" } [dev-dependencies] diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index 10684b1531..21dc94efbe 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -28,15 +28,16 @@ #![warn(missing_docs)] extern crate polkadot_runtime_codec as codec; +extern crate polkadot_runtime_std as runtime_std; extern crate polkadot_primitives as primitives; extern crate polkadot_serializer as serializer; extern crate polkadot_state_machine as state_machine; + extern crate serde; extern crate parity_wasm; extern crate byteorder; extern crate rustc_hex; extern crate native_runtime; -extern crate runtime_std; extern crate libc; #[macro_use] diff --git a/substrate/native-runtime/Cargo.toml b/substrate/native-runtime/Cargo.toml index 6f446049f4..12ff2a1e10 100644 --- a/substrate/native-runtime/Cargo.toml +++ b/substrate/native-runtime/Cargo.toml @@ -5,9 +5,9 @@ authors = ["Parity Technologies "] [dependencies] polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1" } -runtime-std = { path = "./std", version = "0.1" } +polkadot-runtime-std = { path = "../runtime-std", version = "0.1" } rustc-hex = "1.0" [features] default = ["std"] -std = ["polkadot-runtime-codec/std"] +std = ["polkadot-runtime-codec/std", "polkadot-runtime-std/std"] diff --git a/substrate/native-runtime/std/Cargo.toml b/substrate/native-runtime/std/Cargo.toml deleted file mode 100644 index d0d91352dd..0000000000 --- a/substrate/native-runtime/std/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "runtime-std" -version = "0.1.0" -authors = ["Parity Technologies "] - -[features] -strict = [] - -[dependencies] -lazy_static = "1.0.0" -parking_lot = "0.5" -polkadot-state-machine = { path = "../../state-machine" , version = "0.1" } -environmental = { path = "../../environmental", version = "0.1.0" } -polkadot-primitives = { path = "../../primitives", version = "0.1.0" } diff --git a/substrate/runtime-std/Cargo.toml b/substrate/runtime-std/Cargo.toml index 5507e12579..56721a6352 100644 --- a/substrate/runtime-std/Cargo.toml +++ b/substrate/runtime-std/Cargo.toml @@ -1,6 +1,21 @@ [package] -name = "runtime-std" +name = "polkadot-runtime-std" version = "0.1.0" -authors = ["Robert Habermeier "] +authors = ["Parity Technologies "] +build = "build.rs" + +[build-dependencies] +rustc_version = "0.2" [dependencies] +pwasm-alloc = { path = "../wasm-runtime/pwasm-alloc", version = "0.1" } +pwasm-libc = { path = "../wasm-runtime/pwasm-libc", version = "0.1" } +environmental = { path = "../environmental", version = "0.1", optional = true } +polkadot-state-machine = { path = "../state-machine", version = "0.1", optional = true } +polkadot-primitives = { path = "../primitives", version = "0.1", optional = true } + +[features] +default = ["std"] +std = ["environmental", "polkadot-state-machine", "polkadot-primitives"] +nightly = [] +strict = [] diff --git a/substrate/runtime-std/build.rs b/substrate/runtime-std/build.rs new file mode 100644 index 0000000000..35eb154f3a --- /dev/null +++ b/substrate/runtime-std/build.rs @@ -0,0 +1,14 @@ +//! Set a nightly feature + +extern crate rustc_version; +use rustc_version::{version, version_meta, Channel}; + +fn main() { + // Assert we haven't travelled back in time + assert!(version().unwrap().major >= 1); + + // Set cfg flags depending on release channel + if let Channel::Nightly = version_meta().unwrap().channel { + println!("cargo:rustc-cfg=feature=\"nightly\""); + } +} diff --git a/substrate/runtime-std/src/lib.rs b/substrate/runtime-std/src/lib.rs index 31e1bb209f..ab3bbe9580 100644 --- a/substrate/runtime-std/src/lib.rs +++ b/substrate/runtime-std/src/lib.rs @@ -1,7 +1,39 @@ -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(lang_items))] +#![cfg_attr(not(feature = "std"), feature(core_intrinsics))] +#![cfg_attr(not(feature = "std"), feature(alloc))] + +#![cfg_attr(feature = "std", doc = "Polkadot runtime standard library as compiled when linked with Rust's standard library.")] +#![cfg_attr(not(feature = "std"), doc = "Polkadot's runtime standard library as compiled without Rust's standard library.")] + +#[cfg(feature = "std")] +include!("../with_std.rs"); + +#[cfg(not(feature = "std"))] +include!("../without_std.rs"); + + + +/// Prelude of common useful imports. +/// +/// This should include only things which are in the normal std prelude. +pub mod prelude { + pub use ::vec::Vec; + pub use ::boxed::Box; } diff --git a/substrate/native-runtime/std/src/lib.rs b/substrate/runtime-std/with_std.rs similarity index 95% rename from substrate/native-runtime/std/src/lib.rs rename to substrate/runtime-std/with_std.rs index 7a46ce4615..a23f8e13d7 100644 --- a/substrate/native-runtime/std/src/lib.rs +++ b/substrate/runtime-std/with_std.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -//! The std support functions for the runtime. #[macro_use] extern crate environmental; + extern crate polkadot_state_machine; extern crate polkadot_primitives as primitives; @@ -31,14 +31,6 @@ pub use std::boxed; pub use std::slice; pub use std::mem; -/// Prelude of common useful imports. -/// -/// This should include only things which are in the normal std prelude. -pub mod prelude { - pub use std::vec::Vec; - pub use std::boxed::Box; -} - pub use polkadot_state_machine::{Externalities, ExternalitiesError}; use primitives::hexdisplay::HexDisplay; @@ -106,6 +98,7 @@ pub fn with_externalities R>(ext: &mut Externalities, f: F) -> ext::using(ext, f) } +/// Trait for things which can be printed. pub trait Printable { fn print(self); } @@ -128,6 +121,7 @@ impl Printable for u64 { } } +/// Print a printable value. pub fn print(value: T) { value.print(); } diff --git a/substrate/wasm-runtime/std/src/lib.rs b/substrate/runtime-std/without_std.rs similarity index 90% rename from substrate/wasm-runtime/std/src/lib.rs rename to substrate/runtime-std/without_std.rs index 9b7d385e69..8d1e589faa 100644 --- a/substrate/wasm-runtime/std/src/lib.rs +++ b/substrate/runtime-std/without_std.rs @@ -1,11 +1,11 @@ -#![no_std] -#![feature(lang_items)] -#![feature(core_intrinsics)] -#![feature(alloc)] -#![cfg_attr(feature = "strict", deny(warnings))] - +#[cfg(feature = "nightly")] extern crate alloc; +#[cfg(feature = "nightly")] +extern crate pwasm_libc; +#[cfg(feature = "nightly")] +extern crate pwasm_alloc; + pub use alloc::vec; pub use alloc::boxed; pub use alloc::rc; @@ -13,17 +13,8 @@ pub use core::mem; pub use core::slice; pub use core::cell; -/// Common re-exports that are useful to have in scope. -pub mod prelude { - pub use alloc::vec::Vec; - pub use alloc::boxed::Box; -} - use alloc::vec::Vec; -extern crate pwasm_libc; -extern crate pwasm_alloc; - #[lang = "panic_fmt"] #[no_mangle] pub extern fn panic_fmt(_fmt: ::core::fmt::Arguments, _file: &'static str, _line: u32, _col: u32) { @@ -49,6 +40,7 @@ extern "C" { fn ext_ed25519_verify(msg_data: *const u8, msg_len: u32, sig_data: *const u8, pubkey_data: *const u8) -> u32; } +/// Get `key` from storage and return a `Vec`, empty if there's a problem. pub fn storage(key: &[u8]) -> Vec { let mut length: u32 = 0; unsafe { @@ -57,6 +49,7 @@ pub fn storage(key: &[u8]) -> Vec { } } +/// Set the storage to some particular key. pub fn set_storage(key: &[u8], value: &[u8]) { unsafe { ext_set_storage( @@ -66,6 +59,8 @@ pub fn set_storage(key: &[u8], value: &[u8]) { } } +/// Get `key` from storage, placing the value into `value_out` (as much as possible) and return +/// the number of bytes that the key in storage was. pub fn read_storage(key: &[u8], value_out: &mut [u8], value_offset: usize) -> usize { unsafe { ext_get_storage_into(key.as_ptr(), key.len() as u32, value_out.as_mut_ptr(), value_out.len() as u32, value_offset as u32) as usize @@ -116,6 +111,7 @@ pub fn ed25519_verify(sig: &[u8], msg: &[u8], pubkey: &[u8]) -> bool { } == 0 } +/// Trait for things which can be printed. pub trait Printable { fn print(self); } @@ -142,6 +138,7 @@ impl Printable for u64 { } } +/// Print a printable value. pub fn print(value: T) { value.print(); } diff --git a/substrate/wasm-runtime/Cargo.lock b/substrate/wasm-runtime/Cargo.lock index 93bc305136..3fd66a2355 100644 --- a/substrate/wasm-runtime/Cargo.lock +++ b/substrate/wasm-runtime/Cargo.lock @@ -1,38 +1,808 @@ +[[package]] +name = "aho-corasick" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayvec" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arrayvec" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bigint" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byteorder" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cc" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "coco" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crunchy" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "either" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "elastic-array" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "env_logger" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "environmental" +version = "0.1.0" + +[[package]] +name = "ethcore-bigint" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethcore-bytes" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ethcore-logger" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "isatty 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fixed-hash" +version = "0.1.2" +source = "git+https://github.com/paritytech/primitives.git#30f15bb3387faf40f519dd56a5768cb3d3fe3638" +dependencies = [ + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "gcc" +version = "0.3.54" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hashdb" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heapsize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "isatty" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "keccak-hash" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lazy_static" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memorydb" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hashdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nodrop" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "odds" +version = "0.2.26" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "owning_ref" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "patricia-trie" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-logger 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "plain_hasher" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "polkadot-primitives" +version = "0.1.0" +dependencies = [ + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.1.2 (git+https://github.com/paritytech/primitives.git)", + "polkadot-runtime-codec 0.1.0", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.1.0 (git+https://github.com/paritytech/primitives.git)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "polkadot-runtime-codec" version = "0.1.0" +[[package]] +name = "polkadot-runtime-std" +version = "0.1.0" +dependencies = [ + "environmental 0.1.0", + "polkadot-primitives 0.1.0", + "polkadot-state-machine 0.1.0", + "pwasm-alloc 0.1.0", + "pwasm-libc 0.1.0", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "polkadot-state-machine" +version = "0.1.0" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hashdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "patricia-trie 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "polkadot-primitives 0.1.0", + "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pwasm-alloc" version = "0.1.0" dependencies = [ "pwasm-libc 0.1.0", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "pwasm-libc" version = "0.1.0" +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ring" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rlp" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "runtime-polkadot" version = "0.1.0" dependencies = [ "polkadot-runtime-codec 0.1.0", - "runtime-std 0.1.0", -] - -[[package]] -name = "runtime-std" -version = "0.1.0" -dependencies = [ - "pwasm-alloc 0.1.0", - "pwasm-libc 0.1.0", + "polkadot-runtime-std 0.1.0", ] [[package]] name = "runtime-test" version = "0.1.0" dependencies = [ - "runtime-std 0.1.0", + "polkadot-runtime-std 0.1.0", ] +[[package]] +name = "rustc-hex" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive_internals" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "stable_deref_trait" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tiny-keccak" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "triehash" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "twox-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "uint" +version = "0.1.0" +source = "git+https://github.com/paritytech/primitives.git#30f15bb3387faf40f519dd56a5768cb3d3fe3638" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "untrusted" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "utf8-ranges" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" +"checksum arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "06f59fe10306bb78facd90d28c2038ad23ffaaefa85bac43c8a434cde383334f" +"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" +"checksum bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5442186ef6560f30f1ee4b9c1e4c87a35a6879d3644550cc248ec2b955eb5fcd" +"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" +"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" +"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd" +"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" +"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" +"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3" +"checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85" +"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" +"checksum ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb5af77e74a8f70e9c3337e069c37bc82178ef1b459c02091f73c4ad5281eb5" +"checksum ethcore-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3977c772cd6c5c22e1c7cfa208e4c3b746bd6c3a6c8eeec0999a6b2103015ad5" +"checksum ethcore-logger 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fd5813e49546030be7d134e775088d56b8ff4ab60617b90e93d4f0513da4c5b" +"checksum fixed-hash 0.1.2 (git+https://github.com/paritytech/primitives.git)" = "" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" +"checksum hashdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d97be07c358c5b461268b4ce60304024c5fa5acfd4bd8cd743639f0252003cf5" +"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +"checksum isatty 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f2a233726c7bb76995cec749d59582e5664823b7245d4970354408f1d79a7a2" +"checksum keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f300c1f149cd9ca5214eed24f6e713a597517420fb8b15499824aa916259ec1" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" +"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "013b7e4c5e10c764936ebc6bd3662d8e3c92292d267bf6a42ef3f5cad9c793ee" +"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" +"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22" +"checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" +"checksum parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" +"checksum parking_lot_core 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "9f35048d735bb93dd115a0030498785971aab3234d311fbe273d020084d26bd8" +"checksum patricia-trie 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e2f638d79aba5c4a71a4f373df6e3cd702250a53b7f0ed4da1e2a7be9737ae" +"checksum plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83ae80873992f511142c07d0ec6c44de5636628fdb7e204abd655932ea79d995" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" +"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" +"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53" +"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" +"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" +"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" +"checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9" +"checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" +"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" +"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0" +"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5" +"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9" +"checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" +"checksum tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9241752647ca572f12c9b520a5d360d9099360c527770647e694001646a1d0" +"checksum triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9291c7f0fae44858b5e087dd462afb382354120003778f1695b44aab98c7abd7" +"checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435" +"checksum uint 0.1.0 (git+https://github.com/paritytech/primitives.git)" = "" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" +"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/substrate/wasm-runtime/polkadot/Cargo.toml b/substrate/wasm-runtime/polkadot/Cargo.toml index 053e704803..24715e8c99 100644 --- a/substrate/wasm-runtime/polkadot/Cargo.toml +++ b/substrate/wasm-runtime/polkadot/Cargo.toml @@ -7,9 +7,9 @@ authors = ["Parity Technologies "] crate-type = ["cdylib"] [dependencies] -polkadot-runtime-codec = { path = "../../runtime-codec", version = "0.1", default-features = false} -runtime-std = { path = "../std", version = "0.1" } +polkadot-runtime-codec = { path = "../../runtime-codec", version = "0.1", default-features = false } +polkadot-runtime-std = { path = "../../runtime-std", version = "0.1", default-features = false } [features] default = [] -std = ["polkadot-runtime-codec/std"] +std = ["polkadot-runtime-codec/std", "polkadot-runtime-std/std"] diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 23e441e114..f2414c738d 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -19,7 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #[macro_use] -extern crate runtime_std; +extern crate polkadot_runtime_std as runtime_std; #[cfg(feature = "std")] extern crate rustc_hex; diff --git a/substrate/wasm-runtime/pwasm-alloc/Cargo.toml b/substrate/wasm-runtime/pwasm-alloc/Cargo.toml index e0a28f2c0d..d5dbe87e6a 100644 --- a/substrate/wasm-runtime/pwasm-alloc/Cargo.toml +++ b/substrate/wasm-runtime/pwasm-alloc/Cargo.toml @@ -10,9 +10,14 @@ documentation = "https://paritytech.github.io/pwasm-std/pwasm_std/" description = "Parity WebAssembly standard library internal allocator" keywords = ["wasm", "parity", "webassembly", "blockchain"] categories = ["no-std", "embedded"] +build = "build.rs" [dependencies] pwasm-libc = { path = "../pwasm-libc", version = "0.1" } +[build-dependencies] +rustc_version = "0.2" + [features] strict = [] +nightly = [] diff --git a/substrate/wasm-runtime/pwasm-alloc/build.rs b/substrate/wasm-runtime/pwasm-alloc/build.rs new file mode 100644 index 0000000000..35eb154f3a --- /dev/null +++ b/substrate/wasm-runtime/pwasm-alloc/build.rs @@ -0,0 +1,14 @@ +//! Set a nightly feature + +extern crate rustc_version; +use rustc_version::{version, version_meta, Channel}; + +fn main() { + // Assert we haven't travelled back in time + assert!(version().unwrap().major >= 1); + + // Set cfg flags depending on release channel + if let Channel::Nightly = version_meta().unwrap().channel { + println!("cargo:rustc-cfg=feature=\"nightly\""); + } +} diff --git a/substrate/wasm-runtime/pwasm-alloc/src/lib.rs b/substrate/wasm-runtime/pwasm-alloc/src/lib.rs index 8bd7368205..b1afd5af00 100644 --- a/substrate/wasm-runtime/pwasm-alloc/src/lib.rs +++ b/substrate/wasm-runtime/pwasm-alloc/src/lib.rs @@ -2,29 +2,35 @@ #![cfg_attr(feature = "strict", deny(warnings))] #![no_std] #![crate_type = "rlib"] -#![feature(global_allocator)] -#![feature(alloc)] -#![feature(allocator_api)] +#![cfg_attr(feature = "nightly", feature(global_allocator))] +#![cfg_attr(feature = "nightly", feature(alloc))] +#![cfg_attr(feature = "nightly", feature(allocator_api))] //! Custom allocator crate for wasm -extern crate alloc; -extern crate pwasm_libc; - -use alloc::heap::{Alloc, Layout, AllocErr}; - /// Wasm allocator pub struct WasmAllocator; -unsafe impl<'a> Alloc for &'a WasmAllocator { - unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { - Ok(pwasm_libc::malloc(layout.size())) - } - - unsafe fn dealloc(&mut self, ptr: *mut u8, _layout: Layout) { - pwasm_libc::free(ptr) - } -} - +#[cfg(feature = "nightly")] #[global_allocator] static ALLOCATOR: WasmAllocator = WasmAllocator; + +#[cfg(feature = "nightly")] +mod __impl { + extern crate alloc; + extern crate pwasm_libc; + + use self::alloc::heap::{Alloc, Layout, AllocErr}; + + use super::WasmAllocator; + + unsafe impl<'a> Alloc for &'a WasmAllocator { + unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { + Ok(pwasm_libc::malloc(layout.size())) + } + + unsafe fn dealloc(&mut self, ptr: *mut u8, _layout: Layout) { + pwasm_libc::free(ptr) + } + } +} diff --git a/substrate/wasm-runtime/std/Cargo.toml b/substrate/wasm-runtime/std/Cargo.toml deleted file mode 100644 index 802d1fabde..0000000000 --- a/substrate/wasm-runtime/std/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "runtime-std" -version = "0.1.0" -authors = ["Parity Technologies "] - -[dependencies] -pwasm-libc = { path = "../pwasm-libc", version = "0.1" } -pwasm-alloc = { path = "../pwasm-alloc", version = "0.1" } - -[features] -strict = [] 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 f6d352781bc22b76a0073e2d4b09f391003d6812..7fdbe868b7afdaf19448b4e778494f17155ab640 100644 GIT binary patch delta 1751 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 Sdp(SF^&uCGkUDxdpZyo{^(Ei{ 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 0d4c03e72a41eec1bba4822366df1cc863cbe9b3..726801e8a22f212586df06d6ef0c7c8ca782e940 100644 GIT binary patch delta 1779 zcmZvc4Qx|Y6vywq?LOcQ_6D0R$lAKL1INcc*b0;(djukpD1;bgGoh63iG^;jzIGc^ zU^5aUAA`yX5(#P{lZXs0c`7OhWo#tqG8bL6iA1NFvV@V91O!J3o?8k+bV={;o_o(d z@1FlTcc&A&(+OQlquLnVk*q(N_&~CdwOSPeV|41yy%_!0icom3lH4N?3xH z!%ST-ovkHwm6TnyYtA%RTFTUZ6ne+8s2L7V+R8Cw@-BpSYVzZZ^U{>R)7ek~{BGUG zQD+-PXkPn;vD_>#xygF0FspPfM{!vmY%XnNT~@e`D~RH{)1o_<}mto)4}k_Ho>N;%$!5!cJo-Uz|k*sXt$| zA=;B5MEC@Xf>-o|R?!AV=^%~6SCXA4`I}^5u>u&Cide*|6)u`KhL&l|m$hcl60L9L zAxbN>z_UF%HfYtPRYrSJ6S zY!5?Vn5L$g4SBp{z}$EswGwUAr#9h2)31E*qm4iCvbHoYL1^cj-(uXX-t;uy5I)>= z1d9ztTPzUR{28x%(Uz0Rx?g&&f})3JdOe!Px@_9Oo7t2X{OY!uY-=G{wr}A*6W%_A z(6;Z`Pf;8+bHUjbV1R47NQKH{a1IxN#IqD0phh)<3q z4}JuDC=|}c+j~LwzdU?@gG~v5J;MsAB}j)??Tm+O=bwlHbF-HbmaN zH#KNg{Mu0c`A-~WCr+}29Y#)c-i1q>@MT*%pC3H)6c^{pnSDvg-{=fto#+ z?MdqQbshw}ytEX4>8j%LTDtSHqvqs8irqyV7I#m>_J#WHTNqW_a9$~H$?>@TZjU$E zY*89z^+li3MDXDW#?W{|atI+&J^Rmk)x^-gy~&`Gd+1>>4* zLT2Jt2$_WpBWcpN-6V)rXqnJz#-A>^8Z`+f_;~aYP!eP50IdG2tRiF$RzZy72KPCRS4m4cM6E&&>f}*WxmcA04ZdJfr2(tJoE9Pt zS_LDSK*)4-E60C-{W!E;o7k@}M1~ zqf@{y6KObQ$f}!2*HVU0_7Ev?FBaAet5+x(E!ZeLofXK3(+L*}(>-numrp)4 delta 1741 zcmZWp4Qx|Y6u$Si`++yMH`vmF^vCt}f&6VP+ko<89|0v2LqZI0GhuYy6U)k8eeE`; z{27fAWKg*Qk_DuYi6A2xxl^W8D5E0*mPvHcB@(Shg@h3x;YY^^o?FU~vB|sNIp>~x z&bi+?x2Hx7r$!8&yYQ&o?7Tdq(MSmW6u)b7jZ@dDzQ(Xx6V|;AA+Im&*Ba1FT1rOn zY&zZ0k7uzF!#qr4GIM9tWTaL0qtHKwBrWvN_zyTto3I^##U{K!I9{3fPbNv&>F@R} z9M($10LDkBkzsjlxZ>62+i*#Jpc zXioVG(k-*P@-qg~XJM1(G~>J-7#lYc5Ai5yGKre$$oxtUD;6xw=$4gsGu^kKmjKkg zILND9;Hl=&=6Q!CB--ZQJ^Hpql#qasu!rtnKJ@XP(Cm`InM4l7g0Hi^j#Cy&AvY}wMyS-6Z{T7D4Y zQWkox&j1B5rLqVE$<#C3L@+~3>nf>e&dCZ}@kBtE9{NH1-OHz<12(|*{CSIceXVvxX2GS+%)c(Xy`j<8b z9BsjQgmgIQO1;dQuvd_{5!?+GBnAjlXXcs;aub8pVW!9RQZZo`<^S+-OMjko3}aym z4dJwy-B`#cg<6~TrY-R%V|tUGZ~m3^O>?Tg{s)!QdvPN2AFxtPs4Dp9%#=ZIfqa7WxgI%U>IaSonE_wK*J z3uuit5RMNHPUJ{iqbBP5>;X4951C1N&?3=0G#1HcRY&~zIj3!^O;qrjV)5lM=-DJN zijimm9KS{{9~Ge)*N@ILJ(;c4h&`DtI;*1++8^n-0qf>tFdgjnvGu8ZP-|o7zQ>}8 zd3f2h>Z_kPxK5lTmt}h6M9(9rVPn5;&E)cd)30!HuAknMqWr_2FhsuJ)6e<8cy?!s zzi$g^IN`_T^p}K((`)N3%!@r5{((m@L>Ki==I^JW_dY~r_2;w_ujmcvs<*DiR;%f{ z)~wbcC2AIoi2vXn3fVrb!R>7fyAceOP=xXjnhsl~fH{C3K%DYTm<2JJi;xAh7WfP) zYtl?Vzgvtq(+hW9^_>Dat+3m+3Mp}mfB_N~A#1hPtPv~Cy=$_zTmSEr z15V>pPBH4dXT}3`8LUHW?Y+0LxhM$nrowI%kcVCdcPmVJ-z=s}ua!8Xb|F9Duk~rV zTA~H{U+xS&gp@A3AeN2gjz9?@Bmw#oc3}yvxw_J}(FPkl=y9MXBjpg4o<`Hv zP-7sRiWZjy;+rnhUb%rOkWzdS9Z!mb|~z1*Lnj$f43|c0%`+NVrg@;pPLgh iL"] crate-type = ["cdylib"] [dependencies] -runtime-std = { path = "../std", version = "0.1" } +polkadot-runtime-std = { path = "../../runtime-std", version = "0.1", default_features = false } diff --git a/substrate/wasm-runtime/test/src/lib.rs b/substrate/wasm-runtime/test/src/lib.rs index c63ca73fca..b0b7f0a4bb 100644 --- a/substrate/wasm-runtime/test/src/lib.rs +++ b/substrate/wasm-runtime/test/src/lib.rs @@ -7,7 +7,7 @@ extern crate alloc; use alloc::vec::Vec; #[macro_use] -extern crate runtime_std; +extern crate polkadot_runtime_std as runtime_std; use runtime_std::{set_storage, storage, print, blake2_256, twox_128, twox_256, ed25519_verify}; fn test_blake2_256(input: &[u8]) -> Vec { From 0035369f82c51b4d464f99bf0447dfa7359523a6 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 31 Jan 2018 22:27:07 +0100 Subject: [PATCH 05/21] allow polkadot-primitives to compile on nightly --- substrate/Cargo.lock | 26 ++++++++++++++++---------- substrate/primitives/Cargo.toml | 10 +++++----- substrate/primitives/src/bytes.rs | 20 +++++++++++++++++--- substrate/primitives/src/contract.rs | 2 +- substrate/primitives/src/ed25519.rs | 13 +++++++------ substrate/primitives/src/hexdisplay.rs | 4 ++-- substrate/primitives/src/lib.rs | 9 ++++++++- substrate/primitives/src/parachain.rs | 2 +- substrate/primitives/src/validator.rs | 2 +- 9 files changed, 58 insertions(+), 30 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index dbaf8cd6fe..662004ef70 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -400,7 +400,7 @@ dependencies = [ [[package]] name = "fixed-hash" version = "0.1.2" -source = "git+https://github.com/paritytech/primitives.git#30f15bb3387faf40f519dd56a5768cb3d3fe3638" +source = "git+https://github.com/rphmeier/primitives.git?branch=uint-asm-with-feature#18e2f90688b0d90b5f79761865e394595ce55079" dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1054,16 +1054,16 @@ dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.1.2 (git+https://github.com/paritytech/primitives.git)", + "fixed-hash 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=uint-asm-with-feature)", "polkadot-runtime-codec 0.1.0", "polkadot-serializer 0.1.0", "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.1.0 (git+https://github.com/paritytech/primitives.git)", + "uint 0.1.1 (git+https://github.com/rphmeier/primitives.git?branch=uint-asm-with-feature)", "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1312,6 +1312,11 @@ name = "rustc-hex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-hex" +version = "2.0.0" +source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc891d6dc2cc9009d7" + [[package]] name = "rustc-serialize" version = "0.3.24" @@ -1612,20 +1617,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uint" version = "0.1.0" -source = "git+https://github.com/paritytech/primitives.git#30f15bb3387faf40f519dd56a5768cb3d3fe3638" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "uint" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.1.1" +source = "git+https://github.com/rphmeier/primitives.git?branch=uint-asm-with-feature#18e2f90688b0d90b5f79761865e394595ce55079" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1815,7 +1820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ethcrypto 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum ethereum-types 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2adaa5b8ceafcce0bc3a68ef116ca5702958cc97d70a6eb008aeddb569b092b3" "checksum ethkey 0.3.0 (git+https://github.com/paritytech/parity.git)" = "" -"checksum fixed-hash 0.1.2 (git+https://github.com/paritytech/primitives.git)" = "" +"checksum fixed-hash 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=uint-asm-with-feature)" = "" "checksum fixed-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4b54d107faeb66084eca7c506aa50b6b7cb9eb9a1f1f633ae2ca3af55620c191" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" @@ -1894,6 +1899,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" +"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" @@ -1933,8 +1939,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9291c7f0fae44858b5e087dd462afb382354120003778f1695b44aab98c7abd7" "checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -"checksum uint 0.1.0 (git+https://github.com/paritytech/primitives.git)" = "" "checksum uint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91ed1e25ded4e37e0967b1f12d5f910b32f979768d4f48e2f6ca7b6e7130b44e" +"checksum uint 0.1.1 (git+https://github.com/rphmeier/primitives.git?branch=uint-asm-with-feature)" = "" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index 8b3782e545..9421c8f624 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -5,11 +5,11 @@ authors = ["Parity Technologies "] [dependencies] crunchy = "0.1" -fixed-hash = { git = "https://github.com/paritytech/primitives.git" } -rustc-hex = "1.0" -serde = "1.0" +fixed-hash = { git = "https://github.com/rphmeier/primitives.git", branch = "uint-asm-with-feature" } +rustc-hex = { git = "https://github.com/rphmeier/rustc-hex.git", version = "2.0", default_features = false } +serde = { version = "1.0", default_features = false } serde_derive = "1.0" -uint = { git = "https://github.com/paritytech/primitives.git" } +uint = { git = "https://github.com/rphmeier/primitives.git", branch = "uint-asm-with-feature" } ring = "0.12" untrusted = "0.5" twox-hash = "1.1.0" @@ -23,4 +23,4 @@ pretty_assertions = "0.4" [features] default = ["std"] -std = ["uint/std", "fixed-hash/std", "polkadot-runtime-codec/std"] +std = ["uint/std", "fixed-hash/std", "polkadot-runtime-codec/std", "serde/std", "rustc-hex/std"] diff --git a/substrate/primitives/src/bytes.rs b/substrate/primitives/src/bytes.rs index ab69d36e70..c4c9cfaba7 100644 --- a/substrate/primitives/src/bytes.rs +++ b/substrate/primitives/src/bytes.rs @@ -14,15 +14,29 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -use std::fmt; +use core::fmt; use serde::{de, Serializer, Deserializer}; +#[cfg(not(feature = "std"))] +mod alloc_types { + pub use ::alloc::string::String; + pub use ::alloc::vec::Vec; +} + +#[cfg(feature = "std")] +mod alloc_types { + pub use ::std::vec::Vec; + pub use ::std::string::String; +} + +pub use self::alloc_types::*; + /// Serializes a slice of bytes. pub fn serialize(bytes: &[u8], serializer: S) -> Result where S: Serializer, { - let hex = ::rustc_hex::ToHex::to_hex(bytes); + let hex: String = ::rustc_hex::ToHex::to_hex(bytes); serializer.serialize_str(&format!("0x{}", hex)) } @@ -38,7 +52,7 @@ pub fn serialize_uint(bytes: &[u8], serializer: S) -> Result return serializer.serialize_str("0x0"); } - let hex = ::rustc_hex::ToHex::to_hex(bytes); + let hex: String = ::rustc_hex::ToHex::to_hex(bytes); let has_leading_zero = !hex.is_empty() && &hex[0..1] == "0"; serializer.serialize_str( &format!("0x{}", if has_leading_zero { &hex[1..] } else { &hex }) diff --git a/substrate/primitives/src/contract.rs b/substrate/primitives/src/contract.rs index 02411b73d7..40e4f560be 100644 --- a/substrate/primitives/src/contract.rs +++ b/substrate/primitives/src/contract.rs @@ -16,7 +16,7 @@ //! Contract execution data. -use bytes; +use bytes::{self, Vec}; /// Contract call data. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs index b28e0bde6e..85f683e93a 100644 --- a/substrate/primitives/src/ed25519.rs +++ b/substrate/primitives/src/ed25519.rs @@ -16,6 +16,7 @@ //! Simple Ed25519 API. +use bytes::Vec; use untrusted; use ring::{rand, signature}; use rustc_hex::FromHex; @@ -108,14 +109,14 @@ impl Pair { } /// Make a new key pair from the raw secret. pub fn from_secret(secret: &[u8; 32]) -> Pair { - let mut pkcs8_bytes = FromHex::from_hex("302e020100300506032b657004220420").unwrap(); + let mut pkcs8_bytes: Vec = FromHex::from_hex("302e020100300506032b657004220420").unwrap(); pkcs8_bytes.extend_from_slice(&secret[..]); Pair(signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).unwrap()) } /// Make a new key pair from the raw secret and public key (it will check to make sure /// they correspond to each other). pub fn from_both(secret_public: &[u8; 64]) -> Option { - let mut pkcs8_bytes = FromHex::from_hex("3053020101300506032b657004220420").unwrap(); + let mut pkcs8_bytes: Vec = FromHex::from_hex("3053020101300506032b657004220420").unwrap(); pkcs8_bytes.extend_from_slice(&secret_public[0..32]); pkcs8_bytes.extend_from_slice(&[0xa1u8, 0x23, 0x03, 0x21, 0x00]); pkcs8_bytes.extend_from_slice(&secret_public[32..64]); @@ -151,13 +152,13 @@ impl Signature { impl From<&'static str> for Public { fn from(hex: &'static str) -> Self { let mut r = [0u8; 32]; - r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..32]); + r.copy_from_slice(&FromHex::from_hex::>(hex).unwrap()[0..32]); Public(r) } } impl From<&'static str> for Pair { fn from(hex: &'static str) -> Self { - let data = FromHex::from_hex(hex).expect("Key pair given is static so hex should be good."); + let data = FromHex::from_hex::>(hex).expect("Key pair given is static so hex should be good."); match data.len() { 32 => { let mut r = [0u8; 32]; @@ -178,7 +179,7 @@ impl From<&'static str> for Pair { impl From<&'static str> for Signature { fn from(hex: &'static str) -> Self { let mut r = [0u8; 64]; - r.copy_from_slice(&FromHex::from_hex(hex).unwrap()[0..64]); + r.copy_from_slice(&FromHex::from_hex::>(hex).unwrap()[0..64]); Signature(r) } } @@ -228,7 +229,7 @@ mod test { let pair = Pair::from_seed(b"12345678901234567890123456789012"); let public = pair.public(); assert_eq!(public, "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".into()); - let message = FromHex::from_hex("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000").unwrap(); + let message: Vec = FromHex::from_hex("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000").unwrap(); let signature = pair.sign(&message[..]); assert!(signature.verify(&message[..], &public)); } diff --git a/substrate/primitives/src/hexdisplay.rs b/substrate/primitives/src/hexdisplay.rs index fa62d69869..2e8bd3d15b 100644 --- a/substrate/primitives/src/hexdisplay.rs +++ b/substrate/primitives/src/hexdisplay.rs @@ -24,7 +24,7 @@ impl<'a> HexDisplay<'a> { pub fn from(d: &'a AsBytesRef) -> Self { HexDisplay(d.as_bytes_ref()) } } -impl<'a> ::std::fmt::Display for HexDisplay<'a> { +impl<'a> ::core::fmt::Display for HexDisplay<'a> { fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { for byte in self.0 { try!( fmtr.write_fmt(format_args!("{:02x}", byte))); @@ -47,7 +47,7 @@ impl AsBytesRef for [u8] { fn as_bytes_ref(&self) -> &[u8] { &self } } -impl AsBytesRef for Vec { +impl AsBytesRef for ::bytes::Vec { fn as_bytes_ref(&self) -> &[u8] { &self } } diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index c774ec7f42..c69554b8a7 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -18,6 +18,9 @@ #![warn(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(alloc))] + extern crate rustc_hex; extern crate serde; extern crate ring; @@ -35,7 +38,7 @@ extern crate serde_derive; #[macro_use] extern crate uint as uint_crate; -#[cfg(feature="std")] +#[cfg(feature = "std")] extern crate core; #[cfg(test)] extern crate polkadot_serializer; @@ -43,6 +46,10 @@ extern crate polkadot_serializer; #[macro_use] extern crate pretty_assertions; +#[cfg(not(feature = "std"))] +#[macro_use] +extern crate alloc; + mod bytes; pub mod block; pub mod contract; diff --git a/substrate/primitives/src/parachain.rs b/substrate/primitives/src/parachain.rs index cecbbb1dbb..d2f6e765e5 100644 --- a/substrate/primitives/src/parachain.rs +++ b/substrate/primitives/src/parachain.rs @@ -16,7 +16,7 @@ //! Parachain data types. -use bytes; +use bytes::{self, Vec}; /// Unique identifier of a parachain. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize)] diff --git a/substrate/primitives/src/validator.rs b/substrate/primitives/src/validator.rs index b6de301cb4..6e8a7dc6e8 100644 --- a/substrate/primitives/src/validator.rs +++ b/substrate/primitives/src/validator.rs @@ -16,7 +16,7 @@ //! Validator primitives. -use bytes; +use bytes::{self, Vec}; use parachain; /// Parachain outgoing message. From a3b9c2af7d7d7c5eda566c7110637b3f4a6b23b3 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 31 Jan 2018 22:28:11 +0100 Subject: [PATCH 06/21] fix compiler warning --- substrate/state-machine/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substrate/state-machine/src/lib.rs b/substrate/state-machine/src/lib.rs index e497a20474..f0c1d17b8b 100644 --- a/substrate/state-machine/src/lib.rs +++ b/substrate/state-machine/src/lib.rs @@ -19,7 +19,8 @@ #![warn(missing_docs)] extern crate polkadot_primitives as primitives; -#[macro_use] + +#[cfg_attr(test, macro_use)] extern crate hex_literal; extern crate hashdb; From 188332cc4b86b337be8b752881a392324ed67bba Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Thu, 1 Feb 2018 11:13:55 +0100 Subject: [PATCH 07/21] extract out all primitives --- substrate/primitives/src/block.rs | 25 +++++- substrate/primitives/src/hashing.rs | 8 +- substrate/primitives/src/hexdisplay.rs | 2 +- substrate/primitives/src/lib.rs | 41 +++++++-- substrate/primitives/src/parachain.rs | 4 +- substrate/primitives/src/proposal.rs | 89 +++++++++++++++++++ substrate/primitives/src/runtime_function.rs | 54 +++++++++++ substrate/primitives/src/transaction.rs | 61 +++++++++++++ substrate/primitives/src/validator.rs | 20 ----- substrate/runtime-std/Cargo.toml | 4 +- substrate/runtime-std/src/lib.rs | 48 +++++++++- substrate/runtime-std/with_std.rs | 14 +-- substrate/runtime-std/without_std.rs | 2 + .../polkadot/src/primitives/digest.rs | 2 +- .../polkadot/src/primitives/proposal.rs | 32 ------- .../polkadot/src/runtime/governance.rs | 30 +++++++ .../polkadot/src/runtime/system.rs | 37 +++++++- 17 files changed, 386 insertions(+), 87 deletions(-) create mode 100644 substrate/primitives/src/proposal.rs create mode 100644 substrate/primitives/src/runtime_function.rs create mode 100644 substrate/primitives/src/transaction.rs diff --git a/substrate/primitives/src/block.rs b/substrate/primitives/src/block.rs index eb2c7785c2..26639d7d2e 100644 --- a/substrate/primitives/src/block.rs +++ b/substrate/primitives/src/block.rs @@ -16,9 +16,10 @@ //! Block and header type definitions. -use bytes; +use bytes::{self, Vec}; use hash::H256; use parachain; +use transaction::UncheckedTransaction; /// Used to refer to a block number. pub type Number = u64; @@ -33,6 +34,22 @@ pub type TransactionHash = H256; #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct Log(#[serde(with="bytes")] pub Vec); +/// A Polkadot relay chain block. +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +pub struct Block { + /// The block header. + pub header: Header, + /// All relay-chain transactions. + pub transactions: Vec, +} + +/// The digest of a block, useful for light-clients. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct Digest { + /// All logs that have happened in the block. + pub logs: Vec, +} + /// A relay chain block header. /// /// https://github.com/w3f/polkadot-spec/blob/master/spec.md#header @@ -46,10 +63,12 @@ pub struct Header { pub number: Number, /// State root after this transition. pub state_root: H256, + /// The root of the trie that represents this block's transactions, indexed by a 32-byte integer. + pub transaction_root: H256, /// Parachain activity bitfield pub parachain_activity: parachain::Activity, - /// Logs (generated by execution) - pub logs: Vec, + /// The digest of activity on the block. + pub digest: Digest, } /// A relay chain block body. diff --git a/substrate/primitives/src/hashing.rs b/substrate/primitives/src/hashing.rs index e1a4f84a99..8534cf4d98 100644 --- a/substrate/primitives/src/hashing.rs +++ b/substrate/primitives/src/hashing.rs @@ -57,7 +57,7 @@ pub fn blake2_128(data: &[u8]) -> [u8; 16] { /// Do a XX 128-bit hash and place result in `dest`. pub fn twox_128_into(data: &[u8], dest: &mut [u8; 16]) { - use ::std::hash::Hasher; + use ::core::hash::Hasher; let mut h0 = twox_hash::XxHash::with_seed(0); let mut h1 = twox_hash::XxHash::with_seed(1); h0.write(data); @@ -71,14 +71,14 @@ pub fn twox_128_into(data: &[u8], dest: &mut [u8; 16]) { /// Do a XX 128-bit hash and return result. pub fn twox_128(data: &[u8]) -> [u8; 16] { - let mut r: [u8; 16] = unsafe { ::std::mem::uninitialized() }; + let mut r: [u8; 16] = [0; 16]; twox_128_into(data, &mut r); r } /// Do a XX 256-bit hash and place result in `dest`. pub fn twox_256_into(data: &[u8], dest: &mut [u8; 32]) { - use ::std::hash::Hasher; + use ::core::hash::Hasher; use byteorder::{ByteOrder, LittleEndian}; let mut h0 = twox_hash::XxHash::with_seed(0); let mut h1 = twox_hash::XxHash::with_seed(1); @@ -100,7 +100,7 @@ pub fn twox_256_into(data: &[u8], dest: &mut [u8; 32]) { /// Do a XX 256-bit hash and return result. pub fn twox_256(data: &[u8]) -> [u8; 32] { - let mut r: [u8; 32] = unsafe { ::std::mem::uninitialized() }; + let mut r: [u8; 32] = [0; 32]; twox_256_into(data, &mut r); r } diff --git a/substrate/primitives/src/hexdisplay.rs b/substrate/primitives/src/hexdisplay.rs index 2e8bd3d15b..42db221287 100644 --- a/substrate/primitives/src/hexdisplay.rs +++ b/substrate/primitives/src/hexdisplay.rs @@ -25,7 +25,7 @@ impl<'a> HexDisplay<'a> { } impl<'a> ::core::fmt::Display for HexDisplay<'a> { - fn fmt(&self, fmtr: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + fn fmt(&self, fmtr: &mut ::core::fmt::Formatter) -> Result<(), ::core::fmt::Error> { for byte in self.0 { try!( fmtr.write_fmt(format_args!("{:02x}", byte))); } diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index c69554b8a7..00ceee2d54 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -53,23 +53,48 @@ extern crate alloc; mod bytes; pub mod block; pub mod contract; +pub mod ed25519; pub mod hash; +pub mod hashing; +pub mod hexdisplay; pub mod parachain; +pub mod proposal; +pub mod runtime_function; +pub mod transaction; pub mod uint; pub mod validator; -pub mod ed25519; -pub mod hexdisplay; -pub mod hashing; - -/// Alias to 160-bit hash when used in the context of an account address. -pub type Address = hash::H160; -/// Alias to 520-bit hash when used in the context of a signature. -pub type Signature = hash::H512; pub use self::hash::{H160, H256}; pub use self::uint::{U256, U512}; pub use hashing::{blake2_256, twox_128, twox_256}; +/// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody +/// (who matters). Essentially this means that a majority of validators have decided it is +/// "correct". +pub const EVERYBODY: AccountId = [255u8; 32]; + +/// Alias to Ed25519 pubkey that identifies an account. +pub type AccountId = [u8; 32]; + +/// The Ed25519 pub key of an session that belongs to an authority. This is used as what the +/// external environment/consensus algorithm calls an "authority". +pub type SessionKey = AccountId; + +/// Indentifier for a chain. +pub type ChainID = u64; + +/// Index of a block in the chain. +pub type BlockNumber = u64; + +/// Index of a transaction. +pub type TxOrder = u64; + +/// A hash of some data. +pub type Hash = [u8; 32]; + +/// Alias to 520-bit hash when used in the context of a signature. +pub type Signature = hash::H512; + /// A hash function. pub fn hash(data: &[u8]) -> hash::H256 { blake2_256(data).into() diff --git a/substrate/primitives/src/parachain.rs b/substrate/primitives/src/parachain.rs index d2f6e765e5..360b7bacdd 100644 --- a/substrate/primitives/src/parachain.rs +++ b/substrate/primitives/src/parachain.rs @@ -57,11 +57,11 @@ pub struct CandidateReceipt { /// The ID of the parachain this is a candidate for. pub parachain_index: Id, /// The collator's account ID - pub collator: ::Address, + pub collator: ::AccountId, /// The head-data pub head_data: HeadData, /// Balance uploads to the relay chain. - pub balance_uploads: Vec<(::Address, ::uint::U256)>, + pub balance_uploads: Vec<(::AccountId, ::uint::U256)>, /// Egress queue roots. pub egress_queue_roots: Vec<(Id, ::hash::H256)>, /// Fees paid from the chain to the relay chain validators diff --git a/substrate/primitives/src/proposal.rs b/substrate/primitives/src/proposal.rs new file mode 100644 index 0000000000..f8f39c815b --- /dev/null +++ b/substrate/primitives/src/proposal.rs @@ -0,0 +1,89 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Proposals for relay-chain governance. +//! +//! This describes a combination of a function ID and data that can be used to call into +//! an internal function. + +use bytes; + +/// Internal functions that can be dispatched to. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[repr(u8)] +pub enum InternalFunction { + /// Set the system's code. + SystemSetCode = 0, + /// Set the number of sessions per era. + StakingSetSessionsPerEra = 1, + /// Set the minimum bonding duration for staking. + StakingSetBondingDuration = 2, + /// Set the validator count for staking. + StakingSetValidatorCount = 3, + /// Set the per-mille of validator approval required for governance changes. + GovernanceSetApprovalPpmRequired = 4, + /// Set the session length. + SessionSetLength = 5, +} + +impl InternalFunction { + /// Derive `Some` value from a `u8`, or `None` if it's invalid. + pub fn from_u8(value: u8) -> Option { + use self::*; + let functions = [ + InternalFunction::SystemSetCode, + InternalFunction::StakingSetSessionsPerEra, + InternalFunction::StakingSetBondingDuration, + InternalFunction::StakingSetValidatorCount, + InternalFunction::GovernanceSetApprovalPpmRequired, + InternalFunction::SessionSetLength + ]; + if (value as usize) < functions.len() { + Some(functions[value as usize]) + } else { + None + } + } +} + +/// An internal function. +#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct Proposal { + /// The privileged function to call. + pub function: InternalFunction, + /// The serialised data to call it with. + #[serde(with = "bytes")] + pub input_data: Vec, +} + +#[cfg(test)] +mod test { + use super::*; + use support::StaticHexInto; + + #[test] + fn slicing_should_work() { + let p = Proposal { + function: InternalFunction::SystemSetCode, + input_data: b"Hello world".to_vec(), + }; + let v = p.to_vec(); + assert_eq!(v, "000b00000048656c6c6f20776f726c64".convert::>()); + + let o = Proposal::from_slice(&v).unwrap(); + assert_eq!(p, o); + } +} diff --git a/substrate/primitives/src/runtime_function.rs b/substrate/primitives/src/runtime_function.rs new file mode 100644 index 0000000000..0104447f02 --- /dev/null +++ b/substrate/primitives/src/runtime_function.rs @@ -0,0 +1,54 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Polkadot runtime functions. +//! This describes a function that can be called from an external transaction. + +/// Public functions that can be dispatched to. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[repr(u8)] +pub enum Function { + /// Staking subsystem: begin staking. + StakingStake = 0, + /// Staking subsystem: stop staking. + StakingUnstake = 1, + /// Staking subsystem: transfer stake. + StakingTransfer = 2, + /// Set temporary session key as a validator. + SessionSetKey = 3, + /// Set the timestamp. + TimestampSet = 4, + /// Make a proposal for the governance system. + GovernancePropose = 5, + /// Approve a proposal for the governance system. + GovernanceApprove = 6, +} + +impl Function { + /// Derive `Some` value from a `u8`, or `None` if it's invalid. + pub fn from_u8(value: u8) -> Option { + match value { + 0 => Some(Function::StakingStake), + 1 => Some(Function::StakingUnstake), + 2 => Some(Function::StakingTransfer), + 3 => Some(Function::SessionSetKey), + 4 => Some(Function::TimestampSet), + 5 => Some(Function::GovernancePropose), + 6 => Some(Function::GovernanceApprove), + _ => None, + } + } +} diff --git a/substrate/primitives/src/transaction.rs b/substrate/primitives/src/transaction.rs new file mode 100644 index 0000000000..eb3e823c58 --- /dev/null +++ b/substrate/primitives/src/transaction.rs @@ -0,0 +1,61 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Transaction type. + +use bytes::{self, Vec}; +use runtime_function::Function; + +#[cfg(feature = "std")] +use std::fmt; + +#[cfg(not(feature = "std"))] +use alloc::fmt; + +/// A vetted and verified transaction from the external world. +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +pub struct Transaction { + /// Who signed it (note this is not a signature). + pub signed: ::AccountId, + /// The number of transactions have come before from the same signer. + pub nonce: ::TxOrder, + /// The function that should be called. + pub function: Function, + /// Serialised input data to the function. + #[serde(with = "bytes")] + pub input_data: Vec, +} + +/// A transactions right from the external world. Unchecked. +#[derive(Eq, Clone, Serialize, Deserialize)] +pub struct UncheckedTransaction { + /// The actual transaction information. + pub transaction: Transaction, + /// The signature; should be an Ed25519 signature applied to the serialised `transaction` field. + pub signature: ::Signature, +} + +impl PartialEq for UncheckedTransaction { + fn eq(&self, other: &Self) -> bool { + self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction + } +} + +impl fmt::Debug for UncheckedTransaction { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "UncheckedTransaction({:?})", self.transaction) + } +} diff --git a/substrate/primitives/src/validator.rs b/substrate/primitives/src/validator.rs index 6e8a7dc6e8..4f7d60b721 100644 --- a/substrate/primitives/src/validator.rs +++ b/substrate/primitives/src/validator.rs @@ -44,26 +44,6 @@ pub struct ValidationResult { pub balance_uploads: Vec, } -// TODO [ToDr] This shouldn't be here! -/// Validator logic. -pub trait Validator { - /// Validation error. - type Error: ::std::error::Error; - - /// Validates if the provided proof holds given a current ingress queue. - /// - /// In case of success produces egress posts. - fn validate( - &self, - code: &[u8], - // TODO [ToDr] actually consolidate - consolidated_ingress: &[(u64, Vec)], - balance_downloads: &[BalanceDownload], - block_data: ¶chain::BlockData, - previous_head_data: ¶chain::HeadData, - ) -> Result; -} - #[cfg(test)] mod tests { use super::*; diff --git a/substrate/runtime-std/Cargo.toml b/substrate/runtime-std/Cargo.toml index 8a672e93a4..c3f0eaf508 100644 --- a/substrate/runtime-std/Cargo.toml +++ b/substrate/runtime-std/Cargo.toml @@ -12,11 +12,11 @@ pwasm-alloc = { path = "../wasm-runtime/pwasm-alloc", version = "0.1" } pwasm-libc = { path = "../wasm-runtime/pwasm-libc", version = "0.1" } environmental = { path = "../environmental", version = "0.1", optional = true } polkadot-state-machine = { path = "../state-machine", version = "0.1", optional = true } -polkadot-primitives = { path = "../primitives", version = "0.1", optional = true } +polkadot-primitives = { path = "../primitives", version = "0.1", default_features = false } triehash = { version = "0.1", optional = true } [features] default = ["std"] -std = ["environmental", "polkadot-state-machine", "polkadot-primitives", "triehash"] +std = ["environmental", "polkadot-state-machine", "triehash", "polkadot-primitives/std"] nightly = [] strict = [] diff --git a/substrate/runtime-std/src/lib.rs b/substrate/runtime-std/src/lib.rs index ab3bbe9580..c789de3aea 100644 --- a/substrate/runtime-std/src/lib.rs +++ b/substrate/runtime-std/src/lib.rs @@ -28,8 +28,6 @@ include!("../with_std.rs"); #[cfg(not(feature = "std"))] include!("../without_std.rs"); - - /// Prelude of common useful imports. /// /// This should include only things which are in the normal std prelude. @@ -37,3 +35,49 @@ pub mod prelude { pub use ::vec::Vec; pub use ::boxed::Box; } + +/// Type definitions and helpers for transactions. +pub mod transaction { + pub use primitives::transaction::{Transaction, UncheckedTransaction}; + + #[cfg(feature = "std")] + use std::ops; + + #[cfg(not(feature = "std"))] + use core::ops; + + /// A type-safe indicator that a transaction has been checked. + #[derive(Debug, PartialEq, Eq, Clone)] + pub struct CheckedTransaction(UncheckedTransaction); + + impl CheckedTransaction { + /// Get a reference to the checked signature. + pub fn signature(&self) -> &[u8; 64] { + &self.0.signature + } + } + + impl ops::Deref for CheckedTransaction { + type Target = Transaction; + + fn deref(&self) -> &Transaction { + &self.0.transaction + } + } + + /// Check the signature on a transaction. + /// + /// On failure, return the transaction back. + pub fn check(tx: UncheckedTransaction) -> Result { + // TODO: requires canonical serialization of transaction. + let msg = unimplemented!(); + if ed25519_verify(&tx.signature, &msg, &tx.transaction.signed) { + Ok(CheckedTransaction(tx)) + } else { + Err(tx) + } + } +} +/// Check a transaction +pub struct CheckedTransaction(primitives::UncheckedTransaction); + diff --git a/substrate/runtime-std/with_std.rs b/substrate/runtime-std/with_std.rs index 19a3cd04a3..d66eb91419 100644 --- a/substrate/runtime-std/with_std.rs +++ b/substrate/runtime-std/with_std.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . - #[macro_use] extern crate environmental; @@ -32,18 +31,14 @@ pub use std::boxed; pub use std::slice; pub use std::mem; +// re-export hashing functions. +pub use primitives::{blake2_256, twox_128, twox_256}; + pub use polkadot_state_machine::{Externalities, ExternalitiesError, TestExternalities}; use primitives::hexdisplay::HexDisplay; // TODO: use the real error, not NoError. -#[derive(Debug)] -/// As it says - an empty type we use for errors. -pub struct NoError; -impl fmt::Display for NoError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "") } -} - environmental!(ext : trait Externalities); /// Get `key` from storage and return a `Vec`, empty if there's a problem. @@ -97,9 +92,6 @@ pub fn enumerated_trie_root(serialised_values: &[&[u8]]) -> [u8; 32] { triehash::ordered_trie_root(serialised_values.iter().map(|s| s.to_vec())).0 } -/// Conduct a Keccak-256 hash of the given data. -pub use primitives::{blake2_256, twox_128, twox_256}; - /// Verify a ed25519 signature. pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool { ed25519::verify(&sig[..], msg, &pubkey[..]) diff --git a/substrate/runtime-std/without_std.rs b/substrate/runtime-std/without_std.rs index d49bcdbcaa..939b9f0d27 100644 --- a/substrate/runtime-std/without_std.rs +++ b/substrate/runtime-std/without_std.rs @@ -6,6 +6,8 @@ extern crate pwasm_libc; #[cfg(feature = "nightly")] extern crate pwasm_alloc; +extern crate polkadot_primitives as primitives;; + pub use alloc::vec; pub use alloc::boxed; pub use alloc::rc; diff --git a/substrate/wasm-runtime/polkadot/src/primitives/digest.rs b/substrate/wasm-runtime/polkadot/src/primitives/digest.rs index 10f36aef4f..8b9095a883 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/digest.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/digest.rs @@ -18,9 +18,9 @@ use runtime_std::prelude::*; +/// The digest of a block, useful for light-clients. #[derive(Clone, Default)] #[cfg_attr(feature = "std", derive(PartialEq, Debug))] -/// The digest of a block, useful for light-clients. pub struct Digest { /// All logs that have happened in the block. pub logs: Vec>, diff --git a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs index a4c9b5f805..b823391fb8 100644 --- a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs +++ b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs @@ -85,38 +85,6 @@ impl Slicable for Proposal { } } -impl Proposal { - pub fn enact(&self) { - let mut params = StreamReader::new(&self.input_data); - match self.function { - InternalFunction::SystemSetCode => { - let code: Vec = params.read().unwrap(); - system::privileged::set_code(&code); - } - InternalFunction::StakingSetSessionsPerEra => { - let value = params.read().unwrap(); - staking::privileged::set_sessions_per_era(value); - } - InternalFunction::StakingSetBondingDuration => { - let value = params.read().unwrap(); - staking::privileged::set_bonding_duration(value); - } - InternalFunction::StakingSetValidatorCount => { - let value = params.read().unwrap(); - staking::privileged::set_validator_count(value); - } - InternalFunction::GovernanceSetApprovalPpmRequired => { - let value = params.read().unwrap(); - governance::privileged::set_approval_ppm_required(value); - } - InternalFunction::SessionSetLength => { - let value = params.read().unwrap(); - session::privileged::set_length(value); - } - } - } -} - #[cfg(test)] mod test { use super::*; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index 49605ce3ef..c50255ea1e 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -109,6 +109,36 @@ pub mod internal { } } } + + fn enact_proposal(proposal: Proposal) { + let mut params = StreamReader::new(&self.input_data); + match self.function { + InternalFunction::SystemSetCode => { + let code: Vec = params.read().unwrap(); + system::privileged::set_code(&code); + } + InternalFunction::StakingSetSessionsPerEra => { + let value = params.read().unwrap(); + staking::privileged::set_sessions_per_era(value); + } + InternalFunction::StakingSetBondingDuration => { + let value = params.read().unwrap(); + staking::privileged::set_bonding_duration(value); + } + InternalFunction::StakingSetValidatorCount => { + let value = params.read().unwrap(); + staking::privileged::set_validator_count(value); + } + InternalFunction::GovernanceSetApprovalPpmRequired => { + let value = params.read().unwrap(); + governance::privileged::set_approval_ppm_required(value); + } + InternalFunction::SessionSetLength => { + let value = params.read().unwrap(); + session::privileged::set_length(value); + } + } + } } #[cfg(test)] diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 8df20f138e..7a919ae58e 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -49,6 +49,8 @@ pub mod privileged { pub mod internal { use super::*; + struct CheckedTransaction(UncheckedTransaction); + /// Deposits a log and ensures it matches the blocks log data. pub fn deposit_log(log: &[u8]) { with_env(|e| { @@ -115,7 +117,40 @@ pub mod internal { storage::put(&nonce_key, &(expected_nonce + 1)); // decode parameters and dispatch - tx.function.dispatch(&tx.signed, &tx.input_data); + dispatch_function(&tx.function, &tx.signed, &tx.input_data); + } + + fn dispatch_function(function: &Function, transactor: &AccountId, data: &[u8]) { + let mut params = ::runtime_codec::StreamReader::new(data); + match *self { + Function::StakingStake => { + staking::public::stake(transactor); + } + Function::StakingUnstake => { + staking::public::unstake(transactor); + } + Function::StakingTransfer => { + let dest = params.read().unwrap(); + let value = params.read().unwrap(); + staking::public::transfer(transactor, &dest, value); + } + Function::SessionSetKey => { + let session = params.read().unwrap(); + session::public::set_key(transactor, &session); + } + Function::TimestampSet => { + let t = params.read().unwrap(); + timestamp::public::set(t); + } + Function::GovernancePropose => { + let proposal = params.read().unwrap(); + governance::public::propose(transactor, &proposal); + } + Function::GovernanceApprove => { + let era_index = params.read().unwrap(); + governance::public::approve(transactor, era_index); + } + } } } From e4e755a87ab7318da441b5f344aedd61f6f34818 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Thu, 1 Feb 2018 13:29:16 +0100 Subject: [PATCH 08/21] refactor codec --- substrate/runtime-codec/src/lib.rs | 1 - substrate/runtime-codec/src/slicable.rs | 129 +++++++++----------- substrate/runtime-codec/src/streamreader.rs | 74 ----------- 3 files changed, 61 insertions(+), 143 deletions(-) delete mode 100644 substrate/runtime-codec/src/streamreader.rs diff --git a/substrate/runtime-codec/src/lib.rs b/substrate/runtime-codec/src/lib.rs index f31fa3cf94..0599953156 100644 --- a/substrate/runtime-codec/src/lib.rs +++ b/substrate/runtime-codec/src/lib.rs @@ -28,7 +28,6 @@ mod keyedvec; pub use self::endiansensitive::EndianSensitive; pub use self::slicable::{Slicable, NonTrivialSlicable}; -pub use self::streamreader::StreamReader; pub use self::joiner::Joiner; pub use self::keyedvec::KeyedVec; diff --git a/substrate/runtime-codec/src/slicable.rs b/substrate/runtime-codec/src/slicable.rs index 82b527c771..1d76fb851e 100644 --- a/substrate/runtime-codec/src/slicable.rs +++ b/substrate/runtime-codec/src/slicable.rs @@ -23,115 +23,108 @@ use super::endiansensitive::EndianSensitive; /// Trait that allows zero-copy read/write of value-references to/from slices in LE format. pub trait Slicable: Sized { - /// Attempt to deserialise the value from a slice. - fn from_slice(value: &[u8]) -> Option { - Self::set_as_slice(|out, offset| if value.len() >= out.len() + offset { - let value = &value[offset..]; - let len = out.len(); - out.copy_from_slice(&value[0..len]); - true - } else { - false - }) - } + /// Attempt to deserialise the value from a slice. Ignore trailing bytes and + /// set the slice's start to just after the last byte consumed. + /// + /// If `None` is returned, then the slice should be unmodified. + fn from_slice(value: &mut &[u8]) -> Option; + /// Convert self to an owned vector. fn to_vec(&self) -> Vec { self.as_slice_then(|s| s.to_vec()) } - fn set_as_slice bool>(fill_slice: F) -> Option; - fn as_slice_then R>(&self, f: F) -> R { - f(&self.to_vec()) - } - fn size_of(_value: &[u8]) -> Option; + /// Convert self to a slice and then invoke the given closure with it. + fn as_slice_then R>(&self, f: F) -> R; } /// Trait to mark that a type is not trivially (essentially "in place") serialisable. pub trait NonTrivialSlicable: Slicable {} impl Slicable for T { - fn set_as_slice bool>(fill_slice: F) -> Option { + fn from_slice(value: &mut &[u8]) -> Option { let size = mem::size_of::(); assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type."); - let mut result: T = unsafe { mem::zeroed() }; - let result_slice = unsafe { - let ptr = &mut result as *mut _ as *mut u8; - slice::from_raw_parts_mut(ptr, size) - }; - if fill_slice(result_slice, 0) { - Some(result.from_le()) + if value.len() >= size { + let x: T = unsafe { ::std::ptr::read(value.as_ptr() as *const T) }; + *value = &value[size..]; + Some(x.from_le()) } else { None } } + fn as_slice_then R>(&self, f: F) -> R { - let size = mem::size_of::(); - assert!(size > 0, "EndianSensitive can never be implemented for a zero-sized type."); self.as_le_then(|le| { + let size = mem::size_of::(); let value_slice = unsafe { let ptr = le as *const _ as *const u8; - slice::from_raw_parts(ptr, size) + if size != 0 { + slice::from_raw_parts(ptr, size) + } else { + &[] + } }; + f(value_slice) }) } - fn size_of(_value: &[u8]) -> Option { - Some(mem::size_of::()) - } } impl Slicable for Vec { - fn from_slice(value: &[u8]) -> Option { - Some(value[4..].to_vec()) - } - fn set_as_slice bool>(fill_slice: F) -> Option { - u32::set_as_slice(&fill_slice).and_then(|len| { - let mut v = Vec::with_capacity(len as usize); - unsafe { v.set_len(len as usize); } - if fill_slice(&mut v, 4) { - Some(v) - } else { - None - } + fn from_slice(value: &mut &[u8]) -> Option { + u32::from_slice(value).map(move |len| { + let len = len as usize; + let res = value[..len].to_vec(); + *value = &value[len..]; + res }) } - fn to_vec(&self) -> Vec { - let mut r: Vec = Vec::new().join(&(self.len() as u32)); - r.extend_from_slice(&self); - r + fn as_slice_then R>(&self, f: F) -> R { + f(&self.to_vec()) } - fn size_of(data: &[u8]) -> Option { - u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) + + fn to_vec(&self) -> Vec { + let len = self.len(); + assert!(len <= u32::max_value() as usize, "Attempted to serialize vec with too many elements."); + + let mut r: Vec = Vec::new().join(&(len as u32)); + r.extend_from_slice(self); + r } } impl NonTrivialSlicable for Vec where Vec: Slicable {} impl Slicable for Vec { - fn from_slice(value: &[u8]) -> Option { - let len = Self::size_of(&value[0..4])?; - let mut off = 4; - let mut r = Vec::new(); - while off < len { - let element_len = T::size_of(&value[off..])?; - r.push(T::from_slice(&value[off..off + element_len])?); - off += element_len; - } - Some(r) + fn from_slice(value: &mut &[u8]) -> Option { + u32::from_slice(value).and_then(move |len| { + let len = len as usize; + let mut r = Vec::with_capacity(len); + for _ in 0..len { + match T::from_slice(value) { + None => return None, + Some(v) => r.push(v), + } + } + + Some(r) + }) } - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); + fn as_slice_then R>(&self, f: F) -> R { + f(&self.to_vec()) } fn to_vec(&self) -> Vec { - let vecs = self.iter().map(Slicable::to_vec).collect::>(); - let len = vecs.iter().fold(0, |mut a, v| {a += v.len(); a}); - let mut r = Vec::new().join(&(len as u32)); - vecs.iter().for_each(|v| r.extend_from_slice(v)); - r - } + use std::iter::Extend; - fn size_of(data: &[u8]) -> Option { - u32::from_slice(&data[0..4]).map(|i| (i + 4) as usize) + let len = self.len(); + assert!(len <= u32::max_value() as usize, "Attempted to serialize vec with too many elements."); + + let mut r: Vec = Vec::new().join(&(len as u32)); + for item in self { + r.extend(item.to_vec()); + } + r } } diff --git a/substrate/runtime-codec/src/streamreader.rs b/substrate/runtime-codec/src/streamreader.rs deleted file mode 100644 index 33056a5ac3..0000000000 --- a/substrate/runtime-codec/src/streamreader.rs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Deserialiser. - -use slicable::Slicable; - -/// Simple deserialiser. -pub struct StreamReader<'a> { - data: &'a [u8], - offset: usize, -} - -impl<'a> StreamReader<'a> { - /// Create a new deserialiser based on the `data`. - pub fn new(data: &'a [u8]) -> Self { - StreamReader { - data: data, - offset: 0, - } - } - - /// Deserialise a single item from the data stream. - pub fn read(&mut self) -> Option { - let size = T::size_of(&self.data[self.offset..])?; - let new_offset = self.offset + size; - let slice = &self.data[self.offset..new_offset]; - self.offset = new_offset; - Slicable::from_slice(slice) - } -} -/* -// Not in use yet -// TODO: introduce fn size_will_be(&self) -> usize; to Slicable trait and implement -struct StreamWriter<'a> { - data: &'a mut[u8], - offset: usize, -} - -impl<'a> StreamWriter<'a> { - pub fn new(data: &'a mut[u8]) -> Self { - StreamWriter { - data: data, - offset: 0, - } - } - pub fn write(&mut self, value: &T) -> bool { - value.as_slice_then(|s| { - let new_offset = self.offset + s.len(); - if self.data.len() <= new_offset { - let slice = &mut self.data[self.offset..new_offset]; - self.offset = new_offset; - slice.copy_from_slice(s); - true - } else { - false - } - }) - } -} -*/ From 2bc7c57359c3b75d5649f0a9b984dbcd7a4556fb Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 5 Feb 2018 16:15:45 +0100 Subject: [PATCH 09/21] reintroduce slicable to primitives --- substrate/primitives/Cargo.toml | 2 +- substrate/primitives/src/block.rs | 109 +++++++++++++++--- substrate/primitives/src/hash.rs | 10 ++ substrate/primitives/src/lib.rs | 17 +++ substrate/primitives/src/parachain.rs | 20 ++++ substrate/primitives/src/proposal.rs | 112 ++++++++++++++----- substrate/primitives/src/runtime_function.rs | 103 +++++++++++++++-- substrate/primitives/src/transaction.rs | 33 ++++++ substrate/runtime-codec/src/lib.rs | 1 - 9 files changed, 351 insertions(+), 56 deletions(-) diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index 9421c8f624..01aa0315ae 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -15,7 +15,7 @@ untrusted = "0.5" twox-hash = "1.1.0" byteorder = "1.1" blake2-rfc = "0.2.18" -polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1" } +polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1", default_features = false } [dev-dependencies] polkadot-serializer = { path = "../serializer", version = "0.1" } diff --git a/substrate/primitives/src/block.rs b/substrate/primitives/src/block.rs index 26639d7d2e..3fd73b09cc 100644 --- a/substrate/primitives/src/block.rs +++ b/substrate/primitives/src/block.rs @@ -17,6 +17,7 @@ //! Block and header type definitions. use bytes::{self, Vec}; +use codec::Slicable; use hash::H256; use parachain; use transaction::UncheckedTransaction; @@ -34,6 +35,35 @@ pub type TransactionHash = H256; #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct Log(#[serde(with="bytes")] pub Vec); +impl Slicable for Log { + fn from_slice(value: &mut &[u8]) -> Option { + Vec::::from_slice(value).map(Log) + } + + fn as_slice_then R>(&self, f: F) -> R { + self.0.as_slice_then(f) + } +} + +impl ::codec::NonTrivialSlicable for Log { } + +/// The digest of a block, useful for light-clients. +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct Digest { + /// All logs that have happened in the block. + pub logs: Vec, +} + +impl Slicable for Digest { + fn from_slice(value: &mut &[u8]) -> Option { + Vec::::from_slice(value).map(|logs| Digest { logs }) + } + + fn as_slice_then R>(&self, f: F) -> R { + self.logs.as_slice_then(f) + } +} + /// A Polkadot relay chain block. #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct Block { @@ -43,11 +73,26 @@ pub struct Block { pub transactions: Vec, } -/// The digest of a block, useful for light-clients. -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] -pub struct Digest { - /// All logs that have happened in the block. - pub logs: Vec, +impl Slicable for Block { + fn from_slice(value: &mut &[u8]) -> Option { + Some(Block { + header: try_opt!(Slicable::from_slice(value)), + transactions: try_opt!(Slicable::from_slice(value)), + }) + } + + fn to_vec(&self) -> Vec { + let mut v = Vec::new(); + + v.extend(self.header.to_vec()); + v.extend(self.transactions.to_vec()); + + v + } + + fn as_slice_then R>(&self, f: F) -> R { + f(self.to_vec().as_slice()) + } } /// A relay chain block header. @@ -65,12 +110,38 @@ pub struct Header { pub state_root: H256, /// The root of the trie that represents this block's transactions, indexed by a 32-byte integer. pub transaction_root: H256, - /// Parachain activity bitfield - pub parachain_activity: parachain::Activity, /// The digest of activity on the block. pub digest: Digest, } +impl Slicable for Header { + fn from_slice(value: &mut &[u8]) -> Option { + Some(Header { + parent_hash: try_opt!(Slicable::from_slice(value)), + number: try_opt!(Slicable::from_slice(value)), + state_root: try_opt!(Slicable::from_slice(value)), + transaction_root: try_opt!(Slicable::from_slice(value)), + digest: try_opt!(Slicable::from_slice(value)), + }) + } + + fn to_vec(&self) -> Vec { + let mut v = Vec::new(); + + self.parent_hash.as_slice_then(|s| v.extend(s)); + self.number.as_slice_then(|s| v.extend(s)); + self.state_root.as_slice_then(|s| v.extend(s)); + self.transaction_root.as_slice_then(|s| v.extend(s)); + self.digest.as_slice_then(|s| v.extend(s)); + + v + } + + fn as_slice_then R>(&self, f: F) -> R { + f(self.to_vec().as_slice()) + } +} + /// A relay chain block body. /// /// Included candidates should be sorted by parachain ID, and without duplicate @@ -86,25 +157,33 @@ pub struct Body { #[cfg(test)] mod tests { use super::*; + use codec::Slicable; use polkadot_serializer as ser; #[test] fn test_header_serialization() { - assert_eq!(ser::to_string_pretty(&Header { + let header = Header { parent_hash: 5.into(), number: 67, state_root: 3.into(), - parachain_activity: parachain::Activity(vec![0]), - logs: vec![Log(vec![1])], - }), r#"{ + transaction_root: 6.into(), + digest: Digest { logs: vec![Log(vec![1])] }, + }; + + assert_eq!(ser::to_string_pretty(&header), r#"{ "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000005", "number": 67, "stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000003", - "parachainActivity": "0x00", - "logs": [ - "0x01" - ] + "transactionRoot": "0x0000000000000000000000000000000000000000000000000000000000000006", + "digest": { + "logs": [ + "0x01" + ] + } }"#); + + let v = header.to_vec(); + assert_eq!(Header::from_slice(&mut &v[..]).unwrap(), header); } #[test] diff --git a/substrate/primitives/src/hash.rs b/substrate/primitives/src/hash.rs index b6711cdfcb..8e7c6f2b8f 100644 --- a/substrate/primitives/src/hash.rs +++ b/substrate/primitives/src/hash.rs @@ -34,6 +34,16 @@ macro_rules! impl_serde { .map(|x| (&*x).into()) } } + + impl ::codec::Slicable for $name { + fn from_slice(value: &mut &[u8]) -> Option { + <[u8; $len] as ::codec::Slicable>::from_slice(value).map($name) + } + + fn as_slice_then R>(&self, f: F) -> R { + self.0.as_slice_then(f) + } + } } } diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index 00ceee2d54..fb6a056dd5 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -40,6 +40,7 @@ extern crate uint as uint_crate; #[cfg(feature = "std")] extern crate core; +extern crate polkadot_runtime_codec as codec; #[cfg(test)] extern crate polkadot_serializer; #[cfg(test)] @@ -50,6 +51,16 @@ extern crate pretty_assertions; #[macro_use] extern crate alloc; +// TODO: factor out to separate crate. +macro_rules! try_opt { + ($e: expr) => { + match $e { + Some(x) => x, + None => return None, + } + } +} + mod bytes; pub mod block; pub mod contract; @@ -95,6 +106,12 @@ pub type Hash = [u8; 32]; /// Alias to 520-bit hash when used in the context of a signature. pub type Signature = hash::H512; +/// A balance in the staking subsystem. +pub type Balance = u64; + +/// A timestamp. +pub type Timestamp = u64; + /// A hash function. pub fn hash(data: &[u8]) -> hash::H256 { blake2_256(data).into() diff --git a/substrate/primitives/src/parachain.rs b/substrate/primitives/src/parachain.rs index 360b7bacdd..5c5429e019 100644 --- a/substrate/primitives/src/parachain.rs +++ b/substrate/primitives/src/parachain.rs @@ -30,6 +30,16 @@ impl From for Id { fn from(x: u64) -> Self { Id(x) } } +impl ::codec::Slicable for Id { + fn from_slice(value: &mut &[u8]) -> Option { + u64::from_slice(value).map(Id) + } + + fn as_slice_then R>(&self, f: F) -> R { + self.0.as_slice_then(f) + } +} + /// Candidate parachain block. /// /// https://github.com/w3f/polkadot-spec/blob/master/spec.md#candidate-para-chain-block @@ -101,6 +111,16 @@ pub struct ValidationCode(#[serde(with="bytes")] pub Vec); #[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)] pub struct Activity(#[serde(with="bytes")] pub Vec); +impl ::codec::Slicable for Activity { + fn from_slice(value: &mut &[u8]) -> Option { + Vec::::from_slice(value).map(Activity) + } + + fn as_slice_then R>(&self, f: F) -> R { + self.0.as_slice_then(f) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/substrate/primitives/src/proposal.rs b/substrate/primitives/src/proposal.rs index f8f39c815b..833f08a94a 100644 --- a/substrate/primitives/src/proposal.rs +++ b/substrate/primitives/src/proposal.rs @@ -19,12 +19,12 @@ //! This describes a combination of a function ID and data that can be used to call into //! an internal function. -use bytes; +use block::Number as BlockNumber; +use codec::Slicable; -/// Internal functions that can be dispatched to. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[repr(u8)] -pub enum InternalFunction { +enum InternalFunctionId { /// Set the system's code. SystemSetCode = 0, /// Set the number of sessions per era. @@ -39,17 +39,17 @@ pub enum InternalFunction { SessionSetLength = 5, } -impl InternalFunction { +impl InternalFunctionId { /// Derive `Some` value from a `u8`, or `None` if it's invalid. - pub fn from_u8(value: u8) -> Option { + fn from_u8(value: u8) -> Option { use self::*; let functions = [ - InternalFunction::SystemSetCode, - InternalFunction::StakingSetSessionsPerEra, - InternalFunction::StakingSetBondingDuration, - InternalFunction::StakingSetValidatorCount, - InternalFunction::GovernanceSetApprovalPpmRequired, - InternalFunction::SessionSetLength + InternalFunctionId::SystemSetCode, + InternalFunctionId::StakingSetSessionsPerEra, + InternalFunctionId::StakingSetBondingDuration, + InternalFunctionId::StakingSetValidatorCount, + InternalFunctionId::GovernanceSetApprovalPpmRequired, + InternalFunctionId::SessionSetLength ]; if (value as usize) < functions.len() { Some(functions[value as usize]) @@ -59,31 +59,85 @@ impl InternalFunction { } } +/// Internal functions that can be dispatched to. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[repr(u8)] +pub enum InternalFunction { + /// Set the system's code. + SystemSetCode(Vec), + /// Set the number of sessions per era. + StakingSetSessionsPerEra(BlockNumber), + /// Set the minimum bonding duration for staking. + StakingSetBondingDuration(BlockNumber), + /// Set the validator count for staking. + StakingSetValidatorCount(u32), + /// Set the per-mille of validator approval required for governance changes. + GovernanceSetApprovalPpmRequired(u32), + /// Set the session length. + SessionSetLength(BlockNumber), +} + /// An internal function. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct Proposal { /// The privileged function to call. pub function: InternalFunction, - /// The serialised data to call it with. - #[serde(with = "bytes")] - pub input_data: Vec, } -#[cfg(test)] -mod test { - use super::*; - use support::StaticHexInto; - - #[test] - fn slicing_should_work() { - let p = Proposal { - function: InternalFunction::SystemSetCode, - input_data: b"Hello world".to_vec(), +impl Slicable for Proposal { + fn from_slice(value: &mut &[u8]) -> Option { + let id = try_opt!(u8::from_slice(value).and_then(InternalFunctionId::from_u8)); + let function = match id { + InternalFunctionId::SystemSetCode => + InternalFunction::SystemSetCode(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::StakingSetSessionsPerEra => + InternalFunction::StakingSetSessionsPerEra(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::StakingSetBondingDuration => + InternalFunction::StakingSetBondingDuration(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::StakingSetValidatorCount => + InternalFunction::StakingSetValidatorCount(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::GovernanceSetApprovalPpmRequired => + InternalFunction::GovernanceSetApprovalPpmRequired(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::SessionSetLength => + InternalFunction::SessionSetLength(try_opt!(Slicable::from_slice(value))), }; - let v = p.to_vec(); - assert_eq!(v, "000b00000048656c6c6f20776f726c64".convert::>()); - let o = Proposal::from_slice(&v).unwrap(); - assert_eq!(p, o); + Some(Proposal { function }) + } + + fn to_vec(&self) -> Vec { + let mut v = Vec::new(); + match self.function { + InternalFunction::SystemSetCode(ref data) => { + (InternalFunctionId::SystemSetCode as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + InternalFunction::StakingSetSessionsPerEra(ref data) => { + (InternalFunctionId::StakingSetSessionsPerEra as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + InternalFunction::StakingSetBondingDuration(ref data) => { + (InternalFunctionId::StakingSetBondingDuration as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + InternalFunction::StakingSetValidatorCount(ref data) => { + (InternalFunctionId::StakingSetValidatorCount as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + InternalFunction::GovernanceSetApprovalPpmRequired(ref data) => { + (InternalFunctionId::GovernanceSetApprovalPpmRequired as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + InternalFunction::SessionSetLength(ref data) => { + (InternalFunctionId::SessionSetLength as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + } + + v + } + + fn as_slice_then R>(&self, f: F) -> R { + f(self.to_vec().as_slice()) } } diff --git a/substrate/primitives/src/runtime_function.rs b/substrate/primitives/src/runtime_function.rs index 0104447f02..c4f6298f74 100644 --- a/substrate/primitives/src/runtime_function.rs +++ b/substrate/primitives/src/runtime_function.rs @@ -17,10 +17,12 @@ //! Polkadot runtime functions. //! This describes a function that can be called from an external transaction. +use codec::Slicable; + /// Public functions that can be dispatched to. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[repr(u8)] -pub enum Function { +enum FunctionId { /// Staking subsystem: begin staking. StakingStake = 0, /// Staking subsystem: stop staking. @@ -37,18 +39,99 @@ pub enum Function { GovernanceApprove = 6, } -impl Function { +impl FunctionId { /// Derive `Some` value from a `u8`, or `None` if it's invalid. - pub fn from_u8(value: u8) -> Option { + fn from_u8(value: u8) -> Option { match value { - 0 => Some(Function::StakingStake), - 1 => Some(Function::StakingUnstake), - 2 => Some(Function::StakingTransfer), - 3 => Some(Function::SessionSetKey), - 4 => Some(Function::TimestampSet), - 5 => Some(Function::GovernancePropose), - 6 => Some(Function::GovernanceApprove), + 0 => Some(FunctionId::StakingStake), + 1 => Some(FunctionId::StakingUnstake), + 2 => Some(FunctionId::StakingTransfer), + 3 => Some(FunctionId::SessionSetKey), + 4 => Some(FunctionId::TimestampSet), + 5 => Some(FunctionId::GovernancePropose), + 6 => Some(FunctionId::GovernanceApprove), _ => None, } } } + +/// Functions on the runtime. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[repr(u8)] +pub enum Function { + /// Staking subsystem: begin staking. + StakingStake, + /// Staking subsystem: stop staking. + StakingUnstake, + /// Staking subsystem: transfer stake. + StakingTransfer(::AccountId, ::Balance), + /// Set temporary session key as a validator. + SessionSetKey(::SessionKey), + /// Set the timestamp. + TimestampSet(::Timestamp), + /// Make a proposal for the governance system. + GovernancePropose(::proposal::Proposal), + /// Approve a proposal for the governance system. + GovernanceApprove(::block::Number), +} + +impl Slicable for Function { + fn from_slice(value: &mut &[u8]) -> Option { + let id = try_opt!(u8::from_slice(value).and_then(FunctionId::from_u8)); + Some(match id { + FunctionId::StakingStake => Function::StakingStake, + FunctionId::StakingUnstake => Function::StakingUnstake, + FunctionId::StakingTransfer => Function::StakingTransfer( + try_opt!(Slicable::from_slice(value)), + try_opt!(Slicable::from_slice(value)), + ), + FunctionId::SessionSetKey => + Function::SessionSetKey(try_opt!(Slicable::from_slice(value))), + FunctionId::TimestampSet => + Function::TimestampSet(try_opt!(Slicable::from_slice(value))), + FunctionId::GovernancePropose => + Function::GovernancePropose(try_opt!(Slicable::from_slice(value))), + FunctionId::GovernanceApprove => + Function::GovernanceApprove(try_opt!(Slicable::from_slice(value))), + }) + } + + fn to_vec(&self) -> Vec { + let mut v = Vec::new(); + match *self { + Function::StakingStake => { + (FunctionId::StakingStake as u8).as_slice_then(|s| v.extend(s)); + } + Function::StakingUnstake => { + (FunctionId::StakingUnstake as u8).as_slice_then(|s| v.extend(s)); + } + Function::StakingTransfer(ref to, ref amount) => { + (FunctionId::StakingTransfer as u8).as_slice_then(|s| v.extend(s)); + to.as_slice_then(|s| v.extend(s)); + amount.as_slice_then(|s| v.extend(s)); + } + Function::SessionSetKey(ref data) => { + (FunctionId::SessionSetKey as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + Function::TimestampSet(ref data) => { + (FunctionId::TimestampSet as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + Function::GovernancePropose(ref data) => { + (FunctionId::GovernancePropose as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + Function::GovernanceApprove(ref data) => { + (FunctionId::GovernanceApprove as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + } + + v + } + + fn as_slice_then R>(&self, f: F) -> R { + f(self.to_vec().as_slice()) + } +} diff --git a/substrate/primitives/src/transaction.rs b/substrate/primitives/src/transaction.rs index eb3e823c58..57b62c878b 100644 --- a/substrate/primitives/src/transaction.rs +++ b/substrate/primitives/src/transaction.rs @@ -17,6 +17,7 @@ //! Transaction type. use bytes::{self, Vec}; +use codec::Slicable; use runtime_function::Function; #[cfg(feature = "std")] @@ -48,6 +49,38 @@ pub struct UncheckedTransaction { pub signature: ::Signature, } +impl Slicable for UncheckedTransaction { + fn from_slice(value: &mut &[u8]) -> Option { + Some(UncheckedTransaction { + transaction: Transaction { + signed: try_opt!(Slicable::from_slice(value)), + nonce: try_opt!(Slicable::from_slice(value)), + function: try_opt!(Slicable::from_slice(value)), + input_data: try_opt!(Slicable::from_slice(value)), + }, + signature: try_opt!(Slicable::from_slice(value)), + }) + } + + fn to_vec(&self) -> Vec { + let mut v = Vec::new(); + + self.transaction.signed.as_slice_then(|s| v.extend(s)); + self.transaction.nonce.as_slice_then(|s| v.extend(s)); + self.transaction.function.as_slice_then(|s| v.extend(s)); + self.transaction.input_data.as_slice_then(|s| v.extend(s)); + self.signature.as_slice_then(|s| v.extend(s)); + + v + } + + fn as_slice_then R>(&self, f: F) -> R { + f(self.to_vec().as_slice()) + } +} + +impl ::codec::NonTrivialSlicable for UncheckedTransaction {} + impl PartialEq for UncheckedTransaction { fn eq(&self, other: &Self) -> bool { self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction diff --git a/substrate/runtime-codec/src/lib.rs b/substrate/runtime-codec/src/lib.rs index 0599953156..3e076858be 100644 --- a/substrate/runtime-codec/src/lib.rs +++ b/substrate/runtime-codec/src/lib.rs @@ -22,7 +22,6 @@ mod endiansensitive; mod slicable; -mod streamreader; mod joiner; mod keyedvec; From b58df7892f2fe2b29b61a5fa3e05009331dc5faa Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 5 Feb 2018 17:40:49 +0100 Subject: [PATCH 10/21] integrate new primitives with native-runtime --- substrate/Cargo.lock | 2 + substrate/client/src/lib.rs | 4 +- substrate/native-runtime/Cargo.toml | 3 +- substrate/network/src/message.rs | 4 +- substrate/primitives/src/ed25519.rs | 2 +- substrate/primitives/src/lib.rs | 2 +- substrate/primitives/src/transaction.rs | 59 ++++- substrate/rpc/src/chain/tests.rs | 4 +- substrate/runtime-std/Cargo.toml | 3 +- substrate/runtime-std/src/lib.rs | 12 +- substrate/runtime-std/with_std.rs | 1 - substrate/validator/src/validator.rs | 8 +- substrate/wasm-runtime/polkadot/src/lib.rs | 15 +- .../polkadot/src/primitives/block.rs | 58 ----- .../polkadot/src/primitives/digest.rs | 27 -- .../polkadot/src/primitives/function.rs | 86 ------- .../polkadot/src/primitives/header.rs | 72 ------ .../polkadot/src/primitives/misc.rs | 41 --- .../polkadot/src/primitives/mod.rs | 38 --- .../polkadot/src/primitives/proposal.rs | 105 -------- .../polkadot/src/primitives/tests.rs | 241 ------------------ .../polkadot/src/primitives/transaction.rs | 67 ----- .../src/primitives/uncheckedtransaction.rs | 83 ------ .../polkadot/src/runtime/governance.rs | 63 ++--- .../polkadot/src/runtime/session.rs | 12 +- .../polkadot/src/runtime/staking.rs | 20 +- .../polkadot/src/runtime/system.rs | 100 ++++---- .../polkadot/src/runtime/timestamp.rs | 4 +- .../polkadot/src/support/environment.rs | 2 +- .../polkadot/src/support/storage.rs | 11 +- .../polkadot/src/support/testing.rs | 6 +- 31 files changed, 179 insertions(+), 976 deletions(-) delete mode 100644 substrate/wasm-runtime/polkadot/src/primitives/block.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/primitives/digest.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/primitives/function.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/primitives/header.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/primitives/misc.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/primitives/mod.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/primitives/proposal.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/primitives/tests.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/primitives/transaction.rs delete mode 100644 substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 662004ef70..e6ac55fab5 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -817,6 +817,7 @@ name = "native-runtime" version = "0.1.0" dependencies = [ "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "polkadot-primitives 0.1.0", "polkadot-runtime-codec 0.1.0", "polkadot-runtime-std 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1100,6 +1101,7 @@ version = "0.1.0" dependencies = [ "environmental 0.1.0", "polkadot-primitives 0.1.0", + "polkadot-runtime-codec 0.1.0", "polkadot-state-machine 0.1.0", "pwasm-alloc 0.1.0", "pwasm-libc 0.1.0", diff --git a/substrate/client/src/lib.rs b/substrate/client/src/lib.rs index 2773085ece..5ce710c886 100644 --- a/substrate/client/src/lib.rs +++ b/substrate/client/src/lib.rs @@ -115,8 +115,8 @@ impl Client where parent_hash: Default::default(), number: 0, state_root: Default::default(), - parachain_activity: Default::default(), - logs: Default::default(), + transaction_root: Default::default(), + digest: Default::default(), }; let mut tx = backend.begin_transaction(BlockId::Hash(block::HeaderHash::default()))?; diff --git a/substrate/native-runtime/Cargo.toml b/substrate/native-runtime/Cargo.toml index 9081c3d198..a0b874ece1 100644 --- a/substrate/native-runtime/Cargo.toml +++ b/substrate/native-runtime/Cargo.toml @@ -6,9 +6,10 @@ authors = ["Parity Technologies "] [dependencies] polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1" } polkadot-runtime-std = { path = "../runtime-std", version = "0.1" } +polkadot-primitives = { path = "../primitives", version = "0.1" } rustc-hex = "1.0" hex-literal = "0.1.0" [features] default = ["std"] -std = ["polkadot-runtime-codec/std", "polkadot-runtime-std/std"] +std = ["polkadot-runtime-codec/std", "polkadot-runtime-std/std", "polkadot-primitives/std"] diff --git a/substrate/network/src/message.rs b/substrate/network/src/message.rs index ff0c678b0b..807bb02f8a 100644 --- a/substrate/network/src/message.rs +++ b/substrate/network/src/message.rs @@ -18,7 +18,7 @@ use std::borrow::Borrow; use primitives::parachain::Id as ParachainId; -use primitives::Address; +use primitives::AccountId; use primitives::block::{Number as BlockNumber, HeaderHash, Header, Body}; use service::Role as RoleFlags; @@ -150,7 +150,7 @@ pub struct Status { /// Signatue of `best_hash` made with validator address. Required for the validator role. pub validator_signature: Option, /// Validator address. Required for the validator role. - pub validator_id: Option
, + pub validator_id: Option, /// Parachain id. Required for the collator role. pub parachain_id: Option, } diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs index 85f683e93a..f259485eb2 100644 --- a/substrate/primitives/src/ed25519.rs +++ b/substrate/primitives/src/ed25519.rs @@ -229,7 +229,7 @@ mod test { let pair = Pair::from_seed(b"12345678901234567890123456789012"); let public = pair.public(); assert_eq!(public, "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".into()); - let message: Vec = FromHex::from_hex("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000").unwrap(); + let message: Vec = FromHex::from_hex("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee000000000000000002d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000").unwrap(); let signature = pair.sign(&message[..]); assert!(signature.verify(&message[..], &public)); } diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index fb6a056dd5..a5fc293d0a 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -101,7 +101,7 @@ pub type BlockNumber = u64; pub type TxOrder = u64; /// A hash of some data. -pub type Hash = [u8; 32]; +pub type Hash = hash::H256; /// Alias to 520-bit hash when used in the context of a signature. pub type Signature = hash::H512; diff --git a/substrate/primitives/src/transaction.rs b/substrate/primitives/src/transaction.rs index 57b62c878b..67ae64cde1 100644 --- a/substrate/primitives/src/transaction.rs +++ b/substrate/primitives/src/transaction.rs @@ -16,7 +16,7 @@ //! Transaction type. -use bytes::{self, Vec}; +use bytes::Vec; use codec::Slicable; use runtime_function::Function; @@ -35,9 +35,30 @@ pub struct Transaction { pub nonce: ::TxOrder, /// The function that should be called. pub function: Function, - /// Serialised input data to the function. - #[serde(with = "bytes")] - pub input_data: Vec, +} + +impl Slicable for Transaction { + fn from_slice(value: &mut &[u8]) -> Option { + Some(Transaction { + signed: try_opt!(Slicable::from_slice(value)), + nonce: try_opt!(Slicable::from_slice(value)), + function: try_opt!(Slicable::from_slice(value)), + }) + } + + fn to_vec(&self) -> Vec { + let mut v = Vec::new(); + + self.signed.as_slice_then(|s| v.extend(s)); + self.nonce.as_slice_then(|s| v.extend(s)); + self.function.as_slice_then(|s| v.extend(s)); + + v + } + + fn as_slice_then R>(&self, f: F) -> R { + f(self.to_vec().as_slice()) + } } /// A transactions right from the external world. Unchecked. @@ -52,12 +73,7 @@ pub struct UncheckedTransaction { impl Slicable for UncheckedTransaction { fn from_slice(value: &mut &[u8]) -> Option { Some(UncheckedTransaction { - transaction: Transaction { - signed: try_opt!(Slicable::from_slice(value)), - nonce: try_opt!(Slicable::from_slice(value)), - function: try_opt!(Slicable::from_slice(value)), - input_data: try_opt!(Slicable::from_slice(value)), - }, + transaction: try_opt!(Transaction::from_slice(value)), signature: try_opt!(Slicable::from_slice(value)), }) } @@ -68,7 +84,6 @@ impl Slicable for UncheckedTransaction { self.transaction.signed.as_slice_then(|s| v.extend(s)); self.transaction.nonce.as_slice_then(|s| v.extend(s)); self.transaction.function.as_slice_then(|s| v.extend(s)); - self.transaction.input_data.as_slice_then(|s| v.extend(s)); self.signature.as_slice_then(|s| v.extend(s)); v @@ -92,3 +107,25 @@ impl fmt::Debug for UncheckedTransaction { write!(f, "UncheckedTransaction({:?})", self.transaction) } } + +#[cfg(test)] +mod tests { + use ::codec::Slicable; + use runtime_function::Function; + use super::*; + + #[test] + fn serialize_unchecked() { + let tx = UncheckedTransaction { + transaction: Transaction { + signed: [1; 32], + nonce: 999u64, + function: Function::TimestampSet(135135), + }, + signature: ::hash::H512([0; 64]), + }; + + let v = Slicable::to_vec(&tx); + assert_eq!(UncheckedTransaction::from_slice(&mut &v[..]).unwrap(), tx); + } +} diff --git a/substrate/rpc/src/chain/tests.rs b/substrate/rpc/src/chain/tests.rs index bf2f3afdac..18be4f7b1c 100644 --- a/substrate/rpc/src/chain/tests.rs +++ b/substrate/rpc/src/chain/tests.rs @@ -28,8 +28,8 @@ fn should_return_header() { parent_hash: 0.into(), number: 0, state_root: 0.into(), - parachain_activity: Default::default(), - logs: vec![], + transaction_root: Default::default(), + digest: Default::default(), } ); diff --git a/substrate/runtime-std/Cargo.toml b/substrate/runtime-std/Cargo.toml index c3f0eaf508..038f7bbcd6 100644 --- a/substrate/runtime-std/Cargo.toml +++ b/substrate/runtime-std/Cargo.toml @@ -13,10 +13,11 @@ pwasm-libc = { path = "../wasm-runtime/pwasm-libc", version = "0.1" } environmental = { path = "../environmental", version = "0.1", optional = true } polkadot-state-machine = { path = "../state-machine", version = "0.1", optional = true } polkadot-primitives = { path = "../primitives", version = "0.1", default_features = false } +polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1", default_features = false } triehash = { version = "0.1", optional = true } [features] default = ["std"] -std = ["environmental", "polkadot-state-machine", "triehash", "polkadot-primitives/std"] +std = ["environmental", "polkadot-state-machine", "triehash", "polkadot-primitives/std", "polkadot-runtime-codec/std"] nightly = [] strict = [] diff --git a/substrate/runtime-std/src/lib.rs b/substrate/runtime-std/src/lib.rs index c789de3aea..bca0e2018f 100644 --- a/substrate/runtime-std/src/lib.rs +++ b/substrate/runtime-std/src/lib.rs @@ -22,6 +22,8 @@ #![cfg_attr(feature = "std", doc = "Polkadot runtime standard library as compiled when linked with Rust's standard library.")] #![cfg_attr(not(feature = "std"), doc = "Polkadot's runtime standard library as compiled without Rust's standard library.")] +extern crate polkadot_runtime_codec as codec; + #[cfg(feature = "std")] include!("../with_std.rs"); @@ -39,6 +41,7 @@ pub mod prelude { /// Type definitions and helpers for transactions. pub mod transaction { pub use primitives::transaction::{Transaction, UncheckedTransaction}; + use primitives::Signature; #[cfg(feature = "std")] use std::ops; @@ -52,7 +55,7 @@ pub mod transaction { impl CheckedTransaction { /// Get a reference to the checked signature. - pub fn signature(&self) -> &[u8; 64] { + pub fn signature(&self) -> &Signature { &self.0.signature } } @@ -69,15 +72,12 @@ pub mod transaction { /// /// On failure, return the transaction back. pub fn check(tx: UncheckedTransaction) -> Result { - // TODO: requires canonical serialization of transaction. - let msg = unimplemented!(); - if ed25519_verify(&tx.signature, &msg, &tx.transaction.signed) { + let msg = ::codec::Slicable::to_vec(&tx.transaction); + if ::ed25519_verify(&tx.signature.0, &msg, &tx.transaction.signed) { Ok(CheckedTransaction(tx)) } else { Err(tx) } } } -/// Check a transaction -pub struct CheckedTransaction(primitives::UncheckedTransaction); diff --git a/substrate/runtime-std/with_std.rs b/substrate/runtime-std/with_std.rs index d66eb91419..8a4d3ddaee 100644 --- a/substrate/runtime-std/with_std.rs +++ b/substrate/runtime-std/with_std.rs @@ -21,7 +21,6 @@ extern crate polkadot_state_machine; extern crate polkadot_primitives as primitives; extern crate triehash; -use std::fmt; use primitives::ed25519; pub use std::vec; diff --git a/substrate/validator/src/validator.rs b/substrate/validator/src/validator.rs index 40fa94b80d..c251e37918 100644 --- a/substrate/validator/src/validator.rs +++ b/substrate/validator/src/validator.rs @@ -20,7 +20,7 @@ use primitives::{validator, parachain}; use serde::de::DeserializeOwned; use serializer; -use error::{Error, ErrorKind, Result}; +use error::{ErrorKind, Result}; use parachains::{ParachainCode, ParaChain1}; /// A dummy validator implementation. @@ -40,10 +40,8 @@ impl Validator { } } -impl validator::Validator for Validator { - type Error = Error; - - fn validate( +impl Validator { + pub fn validate( &self, code: &[u8], consolidated_ingress: &[(u64, Vec)], diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index 27900b9807..8e565179e3 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -25,6 +25,7 @@ extern crate polkadot_runtime_std as runtime_std; extern crate rustc_hex; extern crate polkadot_runtime_codec as codec; +extern crate polkadot_primitives as primitives; #[cfg(test)] #[macro_use] @@ -32,24 +33,24 @@ extern crate hex_literal; #[macro_use] pub mod support; -pub mod primitives; pub mod runtime; use runtime_std::prelude::*; use codec::Slicable; -use primitives::{Block, UncheckedTransaction}; +use primitives::transaction::UncheckedTransaction; +use primitives::block::Block; /// Execute a block, with `input` being the canonical serialisation of the block. Returns the /// empty vector. -pub fn execute_block(input: &[u8]) -> Vec { - runtime::system::internal::execute_block(Block::from_slice(input).unwrap()); +pub fn execute_block(mut input: &[u8]) -> Vec { + runtime::system::internal::execute_block(Block::from_slice(&mut input).unwrap()); Vec::new() } /// Execute a given, serialised, transaction. Returns the empty vector. -pub fn execute_transaction(input: &[u8]) -> Vec { - let utx = UncheckedTransaction::from_slice(input).unwrap(); - runtime::system::internal::execute_transaction(&utx); +pub fn execute_transaction(mut input: &[u8]) -> Vec { + let utx = UncheckedTransaction::from_slice(&mut input).unwrap(); + runtime::system::internal::execute_transaction(utx); Vec::new() } diff --git a/substrate/wasm-runtime/polkadot/src/primitives/block.rs b/substrate/wasm-runtime/polkadot/src/primitives/block.rs deleted file mode 100644 index 3512133e53..0000000000 --- a/substrate/wasm-runtime/polkadot/src/primitives/block.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Block type. - -use runtime_std::prelude::*; -use codec::{StreamReader, Joiner, Slicable, NonTrivialSlicable}; -use primitives::{Header, UncheckedTransaction}; - -/// A Polkadot relay chain block. -#[cfg_attr(feature = "std", derive(PartialEq, Debug))] -pub struct Block { - /// The header of the block. - pub header: Header, - /// All transactions. - pub transactions: Vec, -} - -impl Slicable for Block { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(Block { - header: reader.read()?, - transactions: reader.read()?, - }) - } - - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - Vec::new() - .join(&self.header) - .join(&self.transactions) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = Header::size_of(data)?; - let second_part = >::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl NonTrivialSlicable for Block {} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/digest.rs b/substrate/wasm-runtime/polkadot/src/primitives/digest.rs deleted file mode 100644 index 8b9095a883..0000000000 --- a/substrate/wasm-runtime/polkadot/src/primitives/digest.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Digest type. - -use runtime_std::prelude::*; - -/// The digest of a block, useful for light-clients. -#[derive(Clone, Default)] -#[cfg_attr(feature = "std", derive(PartialEq, Debug))] -pub struct Digest { - /// All logs that have happened in the block. - pub logs: Vec>, -} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/function.rs b/substrate/wasm-runtime/polkadot/src/primitives/function.rs deleted file mode 100644 index 8aafbb5231..0000000000 --- a/substrate/wasm-runtime/polkadot/src/primitives/function.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Function data: This describes a function that can be called from an external transaction. - -use primitives::AccountID; -use codec::StreamReader; -use runtime::{staking, session, timestamp, governance}; - -/// Public functions that can be dispatched to. -#[derive(Clone, Copy)] -#[cfg_attr(feature = "std", derive(PartialEq, Debug))] -#[repr(u8)] -pub enum Function { - StakingStake = 0, - StakingUnstake = 1, - StakingTransfer = 2, - SessionSetKey = 3, - TimestampSet = 4, - GovernancePropose = 5, - GovernanceApprove = 6, -} - -impl Function { - /// Derive `Some` value from a `u8`, or `None` if it's invalid. - pub fn from_u8(value: u8) -> Option { - use self::*; - let functions = [Function::StakingStake, Function::StakingUnstake, - Function::StakingTransfer, Function::SessionSetKey, Function::TimestampSet, - Function::GovernancePropose, Function::GovernanceApprove]; - if (value as usize) < functions.len() { - Some(functions[value as usize]) - } else { - None - } - } -} - -impl Function { - /// Dispatch the function. - pub fn dispatch(&self, transactor: &AccountID, data: &[u8]) { - let mut params = StreamReader::new(data); - match *self { - Function::StakingStake => { - staking::public::stake(transactor); - } - Function::StakingUnstake => { - staking::public::unstake(transactor); - } - Function::StakingTransfer => { - let dest = params.read().unwrap(); - let value = params.read().unwrap(); - staking::public::transfer(transactor, &dest, value); - } - Function::SessionSetKey => { - let session = params.read().unwrap(); - session::public::set_key(transactor, &session); - } - Function::TimestampSet => { - let t = params.read().unwrap(); - timestamp::public::set(t); - } - Function::GovernancePropose => { - let proposal = params.read().unwrap(); - governance::public::propose(transactor, &proposal); - } - Function::GovernanceApprove => { - let era_index = params.read().unwrap(); - governance::public::approve(transactor, era_index); - } - } - } -} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/header.rs b/substrate/wasm-runtime/polkadot/src/primitives/header.rs deleted file mode 100644 index 7143ae7580..0000000000 --- a/substrate/wasm-runtime/polkadot/src/primitives/header.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Block header type. - -use runtime_std::prelude::*; -use codec::{StreamReader, Joiner, Slicable, NonTrivialSlicable}; -use runtime_std::mem; -use primitives::{BlockNumber, Hash, Digest}; - -#[derive(Clone)] -#[cfg_attr(feature = "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). - pub parent_hash: Hash, - /// The block's number (how many ancestors does it have?). - pub number: BlockNumber, - /// The root of the trie that represents this block's final storage map. - pub state_root: Hash, - /// The root of the trie that represents this block's transactions, indexed by a 32-bit integer. - pub transaction_root: Hash, - /// The digest for this block. - pub digest: Digest, -} - -impl Slicable for Header { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(Header { - parent_hash: reader.read()?, - number: reader.read()?, - state_root: reader.read()?, - transaction_root: reader.read()?, - digest: Digest { logs: reader.read()?, }, - }) - } - - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - Vec::new() - .join(&self.parent_hash) - .join(&self.number) - .join(&self.state_root) - .join(&self.transaction_root) - .join(&self.digest.logs) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = mem::size_of::() + mem::size_of::() + mem::size_of::() + mem::size_of::(); - let second_part = >>::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl NonTrivialSlicable for Header {} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/misc.rs b/substrate/wasm-runtime/polkadot/src/primitives/misc.rs deleted file mode 100644 index 2d6954f9e7..0000000000 --- a/substrate/wasm-runtime/polkadot/src/primitives/misc.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Miscellaneous small types. - -/// The Ed25519 pubkey that identifies an account. -pub type AccountID = [u8; 32]; - -/// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody -/// (who matters). Essentially this means that a majority of validators have decided it is -/// "correct". -pub const EVERYBODY: AccountID = [255u8; 32]; - -/// The Ed25519 pub key of an session that belongs to an authority. This is used as what the -/// external environment/consensus algorithm calls an "authority". -pub type SessionKey = AccountID; - -/// Indentifier for a chain. -pub type ChainID = u64; - -/// Index of a block in the chain. -pub type BlockNumber = u64; - -/// Index of a transaction. -pub type TxOrder = u64; - -/// A hash of some data. -pub type Hash = [u8; 32]; diff --git a/substrate/wasm-runtime/polkadot/src/primitives/mod.rs b/substrate/wasm-runtime/polkadot/src/primitives/mod.rs deleted file mode 100644 index 51ce3d121a..0000000000 --- a/substrate/wasm-runtime/polkadot/src/primitives/mod.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Primitive types for the runtime. - -mod misc; -mod proposal; -mod function; -mod digest; -mod header; -mod transaction; -mod uncheckedtransaction; -mod block; - -#[cfg(test)] -mod tests; - -pub use self::misc::{AccountID, EVERYBODY, SessionKey, ChainID, BlockNumber, TxOrder, Hash}; -pub use self::proposal::{Proposal, InternalFunction}; -pub use self::function::Function; -pub use self::digest::Digest; -pub use self::header::Header; -pub use self::transaction::Transaction; -pub use self::uncheckedtransaction::UncheckedTransaction; -pub use self::block::Block; diff --git a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs b/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs deleted file mode 100644 index b823391fb8..0000000000 --- a/substrate/wasm-runtime/polkadot/src/primitives/proposal.rs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Proposal: This describes a combination of a function ID and data that can be used to call into -//! an internal function. - -use runtime_std::prelude::*; -use runtime_std::mem; -use codec::{Slicable, Joiner, StreamReader}; -use runtime::{system, governance, staking, session}; - -/// Internal functions that can be dispatched to. -#[derive(Clone, Copy)] -#[cfg_attr(feature = "std", derive(PartialEq, Debug))] -#[repr(u8)] -pub enum InternalFunction { - SystemSetCode = 0, - StakingSetSessionsPerEra = 1, - StakingSetBondingDuration = 2, - StakingSetValidatorCount = 3, - GovernanceSetApprovalPpmRequired = 4, - SessionSetLength = 5, -} - -impl InternalFunction { - /// Derive `Some` value from a `u8`, or `None` if it's invalid. - pub fn from_u8(value: u8) -> Option { - use self::*; - let functions = [ - InternalFunction::SystemSetCode, - InternalFunction::StakingSetSessionsPerEra, - InternalFunction::StakingSetBondingDuration, - InternalFunction::StakingSetValidatorCount, - InternalFunction::GovernanceSetApprovalPpmRequired, - InternalFunction::SessionSetLength - ]; - if (value as usize) < functions.len() { - Some(functions[value as usize]) - } else { - None - } - } -} - -/// An internal function. -#[cfg_attr(feature = "std", derive(PartialEq, Debug))] -pub struct Proposal { - /// The priviledged function to call. - pub function: InternalFunction, - /// The serialised data to call it with. - pub input_data: Vec, -} - -impl Slicable for Proposal { - fn set_as_slice bool>(fill_slice: F) -> Option { - Some(Proposal { - function: InternalFunction::from_u8(Slicable::set_as_slice(&fill_slice)?)?, - input_data: Slicable::set_as_slice(|s, o| fill_slice(s, o + 1))?, - }) - } - - fn to_vec(&self) -> Vec { - Vec::new() - .join(&(self.function as u8)) - .join(&self.input_data) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = mem::size_of::(); - let second_part = >::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -#[cfg(test)] -mod test { - use super::*; - use support::StaticHexInto; - - #[test] - fn slicing_should_work() { - let p = Proposal { - function: InternalFunction::SystemSetCode, - input_data: b"Hello world".to_vec(), - }; - let v = p.to_vec(); - assert_eq!(v, "000b00000048656c6c6f20776f726c64".convert::>()); - - let o = Proposal::from_slice(&v).unwrap(); - assert_eq!(p, o); - } -} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/tests.rs b/substrate/wasm-runtime/polkadot/src/primitives/tests.rs deleted file mode 100644 index fdb600a5bb..0000000000 --- a/substrate/wasm-runtime/polkadot/src/primitives/tests.rs +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Tests. - -use super::*; -use runtime_std::prelude::*; -use codec::{Joiner, Slicable}; -use primitives::Function; - -#[test] -fn serialise_transaction_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx = Transaction { - signed: one.clone(), - nonce: 69, - function: Function::StakingTransfer, - input_data: Vec::new().join(&two).join(&69u64), - }; - let serialised = tx.to_vec(); - assert_eq!(serialised, vec![ - 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 0, 0, 0, 0, 0, 0, 0, - 2, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0 - ]); -} - -#[test] -fn deserialise_transaction_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx = Transaction { - signed: one.clone(), - nonce: 69, - function: Function::StakingTransfer, - input_data: Vec::new().join(&two).join(&69u64), - }; - let data = [ - 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 0, 0, 0, 0, 0, 0, 0, - 2, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0 - ]; - let deserialised = Transaction::from_slice(&data).unwrap(); - assert_eq!(deserialised, tx); -} - -#[test] -fn serialise_header_works() { - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let serialised = h.to_vec(); - assert_eq!(serialised, vec![ - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 - ]); -} - -#[test] -fn deserialise_header_works() { - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let data = [ - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 - ]; - let deserialised = Header::from_slice(&data).unwrap(); - assert_eq!(deserialised, h); -} - -#[test] -fn serialise_block_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx1 = UncheckedTransaction { - transaction: Transaction { - signed: one.clone(), - nonce: 69, - function: Function::StakingTransfer, - input_data: Vec::new().join(&two).join(&69u64), - }, - signature: [1u8; 64], - }; - let tx2 = UncheckedTransaction { - transaction: Transaction { - signed: two.clone(), - nonce: 42, - function: Function::StakingStake, - input_data: Vec::new(), - }, - signature: [2u8; 64], - }; - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let b = Block { - header: h, - transactions: vec![tx1, tx2], - }; - let serialised = b.to_vec(); - assert_eq!(serialised, vec![ - // header - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, - // transactions - 2, 1, 0, 0, - // tx1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 0, 0, 0, 0, 0, 0, 0, - 2, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0, - // tx2 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 42, 0, 0, 0, 0, 0, 0, 0, - 0, - 0, 0, 0, 0 - ]); -} - -#[test] -fn deserialise_block_works() { - let one: AccountID = [1u8; 32]; - let two: AccountID = [2u8; 32]; - let tx1 = UncheckedTransaction { - transaction: Transaction { - signed: one.clone(), - nonce: 69, - function: Function::StakingTransfer, - input_data: Vec::new().join(&two).join(&69u64), - }, - signature: [1u8; 64], - }; - let tx2 = UncheckedTransaction { - transaction: Transaction { - signed: two.clone(), - nonce: 42, - function: Function::StakingStake, - input_data: Vec::new(), - }, - signature: [2u8; 64], - }; - let h = Header { - parent_hash: [4u8; 32], - number: 42, - state_root: [5u8; 32], - transaction_root: [6u8; 32], - digest: Digest { logs: vec![ b"one log".to_vec(), b"another log".to_vec() ], }, - }; - let b = Block { - header: h, - transactions: vec![tx1, tx2], - }; - let data = [ - // header - 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 42, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 26, 0, 0, 0, - 7, 0, 0, 0, - 111, 110, 101, 32, 108, 111, 103, - 11, 0, 0, 0, - 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, - // transactions - 2, 1, 0, 0, - // tx1 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 69, 0, 0, 0, 0, 0, 0, 0, - 2, - 40, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 69, 0, 0, 0, 0, 0, 0, 0, - // tx2 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 42, 0, 0, 0, 0, 0, 0, 0, - 0, - 0, 0, 0, 0 - ]; - let deserialised = Block::from_slice(&data).unwrap(); - assert_eq!(deserialised, b); -} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs b/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs deleted file mode 100644 index c31e63cfd9..0000000000 --- a/substrate/wasm-runtime/polkadot/src/primitives/transaction.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Transaction type. - -use runtime_std::prelude::*; -use codec::{StreamReader, Joiner, Slicable, NonTrivialSlicable}; -use primitives::{AccountID, TxOrder, Function}; -use runtime_std::mem; - -/// A vetted and verified transaction from the external world. -#[cfg_attr(feature = "std", derive(PartialEq, Debug))] -pub struct Transaction { - /// Who signed it (note this is not a signature). - pub signed: AccountID, - /// The number of transactions have come before from the same signer. - pub nonce: TxOrder, - /// The function that should be called. - pub function: Function, - /// Serialised input data to the function. - pub input_data: Vec, -} - -impl Slicable for Transaction { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(Transaction { - signed: reader.read()?, - nonce: reader.read()?, - function: Function::from_u8(reader.read()?)?, - input_data: reader.read()?, - }) - } - - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - Vec::new() - .join(&self.signed) - .join(&self.nonce) - .join(&(self.function as u8)) - .join(&self.input_data) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = mem::size_of::() + mem::size_of::() + mem::size_of::(); - let second_part = >::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl NonTrivialSlicable for Transaction {} diff --git a/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs b/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs deleted file mode 100644 index 1bbce40455..0000000000 --- a/substrate/wasm-runtime/polkadot/src/primitives/uncheckedtransaction.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Unchecked Transaction type. - -use runtime_std::{mem, ed25519_verify}; -use runtime_std::prelude::*; -use codec::{Slicable, NonTrivialSlicable, StreamReader, Joiner}; -use primitives::Transaction; - -#[cfg(feature = "std")] -use std::fmt; - -/// A transactions right from the external world. Unchecked. -pub struct UncheckedTransaction { - /// The actual transaction information. - pub transaction: Transaction, - /// The signature; should be an Ed25519 signature applied to the serialised `transaction` field. - pub signature: [u8; 64], -} - -impl UncheckedTransaction { - /// Verify the signature. - pub fn ed25519_verify(&self) -> bool { - let msg = self.transaction.to_vec(); - ed25519_verify(&self.signature, &msg, &self.transaction.signed) - } -} - -#[cfg(feature = "std")] -impl PartialEq for UncheckedTransaction { - fn eq(&self, other: &Self) -> bool { - self.signature.iter().eq(other.signature.iter()) && self.transaction == other.transaction - } -} - -#[cfg(feature = "std")] -impl fmt::Debug for UncheckedTransaction { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "UncheckedTransaction({:?})", self.transaction) - } -} - -impl Slicable for UncheckedTransaction { - fn from_slice(value: &[u8]) -> Option { - let mut reader = StreamReader::new(value); - Some(UncheckedTransaction { - signature: reader.read()?, - transaction: reader.read()?, - }) - } - - fn set_as_slice bool>(_fill_slice: F) -> Option { - unimplemented!(); - } - - fn to_vec(&self) -> Vec { - Vec::new() - .join(&self.signature) - .join(&self.transaction) - } - - fn size_of(data: &[u8]) -> Option { - let first_part = mem::size_of::<[u8; 64]>(); - let second_part = ::size_of(&data[first_part..])?; - Some(first_part + second_part) - } -} - -impl NonTrivialSlicable for UncheckedTransaction {} diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index c50255ea1e..b009e3597a 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -28,7 +28,8 @@ use runtime_std::prelude::*; use codec::KeyedVec; use support::storage; -use primitives::{AccountID, Hash, BlockNumber, Proposal}; +use primitives::{AccountId, Hash, BlockNumber}; +use primitives::proposal::Proposal; use runtime::{staking, system, session}; const APPROVALS_REQUIRED: &[u8] = b"gov:apr"; @@ -52,7 +53,7 @@ pub mod public { /// Propose a sensitive action to be taken. Any action that is enactable by `Proposal` is valid. /// Proposal is by the `transactor` and will automatically count as an approval. Transactor must /// be a current validator. It is illegal to propose when there is already a proposal in effect. - pub fn propose(validator: &AccountID, proposal: &Proposal) { + pub fn propose(validator: &AccountId, proposal: &Proposal) { if storage::exists(CURRENT_PROPOSAL) { panic!("there may only be one proposal per era."); } @@ -62,7 +63,7 @@ pub mod public { /// Approve the current era's proposal. Transactor must be a validator. This may not be done more /// than once for any validator in an era. - pub fn approve(validator: &AccountID, era_index: BlockNumber) { + pub fn approve(validator: &AccountId, era_index: BlockNumber) { if era_index != staking::current_era() { panic!("approval vote applied on non-current era.") } @@ -94,6 +95,7 @@ pub mod privileged { pub mod internal { use super::*; + use primitives::proposal::{Proposal, InternalFunction}; /// Current era is ending; we should finish up any proposals. pub fn end_of_an_era() { @@ -105,36 +107,29 @@ pub mod internal { .take(approvals_required as usize) .count() as u32; if approved == approvals_required { - proposal.enact(); + enact_proposal(proposal); } } } fn enact_proposal(proposal: Proposal) { - let mut params = StreamReader::new(&self.input_data); - match self.function { - InternalFunction::SystemSetCode => { - let code: Vec = params.read().unwrap(); + match proposal.function { + InternalFunction::SystemSetCode(code) => { system::privileged::set_code(&code); } - InternalFunction::StakingSetSessionsPerEra => { - let value = params.read().unwrap(); + InternalFunction::StakingSetSessionsPerEra(value) => { staking::privileged::set_sessions_per_era(value); } - InternalFunction::StakingSetBondingDuration => { - let value = params.read().unwrap(); + InternalFunction::StakingSetBondingDuration(value) => { staking::privileged::set_bonding_duration(value); } - InternalFunction::StakingSetValidatorCount => { - let value = params.read().unwrap(); + InternalFunction::StakingSetValidatorCount(value) => { staking::privileged::set_validator_count(value); } - InternalFunction::GovernanceSetApprovalPpmRequired => { - let value = params.read().unwrap(); - governance::privileged::set_approval_ppm_required(value); + InternalFunction::GovernanceSetApprovalPpmRequired(value) => { + self::privileged::set_approval_ppm_required(value); } - InternalFunction::SessionSetLength => { - let value = params.read().unwrap(); + InternalFunction::SessionSetLength(value) => { session::privileged::set_length(value); } } @@ -147,7 +142,8 @@ mod tests { use runtime_std::{with_externalities, twox_128, TestExternalities}; use codec::{KeyedVec, Joiner}; use support::{one, two, with_env}; - use primitives::{AccountID, InternalFunction}; + use primitives::AccountId; + use primitives::proposal::InternalFunction; use runtime::{staking, session}; fn new_test_ext() -> TestExternalities { @@ -189,8 +185,7 @@ mod tests { // Block 1: Make proposal. Approve it. Era length changes. with_env(|e| e.block_number = 1); public::propose(&one, &Proposal { - function: InternalFunction::StakingSetSessionsPerEra, - input_data: vec![].join(&2u64), + function: InternalFunction::StakingSetSessionsPerEra(2), }); public::approve(&two, 1); staking::internal::check_new_era(); @@ -215,8 +210,7 @@ mod tests { // Block 1: Make proposal. Fail it. with_env(|e| e.block_number = 1); public::propose(&one, &Proposal { - function: InternalFunction::StakingSetSessionsPerEra, - input_data: vec![].join(&2u64), + function: InternalFunction::StakingSetSessionsPerEra(2), }); staking::internal::check_new_era(); assert_eq!(staking::era_length(), 1); @@ -224,8 +218,7 @@ mod tests { // Block 2: Make proposal. Approve it. It should change era length. with_env(|e| e.block_number = 2); public::propose(&one, &Proposal { - function: InternalFunction::StakingSetSessionsPerEra, - input_data: vec![].join(&2u64), + function: InternalFunction::StakingSetSessionsPerEra(2), }); public::approve(&two, 2); staking::internal::check_new_era(); @@ -250,8 +243,7 @@ mod tests { // Block 1: Make proposal. Will have only 1 vote. No change. with_env(|e| e.block_number = 1); public::propose(&one, &Proposal { - function: InternalFunction::StakingSetSessionsPerEra, - input_data: vec![].join(&2u64), + function: InternalFunction::StakingSetSessionsPerEra(2), }); staking::internal::check_new_era(); assert_eq!(staking::era_length(), 1); @@ -276,8 +268,7 @@ mod tests { // Block 1: Make proposal. Will have only 1 vote. No change. with_env(|e| e.block_number = 1); public::propose(&one, &Proposal { - function: InternalFunction::StakingSetSessionsPerEra, - input_data: vec![].join(&2u64), + function: InternalFunction::StakingSetSessionsPerEra(2), }); public::approve(&two, 0); staking::internal::check_new_era(); @@ -303,8 +294,7 @@ mod tests { // Block 1: Make proposal. Will have only 1 vote. No change. with_env(|e| e.block_number = 1); public::propose(&one, &Proposal { - function: InternalFunction::StakingSetSessionsPerEra, - input_data: vec![].join(&2u64), + function: InternalFunction::StakingSetSessionsPerEra(2), }); public::approve(&two, 1); public::approve(&two, 1); @@ -331,12 +321,10 @@ mod tests { // Block 1: Make proposal. Will have only 1 vote. No change. with_env(|e| e.block_number = 1); public::propose(&one, &Proposal { - function: InternalFunction::StakingSetSessionsPerEra, - input_data: vec![].join(&2u64), + function: InternalFunction::StakingSetSessionsPerEra(2), }); public::propose(&two, &Proposal { - function: InternalFunction::StakingSetSessionsPerEra, - input_data: vec![].join(&2u64), + function: InternalFunction::StakingSetSessionsPerEra(2), }); staking::internal::check_new_era(); assert_eq!(staking::era_length(), 1); @@ -385,8 +373,7 @@ mod tests { // Block 1: Make proposal. Will have only 1 vote. No change. with_env(|e| e.block_number = 1); public::propose(&one, &Proposal { - function: InternalFunction::StakingSetSessionsPerEra, - input_data: vec![].join(&2u64), + function: InternalFunction::StakingSetSessionsPerEra(2), }); public::approve(&four, 1); staking::internal::check_new_era(); diff --git a/substrate/wasm-runtime/polkadot/src/runtime/session.rs b/substrate/wasm-runtime/polkadot/src/runtime/session.rs index 6cda783beb..b5ed28eb3a 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/session.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/session.rs @@ -20,7 +20,7 @@ use runtime_std::prelude::*; use codec::KeyedVec; use support::{storage, StorageVec}; -use primitives::{AccountID, SessionKey, BlockNumber}; +use primitives::{AccountId, SessionKey, BlockNumber}; use runtime::{system, staking, consensus}; const SESSION_LENGTH: &[u8] = b"ses:len"; @@ -31,12 +31,12 @@ const NEXT_SESSION_LENGTH: &[u8] = b"ses:nln"; struct ValidatorStorageVec {} impl StorageVec for ValidatorStorageVec { - type Item = AccountID; + type Item = AccountId; const PREFIX: &'static[u8] = b"ses:val:"; } /// Get the current set of authorities. These are the session keys. -pub fn validators() -> Vec { +pub fn validators() -> Vec { ValidatorStorageVec::items() } @@ -65,7 +65,7 @@ pub mod public { /// Sets the session key of `_validator` to `_key`. This doesn't take effect until the next /// session. - pub fn set_key(validator: &AccountID, key: &SessionKey) { + pub fn set_key(validator: &AccountId, key: &SessionKey) { // set new value for next session storage::put(&validator.to_keyed_vec(NEXT_KEY_FOR), key); } @@ -89,7 +89,7 @@ pub mod internal { /// /// Called by staking::next_era() only. `next_session` should be called after this in order to /// update the session keys to the next validator set. - pub fn set_validators(new: &[AccountID]) { + pub fn set_validators(new: &[AccountId]) { ValidatorStorageVec::set_items(new); consensus::internal::set_authorities(new); } @@ -135,7 +135,7 @@ mod tests { use runtime_std::{with_externalities, twox_128, TestExternalities}; use codec::{KeyedVec, Joiner}; use support::{one, two, with_env}; - use primitives::AccountID; + use primitives::AccountId; use runtime::{consensus, session}; fn simple_setup() -> TestExternalities { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs index df8d4d632f..cedcdcddfd 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/staking.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/staking.rs @@ -20,7 +20,7 @@ use runtime_std::prelude::*; use runtime_std::cell::RefCell; use codec::KeyedVec; use support::{storage, StorageVec}; -use primitives::{BlockNumber, AccountID}; +use primitives::{BlockNumber, AccountId}; use runtime::{system, session, governance}; /// The balance of an account. @@ -31,7 +31,7 @@ pub type Bondage = u64; struct IntentionStorageVec {} impl StorageVec for IntentionStorageVec { - type Item = AccountID; + type Item = AccountId; const PREFIX: &'static[u8] = b"sta:wil:"; } @@ -75,12 +75,12 @@ pub fn last_era_length_change() -> BlockNumber { } /// The balance of a given account. -pub fn balance(who: &AccountID) -> Balance { +pub fn balance(who: &AccountId) -> Balance { storage::get_or_default(&who.to_keyed_vec(BALANCE_OF)) } /// The liquidity-state of a given account. -pub fn bondage(who: &AccountID) -> Bondage { +pub fn bondage(who: &AccountId) -> Bondage { storage::get_or_default(&who.to_keyed_vec(BONDAGE_OF)) } @@ -94,7 +94,7 @@ pub mod public { use super::*; /// Transfer some unlocked staking balance to another staker. - pub fn transfer(transactor: &AccountID, dest: &AccountID, value: Balance) { + pub fn transfer(transactor: &AccountId, dest: &AccountId, value: Balance) { let from_key = transactor.to_keyed_vec(BALANCE_OF); let from_balance = storage::get_or_default::(&from_key); assert!(from_balance >= value); @@ -109,7 +109,7 @@ pub mod public { /// Declare the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. - pub fn stake(transactor: &AccountID) { + pub fn stake(transactor: &AccountId) { let mut intentions = IntentionStorageVec::items(); // can't be in the list twice. assert!(intentions.iter().find(|t| *t == transactor).is_none(), "Cannot stake if already staked."); @@ -121,7 +121,7 @@ pub mod public { /// Retract the desire to stake for the transactor. /// /// Effects will be felt at the beginning of the next era. - pub fn unstake(transactor: &AccountID) { + pub fn unstake(transactor: &AccountId) { let mut intentions = IntentionStorageVec::items(); if let Some(position) = intentions.iter().position(|t| t == transactor) { intentions.swap_remove(position); @@ -147,8 +147,8 @@ pub mod privileged { } /// The length of a staking era in sessions. - pub fn set_validator_count(new: usize) { - storage::put(VALIDATOR_COUNT, &(new as u32)); + pub fn set_validator_count(new: u32) { + storage::put(VALIDATOR_COUNT, &new); } } @@ -209,7 +209,7 @@ mod tests { use runtime_std::{with_externalities, twox_128, TestExternalities}; use codec::{KeyedVec, Joiner}; use support::{one, two, with_env}; - use primitives::AccountID; + use primitives::AccountId; use runtime::{staking, session}; #[test] diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 7a919ae58e..13fa35d739 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -21,7 +21,10 @@ use runtime_std::prelude::*; use runtime_std::{mem, print, storage_root, enumerated_trie_root}; use codec::{KeyedVec, Slicable}; use support::{Hashable, storage, with_env}; -use primitives::{Block, BlockNumber, Hash, UncheckedTransaction, TxOrder}; +use primitives::{AccountId, Hash, TxOrder}; +use primitives::block::{Block, Number as BlockNumber}; +use primitives::transaction::UncheckedTransaction; +use primitives::runtime_function::Function; use runtime::{staking, session}; const BLOCK_HASH_AT: &[u8] = b"sys:old:"; @@ -54,7 +57,7 @@ pub mod internal { /// Deposits a log and ensures it matches the blocks log data. pub fn deposit_log(log: &[u8]) { with_env(|e| { - assert_eq!(log, &e.digest.logs[e.next_log_index][..]); + assert_eq!(log, &e.digest.logs[e.next_log_index].0[..]); e.next_log_index += 1; }); } @@ -79,11 +82,10 @@ pub mod internal { // check transaction trie root represents the transactions. let txs = block.transactions.iter().map(Slicable::to_vec).collect::>(); let txs_root = enumerated_trie_root(&txs.iter().map(Vec::as_slice).collect::>()); -// println!("TR: {}", ::support::HexDisplay::from(&txs_root)); - assert!(header.transaction_root == txs_root, "Transaction trie root must be valid."); + assert!(header.transaction_root.0 == txs_root, "Transaction trie root must be valid."); // execute transactions - block.transactions.iter().for_each(execute_transaction); + block.transactions.iter().cloned().for_each(execute_transaction); staking::internal::check_new_era(); session::internal::check_rotate_session(); @@ -93,7 +95,7 @@ pub mod internal { // check storage root. - assert!(header.state_root == storage_root(), "Storage root must match that calculated."); + assert!(header.state_root.0 == 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. @@ -102,11 +104,14 @@ pub mod internal { } /// Execute a given transaction. - pub fn execute_transaction(utx: &UncheckedTransaction) { - // Verify the signature is good. - assert!(utx.ed25519_verify(), "All transactions should be properly signed"); + pub fn execute_transaction(utx: UncheckedTransaction) { + use runtime_std::transaction; - let ref tx = utx.transaction; + // Verify the signature is good. + let tx = match transaction::check(utx) { + Ok(tx) => tx, + Err(_) => panic!("All transactions should be properly signed"), + }; // check nonce let nonce_key = tx.signed.to_keyed_vec(b"sys:non:"); @@ -117,38 +122,31 @@ pub mod internal { storage::put(&nonce_key, &(expected_nonce + 1)); // decode parameters and dispatch - dispatch_function(&tx.function, &tx.signed, &tx.input_data); + dispatch_function(&tx.function, &tx.signed); } - fn dispatch_function(function: &Function, transactor: &AccountId, data: &[u8]) { - let mut params = ::runtime_codec::StreamReader::new(data); - match *self { + fn dispatch_function(function: &Function, transactor: &AccountId) { + match *function { Function::StakingStake => { - staking::public::stake(transactor); + ::runtime::staking::public::stake(transactor); } Function::StakingUnstake => { - staking::public::unstake(transactor); + ::runtime::staking::public::unstake(transactor); } - Function::StakingTransfer => { - let dest = params.read().unwrap(); - let value = params.read().unwrap(); - staking::public::transfer(transactor, &dest, value); + Function::StakingTransfer(dest, value) => { + ::runtime::staking::public::transfer(transactor, &dest, value); } - Function::SessionSetKey => { - let session = params.read().unwrap(); - session::public::set_key(transactor, &session); + Function::SessionSetKey(session) => { + ::runtime::session::public::set_key(transactor, &session); } - Function::TimestampSet => { - let t = params.read().unwrap(); - timestamp::public::set(t); + Function::TimestampSet(t) => { + ::runtime::timestamp::public::set(t); } - Function::GovernancePropose => { - let proposal = params.read().unwrap(); - governance::public::propose(transactor, &proposal); + Function::GovernancePropose(ref proposal) => { + ::runtime::governance::public::propose(transactor, proposal); } - Function::GovernanceApprove => { - let era_index = params.read().unwrap(); - governance::public::approve(transactor, era_index); + Function::GovernanceApprove(era_index) => { + ::runtime::governance::public::approve(transactor, era_index); } } } @@ -168,7 +166,10 @@ 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, Header, Digest}; + use primitives::transaction::{UncheckedTransaction, Transaction}; + use primitives::runtime_function::Function; + use primitives::block::{Header, Digest}; + use primitives::hash::{H256, H512}; use runtime::staking; #[test] @@ -184,18 +185,15 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 0, - function: Function::StakingTransfer, - input_data: vec![].join(&two).join(&69u64), + function: Function::StakingTransfer(two, 69), }, - signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(), + signature: "b543b41e4b7a0270eddf57ed6c435df04bb63f71c79f6ae2530ab26c734bb4e8cd57b1c190c41d5791bcdea66a16c7339b1e883e5d0538ea2d9acea800d60a00".parse().unwrap(), }; // tx: 2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000 - // sig: 679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a - - println!("tx is {}", HexDisplay::from(&tx.transaction.to_vec())); + // sig: b543b41e4b7a0270eddf57ed6c435df04bb63f71c79f6ae2530ab26c734bb4e8cd57b1c190c41d5791bcdea66a16c7339b1e883e5d0538ea2d9acea800d60a00 with_externalities(&mut t, || { - execute_transaction(&tx); + execute_transaction(tx); assert_eq!(staking::balance(&one), 42); assert_eq!(staking::balance(&two), 69); }); @@ -236,17 +234,16 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 0, - function: Function::StakingTransfer, - input_data: vec![].join(&two).join(&69u64), + function: Function::StakingTransfer(two, 69), }, - signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(), + signature: "b543b41e4b7a0270eddf57ed6c435df04bb63f71c79f6ae2530ab26c734bb4e8cd57b1c190c41d5791bcdea66a16c7339b1e883e5d0538ea2d9acea800d60a00".parse().unwrap(), }; let h = Header { - parent_hash: [69u8; 32], + parent_hash: H256([69u8; 32]), number: 1, - state_root: hex!("2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db"), - transaction_root: hex!("91fab88ad8c30a6d05ad8e0cf9ab139bf1b8cdddc69abd51cdfa6d2699038af1"), + state_root: H256(hex!("2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db")), + transaction_root: H256(hex!("c4b361b976b3aa90f9f0cdd32f4afc80dd96f200145a687196388a00363c2235")), digest: Digest { logs: vec![], }, }; @@ -274,19 +271,18 @@ mod tests { transaction: Transaction { signed: one.clone(), nonce: 0, - function: Function::StakingTransfer, - input_data: vec![].join(&two).join(&69u64), + function: Function::StakingTransfer(two, 69), }, - signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".convert(), + signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".parse().unwrap(), }; // tx: 2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000 // sig: 679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a let h = Header { - parent_hash: [69u8; 32], + parent_hash: H256([69u8; 32]), number: 1, - state_root: [0u8; 32], - transaction_root: [0u8; 32], // Unchecked currently. + state_root: H256([0u8; 32]), + transaction_root: H256([0u8; 32]), // Unchecked currently. digest: Digest { logs: vec![], }, }; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs index abc3fab5b9..de62dd03b8 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/timestamp.rs @@ -17,12 +17,10 @@ //! Timestamp manager: just handles the current timestamp. use support::storage; +use primitives::Timestamp; const CURRENT_TIMESTAMP: &[u8] = b"tim:val"; -/// Representation of a time. -pub type Timestamp = u64; - /// Get the current time. pub fn get() -> Timestamp { storage::get_or_default(CURRENT_TIMESTAMP) diff --git a/substrate/wasm-runtime/polkadot/src/support/environment.rs b/substrate/wasm-runtime/polkadot/src/support/environment.rs index 7670a4801f..a41e0d37a6 100644 --- a/substrate/wasm-runtime/polkadot/src/support/environment.rs +++ b/substrate/wasm-runtime/polkadot/src/support/environment.rs @@ -21,7 +21,7 @@ use runtime_std::mem; use runtime_std::cell::RefCell; use runtime_std::rc::Rc; -use primitives::{BlockNumber, Digest}; +use primitives::block::{Number as BlockNumber, Digest}; #[derive(Default)] /// The information that can be accessed globally. diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs index 9e6494f126..5e6ab402b8 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -24,9 +24,8 @@ use codec::{Slicable, KeyedVec}; /// Return the value of the item in storage under `key`, or `None` if there is no explicit entry. pub fn get(key: &[u8]) -> Option { - Slicable::set_as_slice(|out, offset| - runtime_std::read_storage(&twox_128(key)[..], out, offset) >= out.len() - ) + let raw = runtime_std::storage(&twox_128(key)[..]); + Slicable::from_slice(&mut &raw[..]) } /// Return the value of the item in storage under `key`, or the type's default if there is no @@ -216,10 +215,12 @@ mod tests { #[test] fn proposals_can_be_stored() { - use primitives::{Proposal, InternalFunction}; + use primitives::proposal::{Proposal, InternalFunction}; let mut t = TestExternalities { storage: HashMap::new(), }; with_externalities(&mut t, || { - let x = Proposal { function: InternalFunction::StakingSetSessionsPerEra, input_data: b"Hello world".to_vec() }; + let x = Proposal { + function: InternalFunction::StakingSetSessionsPerEra(25519), + }; put(b":test", &x); let y: Proposal = get(b":test").unwrap(); assert_eq!(x, y); diff --git a/substrate/wasm-runtime/polkadot/src/support/testing.rs b/substrate/wasm-runtime/polkadot/src/support/testing.rs index a2c8579c96..06420668c6 100644 --- a/substrate/wasm-runtime/polkadot/src/support/testing.rs +++ b/substrate/wasm-runtime/polkadot/src/support/testing.rs @@ -16,7 +16,7 @@ //! Testing helpers. -use primitives::AccountID; +use primitives::AccountId; use super::statichex::StaticHexInto; #[macro_export] @@ -27,11 +27,11 @@ macro_rules! map { } /// One account (to which we know the secret key). -pub fn one() -> AccountID { +pub fn one() -> AccountId { "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".convert() } /// Another account (secret key known). -pub fn two() -> AccountID { +pub fn two() -> AccountId { "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".convert() } From 5a675e9c645ae1f16f95f866f6e799129db66d3b Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 12:02:03 +0100 Subject: [PATCH 11/21] fix most issues with compiling on WASM --- substrate/Cargo.lock | 25 +- substrate/primitives/Cargo.toml | 26 +- substrate/primitives/src/block.rs | 29 ++- substrate/primitives/src/bytes.rs | 19 +- substrate/primitives/src/contract.rs | 24 +- substrate/primitives/src/ed25519.rs | 236 ------------------- substrate/primitives/src/lib.rs | 33 ++- substrate/primitives/src/parachain.rs | 54 +++-- substrate/primitives/src/proposal.rs | 11 +- substrate/primitives/src/runtime_function.rs | 8 +- substrate/primitives/src/transaction.rs | 6 +- substrate/primitives/src/validator.rs | 26 +- substrate/runtime-std/Cargo.toml | 12 +- substrate/runtime-std/with_std.rs | 17 +- substrate/runtime-std/without_std.rs | 2 +- substrate/serializer/Cargo.toml | 2 +- substrate/wasm-runtime/Cargo.lock | 45 ++-- substrate/wasm-runtime/build.sh | 2 +- 18 files changed, 220 insertions(+), 357 deletions(-) delete mode 100644 substrate/primitives/src/ed25519.rs diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index e6ac55fab5..1f4c24d788 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -400,8 +400,9 @@ dependencies = [ [[package]] name = "fixed-hash" version = "0.1.2" -source = "git+https://github.com/rphmeier/primitives.git?branch=uint-asm-with-feature#18e2f90688b0d90b5f79761865e394595ce55079" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -409,11 +410,9 @@ dependencies = [ [[package]] name = "fixed-hash" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.1.3" +source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#853bb53158497914f1837f5186e31e5b29f77cee" dependencies = [ - "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1055,17 +1054,15 @@ dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=uint-asm-with-feature)", + "fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", "polkadot-runtime-codec 0.1.0", "polkadot-serializer 0.1.0", "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.1.1 (git+https://github.com/rphmeier/primitives.git?branch=uint-asm-with-feature)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", ] [[package]] @@ -1105,8 +1102,10 @@ dependencies = [ "polkadot-state-machine 0.1.0", "pwasm-alloc 0.1.0", "pwasm-libc 0.1.0", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1629,8 +1628,8 @@ dependencies = [ [[package]] name = "uint" -version = "0.1.1" -source = "git+https://github.com/rphmeier/primitives.git?branch=uint-asm-with-feature#18e2f90688b0d90b5f79761865e394595ce55079" +version = "0.1.2" +source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#853bb53158497914f1837f5186e31e5b29f77cee" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1822,8 +1821,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ethcrypto 0.1.0 (git+https://github.com/paritytech/parity.git)" = "" "checksum ethereum-types 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2adaa5b8ceafcce0bc3a68ef116ca5702958cc97d70a6eb008aeddb569b092b3" "checksum ethkey 0.3.0 (git+https://github.com/paritytech/parity.git)" = "" -"checksum fixed-hash 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=uint-asm-with-feature)" = "" "checksum fixed-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4b54d107faeb66084eca7c506aa50b6b7cb9eb9a1f1f633ae2ca3af55620c191" +"checksum fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" @@ -1942,7 +1941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum uint 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91ed1e25ded4e37e0967b1f12d5f910b32f979768d4f48e2f6ca7b6e7130b44e" -"checksum uint 0.1.1 (git+https://github.com/rphmeier/primitives.git?branch=uint-asm-with-feature)" = "" +"checksum uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index 01aa0315ae..6e5a4bd0c4 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -5,16 +5,14 @@ authors = ["Parity Technologies "] [dependencies] crunchy = "0.1" -fixed-hash = { git = "https://github.com/rphmeier/primitives.git", branch = "uint-asm-with-feature" } +fixed-hash = { git = "https://github.com/rphmeier/primitives.git", branch = "compile-for-wasm", default_features = false } rustc-hex = { git = "https://github.com/rphmeier/rustc-hex.git", version = "2.0", default_features = false } serde = { version = "1.0", default_features = false } -serde_derive = "1.0" -uint = { git = "https://github.com/rphmeier/primitives.git", branch = "uint-asm-with-feature" } -ring = "0.12" -untrusted = "0.5" -twox-hash = "1.1.0" -byteorder = "1.1" -blake2-rfc = "0.2.18" +serde_derive = { version = "1.0", optional = true } +uint = { git = "https://github.com/rphmeier/primitives.git", branch = "compile-for-wasm" } +twox-hash = { version = "1.1.0", optional = true } +byteorder = { version = "1.1", default_features = false } +blake2-rfc = { version = "0.2.18", optional = true } polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1", default_features = false } [dev-dependencies] @@ -23,4 +21,14 @@ pretty_assertions = "0.4" [features] default = ["std"] -std = ["uint/std", "fixed-hash/std", "polkadot-runtime-codec/std", "serde/std", "rustc-hex/std"] +std = [ + "uint/std", + "fixed-hash/std", + "polkadot-runtime-codec/std", + "serde/std", + "rustc-hex/std", + "twox-hash", + "blake2-rfc", + "serde_derive", + "byteorder/std" +] diff --git a/substrate/primitives/src/block.rs b/substrate/primitives/src/block.rs index 3fd73b09cc..034bb64093 100644 --- a/substrate/primitives/src/block.rs +++ b/substrate/primitives/src/block.rs @@ -16,7 +16,9 @@ //! Block and header type definitions. -use bytes::{self, Vec}; +#[cfg(feature = "std")] +use bytes; +use bytes::Vec; use codec::Slicable; use hash::H256; use parachain; @@ -32,8 +34,9 @@ pub type HeaderHash = H256; pub type TransactionHash = H256; /// Execution log (event) -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -pub struct Log(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Log(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); impl Slicable for Log { fn from_slice(value: &mut &[u8]) -> Option { @@ -48,7 +51,8 @@ impl Slicable for Log { impl ::codec::NonTrivialSlicable for Log { } /// The digest of a block, useful for light-clients. -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Digest { /// All logs that have happened in the block. pub logs: Vec, @@ -65,7 +69,8 @@ impl Slicable for Digest { } /// A Polkadot relay chain block. -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Block { /// The block header. pub header: Header, @@ -98,9 +103,10 @@ impl Slicable for Block { /// A relay chain block header. /// /// https://github.com/w3f/polkadot-spec/blob/master/spec.md#header -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -#[serde(deny_unknown_fields)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct Header { /// Block parent's hash. pub parent_hash: HeaderHash, @@ -146,9 +152,10 @@ impl Slicable for Header { /// /// Included candidates should be sorted by parachain ID, and without duplicate /// IDs. -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -#[serde(deny_unknown_fields)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct Body { /// Parachain proposal blocks. pub candidates: Vec, diff --git a/substrate/primitives/src/bytes.rs b/substrate/primitives/src/bytes.rs index c4c9cfaba7..052e8fb915 100644 --- a/substrate/primitives/src/bytes.rs +++ b/substrate/primitives/src/bytes.rs @@ -63,6 +63,7 @@ pub fn serialize_uint(bytes: &[u8], serializer: S) -> Result #[derive(Debug, PartialEq, Eq)] pub enum ExpectedLen { /// Any length in bytes. + #[cfg_attr(not(feature = "std"), allow(unused))] Any, /// Exact length in bytes. Exact(usize), @@ -81,6 +82,7 @@ impl fmt::Display for ExpectedLen { } /// Deserialize into vector of bytes. +#[cfg(feature = "std")] pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { @@ -125,9 +127,24 @@ pub fn deserialize_check_len<'de, D>(deserializer: D, len: ExpectedLen) -> Resul _ => ::rustc_hex::FromHex::from_hex(&v[2..]) }; - bytes.map_err(|e| E::custom(&format!("invalid hex value: {:?}", e))) + #[cfg(feature = "std")] + fn format_err(e: ::rustc_hex::FromHexError) -> String { + format!("invalid hex value: {:?}", e); + } + + #[cfg(not(feature = "std"))] + fn format_err(e: ::rustc_hex::FromHexError) -> String { + match e { + ::rustc_hex::InvalidHexLength => format!("invalid hex value: invalid length"), + ::rustc_hex::InvalidHexCharacter(c, p) => + format!("invalid hex value: invalid character {} at position {}", c, p), + } + } + + bytes.map_err(|e| E::custom(format_err(e))) } + #[cfg(feature = "std")] fn visit_string(self, v: String) -> Result { self.visit_str(&v) } diff --git a/substrate/primitives/src/contract.rs b/substrate/primitives/src/contract.rs index 40e4f560be..771381b85b 100644 --- a/substrate/primitives/src/contract.rs +++ b/substrate/primitives/src/contract.rs @@ -16,20 +16,26 @@ //! Contract execution data. -use bytes::{self, Vec}; +#[cfg(feature = "std")] +use bytes; +use bytes::Vec; /// Contract call data. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct CallData(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct CallData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Contract output data. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct OutData(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct OutData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Contract storage key. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct StorageKey(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct StorageKey(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Contract storage entry data. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct StorageData(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct StorageData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); diff --git a/substrate/primitives/src/ed25519.rs b/substrate/primitives/src/ed25519.rs deleted file mode 100644 index f259485eb2..0000000000 --- a/substrate/primitives/src/ed25519.rs +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Simple Ed25519 API. - -use bytes::Vec; -use untrusted; -use ring::{rand, signature}; -use rustc_hex::FromHex; - -/// Verify a message without type checking the parameters' types for the right size. -pub fn verify(sig: &[u8], message: &[u8], public: &[u8]) -> bool { - let public_key = untrusted::Input::from(public); - let msg = untrusted::Input::from(message); - let sig = untrusted::Input::from(sig); - - match signature::verify(&signature::ED25519, public_key, msg, sig) { - Ok(_) => true, - _ => false, - } -} - -/// A public key. -#[derive(PartialEq, Clone, Debug)] -pub struct Public ([u8; 32]); - -/// A key pair. -pub struct Pair(signature::Ed25519KeyPair); - -/// A signature. -#[derive(Clone)] -pub struct Signature ([u8; 64]); - -impl Signature { - /// A new signature from the given 64-byte `data`. - pub fn from(data: [u8; 64]) -> Self { - Signature(data) - } - - /// A new signature from the given slice that should be 64 bytes long. - pub fn from_slice(data: &[u8]) -> Self { - let mut r = [0u8; 64]; - r.copy_from_slice(data); - Signature(r) - } -} - -impl AsRef<[u8; 64]> for Signature { - fn as_ref(&self) -> &[u8; 64] { - &self.0 - } -} - -impl AsRef<[u8]> for Signature { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl Public { - /// A new instance from the given 32-byte `data`. - pub fn from(data: [u8; 32]) -> Self { - Public(data) - } - - /// A new instance from the given slice that should be 32 bytes long. - pub fn from_slice(data: &[u8]) -> Self { - let mut r = [0u8; 32]; - r.copy_from_slice(data); - Public(r) - } -} - -impl AsRef<[u8; 32]> for Public { - fn as_ref(&self) -> &[u8; 32] { - &self.0 - } -} - -impl AsRef<[u8]> for Public { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl Pair { - /// Generate new secure (random) key pair. - pub fn new() -> Pair { - let rng = rand::SystemRandom::new(); - let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); - Pair(signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap()) - } - /// Make a new key pair from a seed phrase. - pub fn from_seed(seed: &[u8; 32]) -> Pair { - Pair(signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..])).unwrap()) - } - /// Make a new key pair from the raw secret. - pub fn from_secret(secret: &[u8; 32]) -> Pair { - let mut pkcs8_bytes: Vec = FromHex::from_hex("302e020100300506032b657004220420").unwrap(); - pkcs8_bytes.extend_from_slice(&secret[..]); - Pair(signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).unwrap()) - } - /// Make a new key pair from the raw secret and public key (it will check to make sure - /// they correspond to each other). - pub fn from_both(secret_public: &[u8; 64]) -> Option { - let mut pkcs8_bytes: Vec = FromHex::from_hex("3053020101300506032b657004220420").unwrap(); - pkcs8_bytes.extend_from_slice(&secret_public[0..32]); - pkcs8_bytes.extend_from_slice(&[0xa1u8, 0x23, 0x03, 0x21, 0x00]); - pkcs8_bytes.extend_from_slice(&secret_public[32..64]); - signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).ok().map(Pair) - } - /// Sign a message. - pub fn sign(&self, message: &[u8]) -> Signature { - let mut r = [0u8; 64]; - r.copy_from_slice(self.0.sign(message).as_ref()); - Signature(r) - } - /// Get the public key. - pub fn public(&self) -> Public { - let mut r = [0u8; 32]; - let pk = self.0.public_key_bytes(); - r.copy_from_slice(pk); - Public(r) - } -} -impl Signature { - /// Verify a message. - pub fn verify(&self, message: &[u8], public: &Public) -> bool { - let peer_public_key = untrusted::Input::from(&public.0[..]); - let msg = untrusted::Input::from(message); - let sig = untrusted::Input::from(&self.0[..]); - - match signature::verify(&signature::ED25519, peer_public_key, msg, sig) { - Ok(_) => true, - _ => false, - } - } -} -impl From<&'static str> for Public { - fn from(hex: &'static str) -> Self { - let mut r = [0u8; 32]; - r.copy_from_slice(&FromHex::from_hex::>(hex).unwrap()[0..32]); - Public(r) - } -} -impl From<&'static str> for Pair { - fn from(hex: &'static str) -> Self { - let data = FromHex::from_hex::>(hex).expect("Key pair given is static so hex should be good."); - match data.len() { - 32 => { - let mut r = [0u8; 32]; - r.copy_from_slice(&data[0..32]); - Pair::from_secret(&r) - } - 64 => { - let mut r = [0u8; 64]; - r.copy_from_slice(&data[0..64]); - Pair::from_both(&r).expect("Key pair given is static so should be good.") - } - _ => { - panic!("Key pair given is static so should be correct length."); - } - } - } -} -impl From<&'static str> for Signature { - fn from(hex: &'static str) -> Self { - let mut r = [0u8; 64]; - r.copy_from_slice(&FromHex::from_hex::>(hex).unwrap()[0..64]); - Signature(r) - } -} - -impl PartialEq for Signature { - fn eq(&self, other: &Signature) -> bool { - self.0.iter().eq(other.0.iter()) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_vector_should_work() { - let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into(); - let public = pair.public(); - assert_eq!(public, "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".into()); - let message = b""; - let signature: Signature = "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b".into(); - assert!(&pair.sign(&message[..]) == &signature); - assert!(signature.verify(&message[..], &public)); - } - - #[test] - fn generated_pair_should_work() { - let pair = Pair::new(); - let public = pair.public(); - let message = b"Something important"; - let signature = pair.sign(&message[..]); - assert!(signature.verify(&message[..], &public)); - } - - #[test] - fn seeded_pair_should_work() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); - let public = pair.public(); - assert_eq!(public, "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".into()); - let message = b"Something important"; - let signature = pair.sign(&message[..]); - assert!(signature.verify(&message[..], &public)); - } - - #[test] - fn can_sign_transaction() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); - let public = pair.public(); - assert_eq!(public, "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".into()); - let message: Vec = FromHex::from_hex("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee000000000000000002d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000").unwrap(); - let signature = pair.sign(&message[..]); - assert!(signature.verify(&message[..], &public)); - } -} diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index a5fc293d0a..111f600517 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -19,20 +19,22 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc))] +#![cfg_attr(not(feature = "std"), feature(alloc, lang_items))] extern crate rustc_hex; extern crate serde; -extern crate ring; -extern crate untrusted; -extern crate twox_hash; extern crate byteorder; + +#[cfg(feature = "std")] +extern crate twox_hash; +#[cfg(feature = "std")] extern crate blake2_rfc; #[macro_use] extern crate crunchy; #[macro_use] extern crate fixed_hash; +#[cfg(feature = "std")] #[macro_use] extern crate serde_derive; #[macro_use] @@ -61,12 +63,21 @@ macro_rules! try_opt { } } +#[lang = "panic_fmt"] +#[no_mangle] +pub extern fn panic_fmt(_fmt: ::core::fmt::Arguments, _file: &'static str, _line: u32, _col: u32) { + unsafe { + ext_print_utf8(_file.as_ptr() as *const u8, _file.len() as u32); + ext_print_num(_line as u64); + ext_print_num(_col as u64); + ::core::intrinsics::abort() + } +} + mod bytes; pub mod block; pub mod contract; -pub mod ed25519; pub mod hash; -pub mod hashing; pub mod hexdisplay; pub mod parachain; pub mod proposal; @@ -75,8 +86,13 @@ pub mod transaction; pub mod uint; pub mod validator; +#[cfg(feature = "std")] +pub mod hashing; + pub use self::hash::{H160, H256}; pub use self::uint::{U256, U512}; + +#[cfg(feature = "std")] pub use hashing::{blake2_256, twox_128, twox_256}; /// Virtual account ID that represents the idea of a dispatch/statement being signed by everybody @@ -111,8 +127,3 @@ pub type Balance = u64; /// A timestamp. pub type Timestamp = u64; - -/// A hash function. -pub fn hash(data: &[u8]) -> hash::H256 { - blake2_256(data).into() -} diff --git a/substrate/primitives/src/parachain.rs b/substrate/primitives/src/parachain.rs index 5c5429e019..4b3f308a70 100644 --- a/substrate/primitives/src/parachain.rs +++ b/substrate/primitives/src/parachain.rs @@ -16,10 +16,13 @@ //! Parachain data types. -use bytes::{self, Vec}; +#[cfg(feature = "std")] +use bytes; +use bytes::Vec; /// Unique identifier of a parachain. -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Id(u64); impl From for u64 { @@ -43,9 +46,10 @@ impl ::codec::Slicable for Id { /// Candidate parachain block. /// /// https://github.com/w3f/polkadot-spec/blob/master/spec.md#candidate-para-chain-block -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -#[serde(deny_unknown_fields)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct Candidate { /// The ID of the parachain this is a proposal for. pub parachain_index: Id, @@ -60,9 +64,10 @@ pub struct Candidate { } /// Candidate receipt type. -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -#[serde(deny_unknown_fields)] +#[derive(PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct CandidateReceipt { /// The ID of the parachain this is a candidate for. pub parachain_index: Id, @@ -79,37 +84,44 @@ pub struct CandidateReceipt { } /// Parachain ingress queue message. -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -pub struct Message(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Message(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Consolidated ingress queue data. /// /// This is just an ordered vector of other parachains' egress queues, /// obtained according to the routing rules. -#[derive(Debug, Default, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[derive(Debug, Default, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct ConsolidatedIngress(pub Vec<(Id, Vec)>); /// Parachain block data. /// /// contains everything required to validate para-block, may contain block and witness data -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -pub struct BlockData(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct BlockData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Parachain header raw bytes wrapper type. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct Header(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Header(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Parachain head data included in the chain. -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -pub struct HeadData(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct HeadData(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Parachain validation code. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct ValidationCode(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct ValidationCode(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Activitiy bit field -#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)] -pub struct Activity(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq, Clone, Default)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Activity(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); impl ::codec::Slicable for Activity { fn from_slice(value: &mut &[u8]) -> Option { diff --git a/substrate/primitives/src/proposal.rs b/substrate/primitives/src/proposal.rs index 833f08a94a..4957a3dee6 100644 --- a/substrate/primitives/src/proposal.rs +++ b/substrate/primitives/src/proposal.rs @@ -19,10 +19,12 @@ //! This describes a combination of a function ID and data that can be used to call into //! an internal function. +use bytes::Vec; use block::Number as BlockNumber; use codec::Slicable; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[repr(u8)] enum InternalFunctionId { /// Set the system's code. @@ -60,8 +62,8 @@ impl InternalFunctionId { } /// Internal functions that can be dispatched to. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[repr(u8)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum InternalFunction { /// Set the system's code. SystemSetCode(Vec), @@ -78,7 +80,8 @@ pub enum InternalFunction { } /// An internal function. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Proposal { /// The privileged function to call. pub function: InternalFunction, diff --git a/substrate/primitives/src/runtime_function.rs b/substrate/primitives/src/runtime_function.rs index c4f6298f74..4c51411f4a 100644 --- a/substrate/primitives/src/runtime_function.rs +++ b/substrate/primitives/src/runtime_function.rs @@ -17,10 +17,12 @@ //! Polkadot runtime functions. //! This describes a function that can be called from an external transaction. +use bytes::Vec; use codec::Slicable; /// Public functions that can be dispatched to. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[repr(u8)] enum FunctionId { /// Staking subsystem: begin staking. @@ -56,8 +58,8 @@ impl FunctionId { } /// Functions on the runtime. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[repr(u8)] +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum Function { /// Staking subsystem: begin staking. StakingStake, diff --git a/substrate/primitives/src/transaction.rs b/substrate/primitives/src/transaction.rs index 67ae64cde1..c7723a7f1a 100644 --- a/substrate/primitives/src/transaction.rs +++ b/substrate/primitives/src/transaction.rs @@ -27,7 +27,8 @@ use std::fmt; use alloc::fmt; /// A vetted and verified transaction from the external world. -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[derive(Debug, PartialEq, Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct Transaction { /// Who signed it (note this is not a signature). pub signed: ::AccountId, @@ -62,7 +63,8 @@ impl Slicable for Transaction { } /// A transactions right from the external world. Unchecked. -#[derive(Eq, Clone, Serialize, Deserialize)] +#[derive(Eq, Clone)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct UncheckedTransaction { /// The actual transaction information. pub transaction: Transaction, diff --git a/substrate/primitives/src/validator.rs b/substrate/primitives/src/validator.rs index 4f7d60b721..e6cba21e73 100644 --- a/substrate/primitives/src/validator.rs +++ b/substrate/primitives/src/validator.rs @@ -16,25 +16,31 @@ //! Validator primitives. -use bytes::{self, Vec}; +#[cfg(feature = "std")] +use bytes; +use bytes::Vec; use parachain; /// Parachain outgoing message. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct EgressPost(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct EgressPost(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Balance upload. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct BalanceUpload(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct BalanceUpload(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// Balance download. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -pub struct BalanceDownload(#[serde(with="bytes")] pub Vec); +#[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct BalanceDownload(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); /// The result of parachain validation. -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -#[serde(deny_unknown_fields)] +#[derive(Debug, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] +#[cfg_attr(feature = "std", serde(deny_unknown_fields))] pub struct ValidationResult { /// New head data that should be included in the relay chain state. pub head_data: parachain::HeadData, diff --git a/substrate/runtime-std/Cargo.toml b/substrate/runtime-std/Cargo.toml index 038f7bbcd6..726fb6716c 100644 --- a/substrate/runtime-std/Cargo.toml +++ b/substrate/runtime-std/Cargo.toml @@ -15,9 +15,19 @@ polkadot-state-machine = { path = "../state-machine", version = "0.1", optional polkadot-primitives = { path = "../primitives", version = "0.1", default_features = false } polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1", default_features = false } triehash = { version = "0.1", optional = true } +ring = { version = "0.12", optional = true } +untrusted = { version = "0.5", optional = true } [features] default = ["std"] -std = ["environmental", "polkadot-state-machine", "triehash", "polkadot-primitives/std", "polkadot-runtime-codec/std"] +std = [ + "environmental", + "polkadot-state-machine", + "triehash", + "polkadot-primitives/std", + "polkadot-runtime-codec/std", + "ring", + "untrusted" +] nightly = [] strict = [] diff --git a/substrate/runtime-std/with_std.rs b/substrate/runtime-std/with_std.rs index 8a4d3ddaee..ede487da64 100644 --- a/substrate/runtime-std/with_std.rs +++ b/substrate/runtime-std/with_std.rs @@ -20,8 +20,8 @@ extern crate environmental; extern crate polkadot_state_machine; extern crate polkadot_primitives as primitives; extern crate triehash; - -use primitives::ed25519; +extern crate ring; +extern crate untrusted; pub use std::vec; pub use std::rc; @@ -93,7 +93,16 @@ pub fn enumerated_trie_root(serialised_values: &[&[u8]]) -> [u8; 32] { /// Verify a ed25519 signature. pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool { - ed25519::verify(&sig[..], msg, &pubkey[..]) + use ring::signature; + + let public_key = untrusted::Input::from(pubkey); + let msg = untrusted::Input::from(msg); + let sig = untrusted::Input::from(sig); + + match signature::verify(&signature::ED25519, public_key, msg, sig) { + Ok(_) => true, + _ => false, + } } /// Execute the given closure with global function available whose functionality routes into the @@ -136,7 +145,7 @@ macro_rules! impl_stubs { } #[cfg(test)] -mod tests { +mod std_tests { use super::*; macro_rules! map { diff --git a/substrate/runtime-std/without_std.rs b/substrate/runtime-std/without_std.rs index 939b9f0d27..efe6249812 100644 --- a/substrate/runtime-std/without_std.rs +++ b/substrate/runtime-std/without_std.rs @@ -6,7 +6,7 @@ extern crate pwasm_libc; #[cfg(feature = "nightly")] extern crate pwasm_alloc; -extern crate polkadot_primitives as primitives;; +extern crate polkadot_primitives as primitives; pub use alloc::vec; pub use alloc::boxed; diff --git a/substrate/serializer/Cargo.toml b/substrate/serializer/Cargo.toml index 5b98496560..259f43016d 100644 --- a/substrate/serializer/Cargo.toml +++ b/substrate/serializer/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] -serde = "1.0" +serde = { version = "1.0", default_features = false } serde_json = "1.0" diff --git a/substrate/wasm-runtime/Cargo.lock b/substrate/wasm-runtime/Cargo.lock index 05d122c8b1..4c46282755 100644 --- a/substrate/wasm-runtime/Cargo.lock +++ b/substrate/wasm-runtime/Cargo.lock @@ -123,7 +123,7 @@ dependencies = [ "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "plain_hasher 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -150,10 +150,9 @@ dependencies = [ [[package]] name = "fixed-hash" -version = "0.1.2" -source = "git+https://github.com/paritytech/primitives.git#30f15bb3387faf40f519dd56a5768cb3d3fe3638" +version = "0.1.3" +source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#853bb53158497914f1837f5186e31e5b29f77cee" dependencies = [ - "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -335,7 +334,7 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -353,7 +352,7 @@ dependencies = [ "keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "memorydb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -373,15 +372,13 @@ dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "fixed-hash 0.1.2 (git+https://github.com/paritytech/primitives.git)", + "fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", "polkadot-runtime-codec 0.1.0", - "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.1.0 (git+https://github.com/paritytech/primitives.git)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", ] [[package]] @@ -394,11 +391,14 @@ version = "0.1.0" dependencies = [ "environmental 0.1.0", "polkadot-primitives 0.1.0", + "polkadot-runtime-codec 0.1.0", "polkadot-state-machine 0.1.0", "pwasm-alloc 0.1.0", "pwasm-libc 0.1.0", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -446,11 +446,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rand" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -480,7 +481,7 @@ dependencies = [ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -557,6 +558,11 @@ name = "rustc-hex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-hex" +version = "2.0.0" +source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc891d6dc2cc9009d7" + [[package]] name = "rustc_version" version = "0.2.1" @@ -684,13 +690,13 @@ name = "twox-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "uint" -version = "0.1.0" -source = "git+https://github.com/paritytech/primitives.git#30f15bb3387faf40f519dd56a5768cb3d3fe3638" +version = "0.1.2" +source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#853bb53158497914f1837f5186e31e5b29f77cee" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -774,7 +780,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ethcore-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb5af77e74a8f70e9c3337e069c37bc82178ef1b459c02091f73c4ad5281eb5" "checksum ethcore-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3977c772cd6c5c22e1c7cfa208e4c3b746bd6c3a6c8eeec0999a6b2103015ad5" "checksum ethcore-logger 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fd5813e49546030be7d134e775088d56b8ff4ab60617b90e93d4f0513da4c5b" -"checksum fixed-hash 0.1.2 (git+https://github.com/paritytech/primitives.git)" = "" +"checksum fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" @@ -803,7 +809,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0" "checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" +"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" "checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53" @@ -814,6 +820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" "checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" +"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" @@ -831,7 +838,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tiny-keccak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e9241752647ca572f12c9b520a5d360d9099360c527770647e694001646a1d0" "checksum triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9291c7f0fae44858b5e087dd462afb382354120003778f1695b44aab98c7abd7" "checksum twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "475352206e7a290c5fccc27624a163e8d0d115f7bb60ca18a64fc9ce056d7435" -"checksum uint 0.1.0 (git+https://github.com/paritytech/primitives.git)" = "" +"checksum uint 0.1.2 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)" = "" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" diff --git a/substrate/wasm-runtime/build.sh b/substrate/wasm-runtime/build.sh index 83f46d5a04..697fd27ee6 100755 --- a/substrate/wasm-runtime/build.sh +++ b/substrate/wasm-runtime/build.sh @@ -1,7 +1,7 @@ #!/bin/sh set -e -cargo +nightly build --target=wasm32-unknown-unknown --release +xargo +nightly build --target=wasm32-unknown-unknown --release dirs=`find * -maxdepth 0 -type d | grep -v pwasm- | grep -v std` for i in $dirs do From af2fdc547826d19fefb1ea5c485617f027ad49a6 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 12:24:34 +0100 Subject: [PATCH 12/21] fix compilation for native --- substrate/Cargo.lock | 14 +- substrate/client/src/in_mem.rs | 2 +- substrate/ed25519/Cargo.toml | 10 ++ substrate/ed25519/src/lib.rs | 191 ++++++++++++++++++++++++ substrate/executor/Cargo.toml | 1 + substrate/executor/src/lib.rs | 1 + substrate/executor/src/wasm_executor.rs | 6 +- substrate/network/src/lib.rs | 2 +- substrate/primitives/src/bytes.rs | 2 +- substrate/primitives/src/lib.rs | 13 +- substrate/runtime-std/Cargo.toml | 6 +- substrate/runtime-std/with_std.rs | 14 +- 12 files changed, 226 insertions(+), 36 deletions(-) create mode 100644 substrate/ed25519/Cargo.toml create mode 100644 substrate/ed25519/src/lib.rs diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 1f4c24d788..140b21dbda 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -191,6 +191,16 @@ name = "dtoa" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ed25519" +version = "0.1.0" +dependencies = [ + "polkadot-primitives 0.1.0", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "edit-distance" version = "2.0.1" @@ -1008,6 +1018,7 @@ version = "0.1.0" dependencies = [ "assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519 0.1.0", "error-chain 0.11.0 (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)", @@ -1096,16 +1107,15 @@ version = "0.1.0" name = "polkadot-runtime-std" version = "0.1.0" dependencies = [ + "ed25519 0.1.0", "environmental 0.1.0", "polkadot-primitives 0.1.0", "polkadot-runtime-codec 0.1.0", "polkadot-state-machine 0.1.0", "pwasm-alloc 0.1.0", "pwasm-libc 0.1.0", - "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/substrate/client/src/in_mem.rs b/substrate/client/src/in_mem.rs index cd8d7da6f9..5a71b8c62f 100644 --- a/substrate/client/src/in_mem.rs +++ b/substrate/client/src/in_mem.rs @@ -27,7 +27,7 @@ use primitives::block::{self, HeaderHash}; use blockchain::{self, BlockId, BlockStatus}; fn header_hash(header: &primitives::block::Header) -> primitives::block::HeaderHash { - primitives::hash(&ser::to_vec(header)) + primitives::hashing::blake2_256(&ser::to_vec(header)).into() } struct PendingBlock { diff --git a/substrate/ed25519/Cargo.toml b/substrate/ed25519/Cargo.toml new file mode 100644 index 0000000000..a918468dd2 --- /dev/null +++ b/substrate/ed25519/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "ed25519" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +ring = "0.12" +untrusted = "0.5" +polkadot-primitives = { version = "0.1", path = "../primitives" } +rustc-hex = { git = "https://github.com/rphmeier/rustc-hex.git", version = "2.0", default_features = false } diff --git a/substrate/ed25519/src/lib.rs b/substrate/ed25519/src/lib.rs new file mode 100644 index 0000000000..9658b46d97 --- /dev/null +++ b/substrate/ed25519/src/lib.rs @@ -0,0 +1,191 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Simple Ed25519 API. + +extern crate ring; +extern crate polkadot_primitives as primitives; +extern crate untrusted; +extern crate rustc_hex; + +use ring::{rand, signature}; +use primitives::Signature; +use rustc_hex::FromHex; + +/// Verify a message without type checking the parameters' types for the right size. +pub fn verify(sig: &[u8], message: &[u8], public: &[u8]) -> bool { + let public_key = untrusted::Input::from(public); + let msg = untrusted::Input::from(message); + let sig = untrusted::Input::from(sig); + + match signature::verify(&signature::ED25519, public_key, msg, sig) { + Ok(_) => true, + _ => false, + } +} + +/// A public key. +#[derive(PartialEq, Clone, Debug)] +pub struct Public ([u8; 32]); + +/// A key pair. +pub struct Pair(signature::Ed25519KeyPair); + +impl Public { + /// A new instance from the given 32-byte `data`. + pub fn from(data: [u8; 32]) -> Self { + Public(data) + } + + /// A new instance from the given slice that should be 32 bytes long. + pub fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(data); + Public(r) + } +} + +impl AsRef<[u8; 32]> for Public { + fn as_ref(&self) -> &[u8; 32] { + &self.0 + } +} + +impl AsRef<[u8]> for Public { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl Pair { + /// Generate new secure (random) key pair. + pub fn new() -> Pair { + let rng = rand::SystemRandom::new(); + let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).unwrap(); + Pair(signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).unwrap()) + } + /// Make a new key pair from a seed phrase. + pub fn from_seed(seed: &[u8; 32]) -> Pair { + Pair(signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..])).unwrap()) + } + /// Make a new key pair from the raw secret. + pub fn from_secret(secret: &[u8; 32]) -> Pair { + let mut pkcs8_bytes: Vec<_> = FromHex::from_hex("302e020100300506032b657004220420").unwrap(); + pkcs8_bytes.extend_from_slice(&secret[..]); + Pair(signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).unwrap()) + } + /// Make a new key pair from the raw secret and public key (it will check to make sure + /// they correspond to each other). + pub fn from_both(secret_public: &[u8; 64]) -> Option { + let mut pkcs8_bytes: Vec<_> = FromHex::from_hex("3053020101300506032b657004220420").unwrap(); + pkcs8_bytes.extend_from_slice(&secret_public[0..32]); + pkcs8_bytes.extend_from_slice(&[0xa1u8, 0x23, 0x03, 0x21, 0x00]); + pkcs8_bytes.extend_from_slice(&secret_public[32..64]); + signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&pkcs8_bytes)).ok().map(Pair) + } + /// Sign a message. + pub fn sign(&self, message: &[u8]) -> Signature { + let mut r = [0u8; 64]; + r.copy_from_slice(self.0.sign(message).as_ref()); + Signature::from(r) + } + /// Get the public key. + pub fn public(&self) -> Public { + let mut r = [0u8; 32]; + let pk = self.0.public_key_bytes(); + r.copy_from_slice(pk); + Public(r) + } +} + +/// Verify a signature on a message. +pub fn verify_strong(sig: &Signature, message: &[u8], pubkey: &Public) -> bool { + let public_key = untrusted::Input::from(&pubkey.0[..]); + let msg = untrusted::Input::from(message); + let sig = untrusted::Input::from(&sig.0[..]); + + match signature::verify(&signature::ED25519, public_key, msg, sig) { + Ok(_) => true, + _ => false, + } +} + +impl From<&'static str> for Public { + fn from(hex: &'static str) -> Self { + let mut r = [0u8; 32]; + let v: Vec<_> = FromHex::from_hex(hex).unwrap(); + r.copy_from_slice(&v[0..32]); + Public(r) + } +} +impl From<&'static str> for Pair { + fn from(hex: &'static str) -> Self { + let data: Vec<_> = FromHex::from_hex(hex).expect("Key pair given is static so hex should be good."); + match data.len() { + 32 => { + let mut r = [0u8; 32]; + r.copy_from_slice(&data[0..32]); + Pair::from_secret(&r) + } + 64 => { + let mut r = [0u8; 64]; + r.copy_from_slice(&data[0..64]); + Pair::from_both(&r).expect("Key pair given is static so should be good.") + } + _ => { + panic!("Key pair given is static so should be correct length."); + } + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_vector_should_work() { + let pair: Pair = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into(); + let public = pair.public(); + assert_eq!(public, "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a".into()); + let message = b""; + let signature: Signature = "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b".into(); + assert!(&pair.sign(&message[..]) == &signature); + assert!(verify_strong(&signature, &message[..], &public)); + } + + #[test] + fn generated_pair_should_work() { + let pair = Pair::new(); + let public = pair.public(); + let message = b"Something important"; + let signature = pair.sign(&message[..]); + assert!(verify_strong(&signature, &message[..], &public)); + } + + #[test] + fn seeded_pair_should_work() { + use primitives::hexdisplay::HexDisplay; + + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let public = pair.public(); + assert_eq!(public, "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee".into()); + let message: Vec<_> = FromHex::from_hex("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000002228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000").unwrap(); + let signature = pair.sign(&message[..]); + println!("Correct signature: {}", HexDisplay::from(&signature.0)); + assert!(verify_strong(&signature, &message[..], &public)); + } +} diff --git a/substrate/executor/Cargo.toml b/substrate/executor/Cargo.toml index ee9f9e4759..da5854e854 100644 --- a/substrate/executor/Cargo.toml +++ b/substrate/executor/Cargo.toml @@ -17,6 +17,7 @@ byteorder = "1.1" rustc-hex = "1.0.0" native-runtime = { path = "../native-runtime", version = "0.1" } triehash = "0.1.0" +ed25519 = { path = "../ed25519", version = "0.1" } [dev-dependencies] assert_matches = "1.1" diff --git a/substrate/executor/src/lib.rs b/substrate/executor/src/lib.rs index c6a9837a8d..7f63fd64f9 100644 --- a/substrate/executor/src/lib.rs +++ b/substrate/executor/src/lib.rs @@ -32,6 +32,7 @@ extern crate polkadot_runtime_std as runtime_std; extern crate polkadot_primitives as primitives; extern crate polkadot_serializer as serializer; extern crate polkadot_state_machine as state_machine; +extern crate ed25519; extern crate serde; extern crate parity_wasm; diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 7819a8fde5..f44c0414d1 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -27,7 +27,7 @@ use state_machine::{Externalities, CodeExecutor}; use error::{Error, ErrorKind, Result}; use wasm_utils::{MemoryInstance, UserDefinedElements, AddModuleWithoutFullDependentInstance}; -use primitives::{ed25519, blake2_256, twox_128, twox_256}; +use primitives::{blake2_256, twox_128, twox_256}; use primitives::hexdisplay::HexDisplay; use triehash::ordered_trie_root; @@ -217,7 +217,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| DummyUserError)?; let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| DummyUserError)?; - if ed25519::Signature::from(sig).verify(&msg, &ed25519::Public::from(pubkey)) { + if ::ed25519::verify(&sig, &msg, &pubkey) { 0 } else { 5 @@ -372,7 +372,7 @@ mod tests { fn ed25519_verify_should_work() { let mut ext = TestExternalities::default(); let test_code = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); - let key = ed25519::Pair::from_seed(&blake2_256(b"test")); + let key = ::ed25519::Pair::from_seed(&blake2_256(b"test")); let sig = key.sign(b"all ok!"); let mut calldata = vec![]; calldata.extend_from_slice(key.public().as_ref()); diff --git a/substrate/network/src/lib.rs b/substrate/network/src/lib.rs index 10a6eb6065..75f416f97b 100644 --- a/substrate/network/src/lib.rs +++ b/substrate/network/src/lib.rs @@ -57,6 +57,6 @@ pub use network::{NonReservedPeerMode, ConnectionFilter, ConnectionDirection, Ne // TODO: move it elsewhere fn header_hash(header: &primitives::block::Header) -> primitives::block::HeaderHash { - primitives::hash(&ser::to_vec(header)) + primitives::hashing::blake2_256(&ser::to_vec(header)).into() } diff --git a/substrate/primitives/src/bytes.rs b/substrate/primitives/src/bytes.rs index 052e8fb915..f8c33c5a8c 100644 --- a/substrate/primitives/src/bytes.rs +++ b/substrate/primitives/src/bytes.rs @@ -129,7 +129,7 @@ pub fn deserialize_check_len<'de, D>(deserializer: D, len: ExpectedLen) -> Resul #[cfg(feature = "std")] fn format_err(e: ::rustc_hex::FromHexError) -> String { - format!("invalid hex value: {:?}", e); + format!("invalid hex value: {:?}", e) } #[cfg(not(feature = "std"))] diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index 111f600517..95c54c64d2 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -19,7 +19,7 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(not(feature = "std"), feature(alloc, lang_items))] +#![cfg_attr(not(feature = "std"), feature(alloc))] extern crate rustc_hex; extern crate serde; @@ -63,17 +63,6 @@ macro_rules! try_opt { } } -#[lang = "panic_fmt"] -#[no_mangle] -pub extern fn panic_fmt(_fmt: ::core::fmt::Arguments, _file: &'static str, _line: u32, _col: u32) { - unsafe { - ext_print_utf8(_file.as_ptr() as *const u8, _file.len() as u32); - ext_print_num(_line as u64); - ext_print_num(_col as u64); - ::core::intrinsics::abort() - } -} - mod bytes; pub mod block; pub mod contract; diff --git a/substrate/runtime-std/Cargo.toml b/substrate/runtime-std/Cargo.toml index 726fb6716c..7ecafc73ce 100644 --- a/substrate/runtime-std/Cargo.toml +++ b/substrate/runtime-std/Cargo.toml @@ -15,8 +15,7 @@ polkadot-state-machine = { path = "../state-machine", version = "0.1", optional polkadot-primitives = { path = "../primitives", version = "0.1", default_features = false } polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1", default_features = false } triehash = { version = "0.1", optional = true } -ring = { version = "0.12", optional = true } -untrusted = { version = "0.5", optional = true } +ed25519 = { path = "../ed25519", version = "0.1", optional = true } [features] default = ["std"] @@ -26,8 +25,7 @@ std = [ "triehash", "polkadot-primitives/std", "polkadot-runtime-codec/std", - "ring", - "untrusted" + "ed25519", ] nightly = [] strict = [] diff --git a/substrate/runtime-std/with_std.rs b/substrate/runtime-std/with_std.rs index ede487da64..d03cf840fc 100644 --- a/substrate/runtime-std/with_std.rs +++ b/substrate/runtime-std/with_std.rs @@ -20,8 +20,7 @@ extern crate environmental; extern crate polkadot_state_machine; extern crate polkadot_primitives as primitives; extern crate triehash; -extern crate ring; -extern crate untrusted; +extern crate ed25519; pub use std::vec; pub use std::rc; @@ -93,16 +92,7 @@ pub fn enumerated_trie_root(serialised_values: &[&[u8]]) -> [u8; 32] { /// Verify a ed25519 signature. pub fn ed25519_verify(sig: &[u8; 64], msg: &[u8], pubkey: &[u8; 32]) -> bool { - use ring::signature; - - let public_key = untrusted::Input::from(pubkey); - let msg = untrusted::Input::from(msg); - let sig = untrusted::Input::from(sig); - - match signature::verify(&signature::ED25519, public_key, msg, sig) { - Ok(_) => true, - _ => false, - } + ed25519::verify(sig, msg, pubkey) } /// Execute the given closure with global function available whose functionality routes into the From d43c93a7dc1a69fb0d3cdf525dbc413c1ed19687 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 12:44:08 +0100 Subject: [PATCH 13/21] update native executor tests to use new tx format --- substrate/executor/src/native_executor.rs | 2 +- substrate/wasm-runtime/polkadot/src/runtime/system.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 0ecd91be35..3f1600554a 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -49,7 +49,7 @@ mod tests { const BLOATY_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); const COMPACT_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); - fn tx() -> Vec { "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000".convert() } + fn tx() -> Vec { "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee000000000000000002d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000b543b41e4b7a0270eddf57ed6c435df04bb63f71c79f6ae2530ab26c734bb4e8cd57b1c190c41d5791bcdea66a16c7339b1e883e5d0538ea2d9acea800d60a00".convert() } #[test] fn panic_execution_with_foreign_code_gives_error() { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 13fa35d739..6bced06c64 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -273,10 +273,10 @@ mod tests { nonce: 0, function: Function::StakingTransfer(two, 69), }, - signature: "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a".parse().unwrap(), + signature: "b543b41e4b7a0270eddf57ed6c435df04bb63f71c79f6ae2530ab26c734bb4e8cd57b1c190c41d5791bcdea66a16c7339b1e883e5d0538ea2d9acea800d60a00".parse().unwrap(), }; // tx: 2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000 - // sig: 679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a + // sig: b543b41e4b7a0270eddf57ed6c435df04bb63f71c79f6ae2530ab26c734bb4e8cd57b1c190c41d5791bcdea66a16c7339b1e883e5d0538ea2d9acea800d60a00 let h = Header { parent_hash: H256([69u8; 32]), From aa7432f15e863ffe2e0abb8cf0668277a29d90cd Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 13:27:09 +0100 Subject: [PATCH 14/21] get compiling on wasm --- substrate/Cargo.lock | 1 - substrate/wasm-runtime/Cargo.lock | 18 ++++++++++++++---- substrate/wasm-runtime/build.sh | 2 +- substrate/wasm-runtime/polkadot/Cargo.toml | 3 ++- .../release/runtime_polkadot.compact.wasm | Bin 68712 -> 65282 bytes .../release/runtime_polkadot.wasm | Bin 68761 -> 65360 bytes 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 140b21dbda..c25d04393b 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -1064,7 +1064,6 @@ version = "0.1.0" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", "polkadot-runtime-codec 0.1.0", "polkadot-serializer 0.1.0", diff --git a/substrate/wasm-runtime/Cargo.lock b/substrate/wasm-runtime/Cargo.lock index 4c46282755..3373ebcc9b 100644 --- a/substrate/wasm-runtime/Cargo.lock +++ b/substrate/wasm-runtime/Cargo.lock @@ -88,6 +88,16 @@ name = "crunchy" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ed25519" +version = "0.1.0" +dependencies = [ + "polkadot-primitives 0.1.0", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "either" version = "1.4.0" @@ -151,7 +161,7 @@ dependencies = [ [[package]] name = "fixed-hash" version = "0.1.3" -source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#853bb53158497914f1837f5186e31e5b29f77cee" +source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#8dc457899afdaf968ff7f16140b03d1e37b01d71" dependencies = [ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -389,16 +399,15 @@ version = "0.1.0" name = "polkadot-runtime-std" version = "0.1.0" dependencies = [ + "ed25519 0.1.0", "environmental 0.1.0", "polkadot-primitives 0.1.0", "polkadot-runtime-codec 0.1.0", "polkadot-state-machine 0.1.0", "pwasm-alloc 0.1.0", "pwasm-libc 0.1.0", - "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -542,6 +551,7 @@ dependencies = [ name = "runtime-polkadot" version = "0.1.0" dependencies = [ + "polkadot-primitives 0.1.0", "polkadot-runtime-codec 0.1.0", "polkadot-runtime-std 0.1.0", ] @@ -696,7 +706,7 @@ dependencies = [ [[package]] name = "uint" version = "0.1.2" -source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#853bb53158497914f1837f5186e31e5b29f77cee" +source = "git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm#8dc457899afdaf968ff7f16140b03d1e37b01d71" dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/substrate/wasm-runtime/build.sh b/substrate/wasm-runtime/build.sh index 697fd27ee6..83f46d5a04 100755 --- a/substrate/wasm-runtime/build.sh +++ b/substrate/wasm-runtime/build.sh @@ -1,7 +1,7 @@ #!/bin/sh set -e -xargo +nightly build --target=wasm32-unknown-unknown --release +cargo +nightly build --target=wasm32-unknown-unknown --release dirs=`find * -maxdepth 0 -type d | grep -v pwasm- | grep -v std` for i in $dirs do diff --git a/substrate/wasm-runtime/polkadot/Cargo.toml b/substrate/wasm-runtime/polkadot/Cargo.toml index 24715e8c99..b0bc7a480b 100644 --- a/substrate/wasm-runtime/polkadot/Cargo.toml +++ b/substrate/wasm-runtime/polkadot/Cargo.toml @@ -9,7 +9,8 @@ crate-type = ["cdylib"] [dependencies] polkadot-runtime-codec = { path = "../../runtime-codec", version = "0.1", default-features = false } polkadot-runtime-std = { path = "../../runtime-std", version = "0.1", default-features = false } +polkadot-primitives = { path = "../../primitives", version = "0.1", default-features = false } [features] default = [] -std = ["polkadot-runtime-codec/std", "polkadot-runtime-std/std"] +std = ["polkadot-runtime-codec/std", "polkadot-runtime-std/std", "polkadot-primitives/std"] 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 1e0d5c637beb89bb2efd1a5db78ab304ad73f429..e5b92273481035ff15c3bc974578f9ebdf648035 100644 GIT binary patch literal 65282 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 From 4cba452c31a60d980871a308794db4d9ceda7b43 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 13:39:29 +0100 Subject: [PATCH 15/21] fix tests --- substrate/Cargo.lock | 1 + substrate/executor/src/wasm_executor.rs | 4 ++-- substrate/rpc/src/chain/tests.rs | 2 +- substrate/rpc/src/state/tests.rs | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index c25d04393b..140b21dbda 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -1064,6 +1064,7 @@ version = "0.1.0" dependencies = [ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", "polkadot-runtime-codec 0.1.0", "polkadot-serializer 0.1.0", diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index f44c0414d1..c7f9073aab 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -287,6 +287,8 @@ mod tests { use native_runtime::support::{one, two, StaticHexInto}; use native_runtime::runtime::staking::balance; + fn tx() -> Vec { "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee000000000000000002d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000b543b41e4b7a0270eddf57ed6c435df04bb63f71c79f6ae2530ab26c734bb4e8cd57b1c190c41d5791bcdea66a16c7339b1e883e5d0538ea2d9acea800d60a00".convert() } + #[test] fn returning_should_work() { let mut ext = TestExternalities::default(); @@ -393,8 +395,6 @@ mod tests { ); } - fn tx() -> Vec { "679fcf0a846b4224c84ecad7d91a26241c46d00cb53d6480a363274e8965ee34b0b80b4b2e3836d3d8f8f12c0c1aef7350af587d9aee3883561d11726068ac0a2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000".convert() } - #[test] fn panic_execution_gives_error() { let one = one(); diff --git a/substrate/rpc/src/chain/tests.rs b/substrate/rpc/src/chain/tests.rs index 18be4f7b1c..952b20b35c 100644 --- a/substrate/rpc/src/chain/tests.rs +++ b/substrate/rpc/src/chain/tests.rs @@ -23,7 +23,7 @@ fn should_return_header() { let client = client::new_in_mem(executor::executor()).unwrap(); assert_matches!( - ChainApi::header(&client, "11265ce45dd2baaaf071f6df8c5a44f0ed1d85a50e71451ff2d4345e57d12e3a".into()), + ChainApi::header(&client, "af65e54217fb213853703d57b80fc5b2bb834bf923046294d7a49bff62f0a8b2".into()), Ok(Some(ref x)) if x == &block::Header { parent_hash: 0.into(), number: 0, diff --git a/substrate/rpc/src/state/tests.rs b/substrate/rpc/src/state/tests.rs index b62221adea..556fa8cfce 100644 --- a/substrate/rpc/src/state/tests.rs +++ b/substrate/rpc/src/state/tests.rs @@ -23,7 +23,7 @@ use client; #[test] fn should_return_storage() { let client = client::new_in_mem(executor::executor()).unwrap(); - let genesis_hash = "11265ce45dd2baaaf071f6df8c5a44f0ed1d85a50e71451ff2d4345e57d12e3a".into(); + let genesis_hash = "af65e54217fb213853703d57b80fc5b2bb834bf923046294d7a49bff62f0a8b2".into(); assert_matches!( StateApi::storage(&client, StorageKey(vec![10]), genesis_hash), @@ -36,7 +36,7 @@ fn should_return_storage() { fn should_call_contract() { // TODO [ToDr] Fix test after we are able to mock state. let client = client::new_in_mem(executor::executor()).unwrap(); - let genesis_hash = "11265ce45dd2baaaf071f6df8c5a44f0ed1d85a50e71451ff2d4345e57d12e3a".into(); + let genesis_hash = "af65e54217fb213853703d57b80fc5b2bb834bf923046294d7a49bff62f0a8b2".into(); assert_matches!( StateApi::call(&client, "balanceOf".into(), CallData(vec![1,2,3]), genesis_hash), From de65de47581131e53cde6e96cce275b44a9139fb Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 14:44:25 +0100 Subject: [PATCH 16/21] fix tests after merge --- substrate/Cargo.lock | 2 + substrate/client/Cargo.toml | 2 + substrate/client/src/genesis.rs | 37 ++++++++-------- substrate/client/src/lib.rs | 2 + substrate/executor/src/native_executor.rs | 40 +++++++++--------- substrate/executor/src/wasm_executor.rs | 19 ++++----- substrate/primitives/src/block.rs | 13 ++++++ .../polkadot/src/runtime/genesismap.rs | 11 ++--- .../polkadot/src/runtime/system.rs | 10 ++--- .../release/runtime_polkadot.compact.wasm | Bin 65282 -> 66501 bytes .../release/runtime_polkadot.wasm | Bin 65360 -> 66580 bytes .../release/runtime_test.compact.wasm | Bin 14114 -> 14104 bytes .../release/runtime_test.wasm | Bin 14239 -> 14229 bytes 13 files changed, 77 insertions(+), 59 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 0e3641737f..75a256c839 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -996,6 +996,7 @@ dependencies = [ name = "polkadot-client" version = "0.1.0" dependencies = [ + "ed25519 0.1.0", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1003,6 +1004,7 @@ dependencies = [ "parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "polkadot-executor 0.1.0", "polkadot-primitives 0.1.0", + "polkadot-runtime-codec 0.1.0", "polkadot-serializer 0.1.0", "polkadot-state-machine 0.1.0", "triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/substrate/client/Cargo.toml b/substrate/client/Cargo.toml index 06bfaf97b3..f8221bef8e 100644 --- a/substrate/client/Cargo.toml +++ b/substrate/client/Cargo.toml @@ -11,6 +11,8 @@ polkadot-primitives = { path = "../primitives", version = "0.1" } polkadot-state-machine = { path = "../state-machine", version = "0.1" } polkadot-serializer = { path = "../serializer" } polkadot-executor = { path = "../executor" } +polkadot-runtime-codec = { path = "../runtime-codec", version = "0.1" } native-runtime = { path = "../native-runtime" } triehash = "0.1" hex-literal = "0.1" +ed25519 = { path = "../ed25519", version = "0.1" } diff --git a/substrate/client/src/genesis.rs b/substrate/client/src/genesis.rs index 6e560a91d1..3a8a287e27 100644 --- a/substrate/client/src/genesis.rs +++ b/substrate/client/src/genesis.rs @@ -40,19 +40,21 @@ pub fn construct_genesis_block(storage: &HashMap, Vec>) -> Block { #[cfg(test)] mod tests { use super::*; - use native_runtime::codec::{Slicable, Joiner}; + use codec::{Slicable, Joiner}; use native_runtime::support::{one, two, Hashable}; use native_runtime::runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; - use native_runtime::primitives::{AccountID, Hash, BlockNumber, Transaction, - UncheckedTransaction, Digest, Function}; use state_machine::execute; use state_machine::OverlayedChanges; use state_machine::backend::InMemory; use polkadot_executor::executor; + use primitives::{AccountId, Hash, H256}; + use primitives::block::{Number as BlockNumber, Header, Digest}; + use primitives::runtime_function::Function; + use primitives::transaction::{UncheckedTransaction, Transaction}; use primitives::contract::CallData; - use primitives::ed25519::Pair; + use ed25519::Pair; - fn secret_for(who: &AccountID) -> Option { + fn secret_for(who: &AccountId) -> Option { match who { x if *x == one() => Some(Pair::from_seed(b"12345678901234567890123456789012")), x if *x == two() => Some("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into()), @@ -65,12 +67,12 @@ mod tests { let transactions = txs.into_iter().map(|transaction| { let signature = secret_for(&transaction.signed).unwrap() - .sign(&transaction.to_vec()) - .inner(); + .sign(&transaction.to_vec()); + UncheckedTransaction { transaction, signature } }).collect::>(); - let transaction_root = ordered_trie_root(transactions.iter().map(Slicable::to_vec)).0; + let transaction_root = H256(ordered_trie_root(transactions.iter().map(Slicable::to_vec)).0); let mut header = Header { parent_hash, @@ -84,24 +86,26 @@ mod tests { let mut overlay = OverlayedChanges::default(); for tx in transactions.iter() { - header = Header::from_slice(&execute( + let ret_data = execute( backend, &mut overlay, &executor(), "execute_transaction", &CallData(vec![].join(&header).join(tx)) - ).unwrap()).unwrap(); + ).unwrap(); + header = Header::from_slice(&mut &ret_data[..]).unwrap(); } - header = Header::from_slice(&execute( + let ret_data = execute( backend, &mut overlay, &executor(), "finalise_block", &CallData(vec![].join(&header)) - ).unwrap()).unwrap(); + ).unwrap(); + header = Header::from_slice(&mut &ret_data[..]).unwrap(); - (vec![].join(&Block { header, transactions }), hash) + (vec![].join(&Block { header, transactions }), H256(hash)) } fn block1(genesis_hash: Hash, backend: &InMemory) -> (Vec, Hash) { @@ -109,12 +113,11 @@ mod tests { backend, 1, genesis_hash, - hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c"), + H256(hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c")), vec![Transaction { signed: one(), nonce: 0, - function: Function::StakingTransfer, - input_data: vec![].join(&two()).join(&69u64), + function: Function::StakingTransfer(two(), 69), }] ) } @@ -125,7 +128,7 @@ mod tests { vec![one(), two()], 1000 ).genesis_map(); let block = construct_genesis_block(&storage); - let genesis_hash = block.header.blake2_256(); + let genesis_hash = H256(block.header.blake2_256()); storage.extend(additional_storage_with_genesis(&block).into_iter()); let mut overlay = OverlayedChanges::default(); diff --git a/substrate/client/src/lib.rs b/substrate/client/src/lib.rs index 6eff92226f..9d0513bc6a 100644 --- a/substrate/client/src/lib.rs +++ b/substrate/client/src/lib.rs @@ -21,8 +21,10 @@ extern crate polkadot_primitives as primitives; extern crate polkadot_state_machine as state_machine; extern crate polkadot_serializer as ser; +extern crate polkadot_runtime_codec as codec; extern crate polkadot_executor; extern crate native_runtime; +extern crate ed25519; extern crate triehash; extern crate parking_lot; diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 3b86627437..df6e64908f 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -42,13 +42,15 @@ impl CodeExecutor for NativeExecutor { #[cfg(test)] mod tests { use super::*; - use codec::{KeyedVec, Slicable}; - use native_runtime::support::{one, two, Hashable}; - use runtime_std::TestExternalities; + use codec::{KeyedVec, Slicable, Joiner}; use native_runtime::support::{one, two, Hashable}; use native_runtime::runtime::staking::balance; use state_machine::TestExternalities; - use primitives::twox_128; + use primitives::{twox_128, Hash, H256}; + use primitives::runtime_function::Function; + use primitives::block::{Header, Number as BlockNumber, Block, Digest}; + use primitives::transaction::{Transaction, UncheckedTransaction}; + use ed25519::Pair; const BLOATY_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); const COMPACT_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.compact.wasm"); @@ -60,8 +62,8 @@ mod tests { function: Function::StakingTransfer(two(), 69), }; let signature = secret_for(&transaction.signed).unwrap() - .sign(&transaction.to_vec()) - .inner(); + .sign(&transaction.to_vec()); + UncheckedTransaction { transaction, signature } } @@ -147,8 +149,7 @@ mod tests { ], } } - use primitives::ed25519::Pair; - fn secret_for(who: &AccountID) -> Option { + fn secret_for(who: &::primitives::AccountId) -> Option { match who { x if *x == one() => Some(Pair::from_seed(b"12345678901234567890123456789012")), x if *x == two() => Some("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60".into()), @@ -161,12 +162,12 @@ mod tests { let transactions = txs.into_iter().map(|transaction| { let signature = secret_for(&transaction.signed).unwrap() - .sign(&transaction.to_vec()) - .inner(); + .sign(&transaction.to_vec()); + UncheckedTransaction { transaction, signature } }).collect::>(); - let transaction_root = ordered_trie_root(transactions.iter().map(Slicable::to_vec)).0; + let transaction_root = H256(ordered_trie_root(transactions.iter().map(Slicable::to_vec)).0); let header = Header { parent_hash, @@ -177,19 +178,18 @@ mod tests { }; let hash = header.blake2_256(); - (Block { header, transactions }.to_vec(), hash) + (Block { header, transactions }.to_vec(), H256(hash)) } fn block1() -> (Vec, Hash) { construct_block( 1, - [69u8; 32], - hex!("2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db"), + H256([69u8; 32]), + H256(hex!("2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db")), vec![Transaction { signed: one(), nonce: 0, - function: Function::StakingTransfer, - input_data: vec![].join(&two()).join(&69u64), + function: Function::StakingTransfer(two(), 69), }] ) } @@ -198,19 +198,17 @@ mod tests { construct_block( 2, block1().1, - hex!("2e69e4405a13981224078ad5355c68401bf56d0fe3f14a3536734666e6a8a047"), + H256(hex!("2cdbbf9bd766c2286a5f4091c131fe161addd060ba6fc041b3419089f4601bda")), vec![ Transaction { signed: two(), nonce: 0, - function: Function::StakingTransfer, - input_data: vec![].join(&one()).join(&5u64), + function: Function::StakingTransfer(one(), 5), }, Transaction { signed: one(), nonce: 1, - function: Function::StakingTransfer, - input_data: vec![].join(&two()).join(&15u64), + function: Function::StakingTransfer(two(), 15), } ] ) diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 68353e99b8..e409d6ab94 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -287,17 +287,17 @@ impl CodeExecutor for WasmExecutor { #[cfg(test)] mod tests { - use super::*; use rustc_hex::FromHex; - use primitives::{AccountId, blake2_256, twox_128}; - use primitives::block::Header; - use primitives::transaction::{Transaction, UncheckedTransaction}; - use codec::KeyedVec; - use state_machine::TestExternalities; - use runtime_std; + use codec::{KeyedVec, Slicable, Joiner}; use native_runtime::support::{one, two}; use native_runtime::runtime::staking::balance; + use state_machine::TestExternalities; + use primitives::{twox_128, AccountId}; + use primitives::runtime_function::Function; + use primitives::block::Header; + use primitives::transaction::{Transaction, UncheckedTransaction}; + use runtime_std; use ed25519::Pair; fn secret_for(who: &AccountId) -> Option { @@ -309,16 +309,13 @@ mod tests { } fn tx() -> UncheckedTransaction { - use native_runtime::codec::Slicable; - let transaction = Transaction { signed: one(), nonce: 0, function: Function::StakingTransfer(two(), 69), }; let signature = secret_for(&transaction.signed).unwrap() - .sign(&transaction.to_vec()) - .inner(); + .sign(&transaction.to_vec()); UncheckedTransaction { transaction, signature } } diff --git a/substrate/primitives/src/block.rs b/substrate/primitives/src/block.rs index 034bb64093..ca84ba6c88 100644 --- a/substrate/primitives/src/block.rs +++ b/substrate/primitives/src/block.rs @@ -120,6 +120,19 @@ pub struct Header { pub digest: Digest, } +impl Header { + /// Create a new instance with default fields except `number`, which is given as an argument. + pub fn from_block_number(number: Number) -> Self { + Header { + parent_hash: Default::default(), + number, + state_root: Default::default(), + transaction_root: Default::default(), + digest: Default::default(), + } + } +} + impl Slicable for Header { fn from_slice(value: &mut &[u8]) -> Option { Some(Header { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/genesismap.rs b/substrate/wasm-runtime/polkadot/src/runtime/genesismap.rs index a56d03bd04..a2da04427c 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/genesismap.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/genesismap.rs @@ -20,14 +20,15 @@ use std::collections::HashMap; use runtime_std::twox_128; use codec::{KeyedVec, Joiner}; use support::Hashable; -use primitives::{AccountID, BlockNumber, Block}; +use primitives::block::{Number as BlockNumber, Block}; +use primitives::AccountId; use runtime::staking::Balance; /// Configuration of a general Polkadot genesis block. pub struct GenesisConfig { - pub validators: Vec, - pub authorities: Vec, - pub balances: Vec<(AccountID, Balance)>, + pub validators: Vec, + pub authorities: Vec, + pub balances: Vec<(AccountId, Balance)>, pub block_time: u64, pub session_length: BlockNumber, pub sessions_per_era: BlockNumber, @@ -36,7 +37,7 @@ pub struct GenesisConfig { } impl GenesisConfig { - pub fn new_simple(authorities_validators: Vec, balance: Balance) -> Self { + pub fn new_simple(authorities_validators: Vec, balance: Balance) -> Self { GenesisConfig { validators: authorities_validators.clone(), authorities: authorities_validators.clone(), diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 262e001154..6a56698923 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -282,8 +282,8 @@ mod tests { let h = Header { parent_hash: H256([69u8; 32]), number: 1, - state_root: H256(hex!("2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db")), - transaction_root: H256(hex!("c4b361b976b3aa90f9f0cdd32f4afc80dd96f200145a687196388a00363c2235")), + state_root: H256(hex!("1ab2dbb7d4868a670b181327b0b6a58dc64b10cfb9876f737a5aa014b8da31e0")), + transaction_root: H256(hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")), digest: Digest { logs: vec![], }, }; @@ -306,10 +306,10 @@ mod tests { let mut t = new_test_ext(); let h = Header { - parent_hash: [69u8; 32], + parent_hash: H256([69u8; 32]), number: 1, - state_root: [0u8; 32], - transaction_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), + state_root: H256([0u8; 32]), + transaction_root: H256(hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")), digest: Digest { logs: vec![], }, }; 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 e5b92273481035ff15c3bc974578f9ebdf648035..d29436d0d42ab6c117ab733811222fb5594d658d 100644 GIT binary patch literal 66501 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 literal 65282 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 R+r22&V$An%i)gQQ{{RQKn^yn; literal 65360 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 Nb!$fM&4udA`2jeZ9ghG2 diff --git a/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm b/substrate/wasm-runtime/target/wasm32-unknown-unknown/release/runtime_test.wasm index 58bc742f46e1f30262e6e20c1b62cb08dac068fa..bbba7527d46aca944120e5cafdf8b353abece6ed 100644 GIT binary patch delta 121 zcmbQAKQ*75A+b1@k%57M(UWH)w~Q!DJrFP?FoH2-eF9@0Lju!A7i~sHmdOQ-nu;ty zr3`GWjEo#C92~4n99)b*z{(8+Oq`o{G0HPCPTqWr>3|aBo6WOTA2UvFP`75}oV*7_ KZvLUZoF4$+pBl~p delta 131 zcmbQ5KR=(FA+b1@k%57MF_3p6w~Q=nJqR!)FoH2-eF9@0Ljn^>gr&ZIqm4ErBj@A{ zMomRdpcV!;Rz^k+P7V%MCJt^!AYkQz0Vb}^n;7L88K-W(#B@N3@!jUhs*f2NxhI#Z S+W^T;>eh_ho8PG~=LY~?)*Yt+ From d2660900de2854b865f0f82f40a761b9891413f0 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 15:41:28 +0100 Subject: [PATCH 17/21] unclobber function changes --- substrate/Cargo.lock | 10 +-- substrate/ed25519/Cargo.toml | 2 +- substrate/primitives/Cargo.toml | 4 +- substrate/primitives/src/lib.rs | 2 + substrate/primitives/src/proposal.rs | 68 +++++++++++------- substrate/primitives/src/runtime_function.rs | 69 +++++++++---------- substrate/wasm-runtime/Cargo.lock | 10 +-- .../polkadot/src/runtime/governance.rs | 13 +++- 8 files changed, 94 insertions(+), 84 deletions(-) diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 75a256c839..8d46cf6766 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -197,7 +197,7 @@ version = "0.1.0" dependencies = [ "polkadot-primitives 0.1.0", "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1077,7 +1077,7 @@ dependencies = [ "polkadot-runtime-codec 0.1.0", "polkadot-serializer 0.1.0", "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1332,11 +1332,6 @@ name = "rustc-hex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rustc-hex" -version = "2.0.0" -source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc891d6dc2cc9009d7" - [[package]] name = "rustc-serialize" version = "0.3.24" @@ -1919,7 +1914,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" -"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" diff --git a/substrate/ed25519/Cargo.toml b/substrate/ed25519/Cargo.toml index a918468dd2..e6ba80d9a5 100644 --- a/substrate/ed25519/Cargo.toml +++ b/substrate/ed25519/Cargo.toml @@ -7,4 +7,4 @@ authors = ["Parity Technologies "] ring = "0.12" untrusted = "0.5" polkadot-primitives = { version = "0.1", path = "../primitives" } -rustc-hex = { git = "https://github.com/rphmeier/rustc-hex.git", version = "2.0", default_features = false } +rustc-hex = "1.0" diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index 6e5a4bd0c4..27c2e70f0e 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Parity Technologies "] [dependencies] crunchy = "0.1" fixed-hash = { git = "https://github.com/rphmeier/primitives.git", branch = "compile-for-wasm", default_features = false } -rustc-hex = { git = "https://github.com/rphmeier/rustc-hex.git", version = "2.0", default_features = false } +rustc-hex = { version = "1.0", optional = true } serde = { version = "1.0", default_features = false } serde_derive = { version = "1.0", optional = true } uint = { git = "https://github.com/rphmeier/primitives.git", branch = "compile-for-wasm" } @@ -26,7 +26,7 @@ std = [ "fixed-hash/std", "polkadot-runtime-codec/std", "serde/std", - "rustc-hex/std", + "rustc-hex", "twox-hash", "blake2-rfc", "serde_derive", diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index 95c54c64d2..7b7da0c924 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -21,7 +21,9 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] +#[cfg(feature = "std")] extern crate rustc_hex; + extern crate serde; extern crate byteorder; diff --git a/substrate/primitives/src/proposal.rs b/substrate/primitives/src/proposal.rs index 4957a3dee6..65e85fa641 100644 --- a/substrate/primitives/src/proposal.rs +++ b/substrate/primitives/src/proposal.rs @@ -28,36 +28,41 @@ use codec::Slicable; #[repr(u8)] enum InternalFunctionId { /// Set the system's code. - SystemSetCode = 0, - /// Set the number of sessions per era. - StakingSetSessionsPerEra = 1, - /// Set the minimum bonding duration for staking. - StakingSetBondingDuration = 2, - /// Set the validator count for staking. - StakingSetValidatorCount = 3, - /// Set the per-mille of validator approval required for governance changes. - GovernanceSetApprovalPpmRequired = 4, + SystemSetCode = 0x00, + /// Set the session length. - SessionSetLength = 5, + SessionSetLength = 0x10, + /// Force a new session. + SessionForceNewSession = 0x11, + + /// Set the number of sessions per era. + StakingSetSessionsPerEra = 0x20, + /// Set the minimum bonding duration for staking. + StakingSetBondingDuration = 0x21, + /// Set the validator count for staking. + StakingSetValidatorCount = 0x22, + /// Force a new staking era. + StakingForceNewEra = 0x23, + + /// Set the per-mille of validator approval required for governance changes. + GovernanceSetApprovalPpmRequired = 0x30, + } impl InternalFunctionId { /// Derive `Some` value from a `u8`, or `None` if it's invalid. fn from_u8(value: u8) -> Option { - use self::*; let functions = [ InternalFunctionId::SystemSetCode, + InternalFunctionId::SessionSetLength, + InternalFunctionId::SessionForceNewSession, InternalFunctionId::StakingSetSessionsPerEra, InternalFunctionId::StakingSetBondingDuration, InternalFunctionId::StakingSetValidatorCount, + InternalFunctionId::StakingForceNewEra, InternalFunctionId::GovernanceSetApprovalPpmRequired, - InternalFunctionId::SessionSetLength ]; - if (value as usize) < functions.len() { - Some(functions[value as usize]) - } else { - None - } + functions.iter().map(|&f| f).find(|&f| value == f as u8) } } @@ -67,16 +72,21 @@ impl InternalFunctionId { pub enum InternalFunction { /// Set the system's code. SystemSetCode(Vec), + /// Set the session length. + SessionSetLength(BlockNumber), + /// Force a new session. + SessionForceNewSession, /// Set the number of sessions per era. StakingSetSessionsPerEra(BlockNumber), /// Set the minimum bonding duration for staking. StakingSetBondingDuration(BlockNumber), /// Set the validator count for staking. StakingSetValidatorCount(u32), + /// Force a new staking era. + StakingForceNewEra, /// Set the per-mille of validator approval required for governance changes. GovernanceSetApprovalPpmRequired(u32), - /// Set the session length. - SessionSetLength(BlockNumber), + } /// An internal function. @@ -93,16 +103,18 @@ impl Slicable for Proposal { let function = match id { InternalFunctionId::SystemSetCode => InternalFunction::SystemSetCode(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::SessionSetLength => + InternalFunction::SessionSetLength(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::SessionForceNewSession => InternalFunction::SessionForceNewSession, InternalFunctionId::StakingSetSessionsPerEra => InternalFunction::StakingSetSessionsPerEra(try_opt!(Slicable::from_slice(value))), InternalFunctionId::StakingSetBondingDuration => InternalFunction::StakingSetBondingDuration(try_opt!(Slicable::from_slice(value))), InternalFunctionId::StakingSetValidatorCount => InternalFunction::StakingSetValidatorCount(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::StakingForceNewEra => InternalFunction::StakingForceNewEra, InternalFunctionId::GovernanceSetApprovalPpmRequired => InternalFunction::GovernanceSetApprovalPpmRequired(try_opt!(Slicable::from_slice(value))), - InternalFunctionId::SessionSetLength => - InternalFunction::SessionSetLength(try_opt!(Slicable::from_slice(value))), }; Some(Proposal { function }) @@ -115,6 +127,13 @@ impl Slicable for Proposal { (InternalFunctionId::SystemSetCode as u8).as_slice_then(|s| v.extend(s)); data.as_slice_then(|s| v.extend(s)); } + InternalFunction::SessionSetLength(ref data) => { + (InternalFunctionId::SessionSetLength as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + InternalFunction::SessionForceNewSession => { + (InternalFunctionId::SessionForceNewSession as u8).as_slice_then(|s| v.extend(s)); + } InternalFunction::StakingSetSessionsPerEra(ref data) => { (InternalFunctionId::StakingSetSessionsPerEra as u8).as_slice_then(|s| v.extend(s)); data.as_slice_then(|s| v.extend(s)); @@ -127,14 +146,13 @@ impl Slicable for Proposal { (InternalFunctionId::StakingSetValidatorCount as u8).as_slice_then(|s| v.extend(s)); data.as_slice_then(|s| v.extend(s)); } + InternalFunction::StakingForceNewEra => { + (InternalFunctionId::StakingForceNewEra as u8).as_slice_then(|s| v.extend(s)); + } InternalFunction::GovernanceSetApprovalPpmRequired(ref data) => { (InternalFunctionId::GovernanceSetApprovalPpmRequired as u8).as_slice_then(|s| v.extend(s)); data.as_slice_then(|s| v.extend(s)); } - InternalFunction::SessionSetLength(ref data) => { - (InternalFunctionId::SessionSetLength as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } } v diff --git a/substrate/primitives/src/runtime_function.rs b/substrate/primitives/src/runtime_function.rs index 4c51411f4a..9ec5da029c 100644 --- a/substrate/primitives/src/runtime_function.rs +++ b/substrate/primitives/src/runtime_function.rs @@ -25,35 +25,30 @@ use codec::Slicable; #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] #[repr(u8)] enum FunctionId { - /// Staking subsystem: begin staking. - StakingStake = 0, - /// Staking subsystem: stop staking. - StakingUnstake = 1, - /// Staking subsystem: transfer stake. - StakingTransfer = 2, - /// Set temporary session key as a validator. - SessionSetKey = 3, /// Set the timestamp. - TimestampSet = 4, + TimestampSet = 0x00, + /// Set temporary session key as a validator. + SessionSetKey = 0x10, + /// Staking subsystem: begin staking. + StakingStake = 0x20, + /// Staking subsystem: stop staking. + StakingUnstake = 0x21, + /// Staking subsystem: transfer stake. + StakingTransfer = 0x22, /// Make a proposal for the governance system. - GovernancePropose = 5, + GovernancePropose = 0x30, /// Approve a proposal for the governance system. - GovernanceApprove = 6, + GovernanceApprove = 0x31, } impl FunctionId { /// Derive `Some` value from a `u8`, or `None` if it's invalid. fn from_u8(value: u8) -> Option { - match value { - 0 => Some(FunctionId::StakingStake), - 1 => Some(FunctionId::StakingUnstake), - 2 => Some(FunctionId::StakingTransfer), - 3 => Some(FunctionId::SessionSetKey), - 4 => Some(FunctionId::TimestampSet), - 5 => Some(FunctionId::GovernancePropose), - 6 => Some(FunctionId::GovernanceApprove), - _ => None, - } + use self::*; + let functions = [FunctionId::StakingStake, FunctionId::StakingUnstake, + FunctionId::StakingTransfer, FunctionId::SessionSetKey, FunctionId::TimestampSet, + FunctionId::GovernancePropose, FunctionId::GovernanceApprove]; + functions.iter().map(|&f| f).find(|&f| value == f as u8) } } @@ -61,16 +56,16 @@ impl FunctionId { #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub enum Function { + /// Set the timestamp. + TimestampSet(::Timestamp), + /// Set temporary session key as a validator. + SessionSetKey(::SessionKey), /// Staking subsystem: begin staking. StakingStake, /// Staking subsystem: stop staking. StakingUnstake, /// Staking subsystem: transfer stake. StakingTransfer(::AccountId, ::Balance), - /// Set temporary session key as a validator. - SessionSetKey(::SessionKey), - /// Set the timestamp. - TimestampSet(::Timestamp), /// Make a proposal for the governance system. GovernancePropose(::proposal::Proposal), /// Approve a proposal for the governance system. @@ -81,16 +76,16 @@ impl Slicable for Function { fn from_slice(value: &mut &[u8]) -> Option { let id = try_opt!(u8::from_slice(value).and_then(FunctionId::from_u8)); Some(match id { + FunctionId::TimestampSet => + Function::TimestampSet(try_opt!(Slicable::from_slice(value))), + FunctionId::SessionSetKey => + Function::SessionSetKey(try_opt!(Slicable::from_slice(value))), FunctionId::StakingStake => Function::StakingStake, FunctionId::StakingUnstake => Function::StakingUnstake, FunctionId::StakingTransfer => Function::StakingTransfer( try_opt!(Slicable::from_slice(value)), try_opt!(Slicable::from_slice(value)), ), - FunctionId::SessionSetKey => - Function::SessionSetKey(try_opt!(Slicable::from_slice(value))), - FunctionId::TimestampSet => - Function::TimestampSet(try_opt!(Slicable::from_slice(value))), FunctionId::GovernancePropose => Function::GovernancePropose(try_opt!(Slicable::from_slice(value))), FunctionId::GovernanceApprove => @@ -101,6 +96,14 @@ impl Slicable for Function { fn to_vec(&self) -> Vec { let mut v = Vec::new(); match *self { + Function::TimestampSet(ref data) => { + (FunctionId::TimestampSet as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + Function::SessionSetKey(ref data) => { + (FunctionId::SessionSetKey as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } Function::StakingStake => { (FunctionId::StakingStake as u8).as_slice_then(|s| v.extend(s)); } @@ -112,14 +115,6 @@ impl Slicable for Function { to.as_slice_then(|s| v.extend(s)); amount.as_slice_then(|s| v.extend(s)); } - Function::SessionSetKey(ref data) => { - (FunctionId::SessionSetKey as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } - Function::TimestampSet(ref data) => { - (FunctionId::TimestampSet as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } Function::GovernancePropose(ref data) => { (FunctionId::GovernancePropose as u8).as_slice_then(|s| v.extend(s)); data.as_slice_then(|s| v.extend(s)); diff --git a/substrate/wasm-runtime/Cargo.lock b/substrate/wasm-runtime/Cargo.lock index 3373ebcc9b..71665b12ce 100644 --- a/substrate/wasm-runtime/Cargo.lock +++ b/substrate/wasm-runtime/Cargo.lock @@ -94,7 +94,7 @@ version = "0.1.0" dependencies = [ "polkadot-primitives 0.1.0", "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -384,7 +384,7 @@ dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", "polkadot-runtime-codec 0.1.0", - "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -568,11 +568,6 @@ name = "rustc-hex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rustc-hex" -version = "2.0.0" -source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc891d6dc2cc9009d7" - [[package]] name = "rustc_version" version = "0.2.1" @@ -830,7 +825,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" "checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" -"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index b009e3597a..ad71a7a236 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -117,6 +117,12 @@ pub mod internal { InternalFunction::SystemSetCode(code) => { system::privileged::set_code(&code); } + InternalFunction::SessionSetLength(value) => { + session::privileged::set_length(value); + } + InternalFunction::SessionForceNewSession => { + session::privileged::force_new_session(); + } InternalFunction::StakingSetSessionsPerEra(value) => { staking::privileged::set_sessions_per_era(value); } @@ -126,12 +132,13 @@ pub mod internal { InternalFunction::StakingSetValidatorCount(value) => { staking::privileged::set_validator_count(value); } + InternalFunction::StakingForceNewEra => { + staking::privileged::force_new_era() + } InternalFunction::GovernanceSetApprovalPpmRequired(value) => { self::privileged::set_approval_ppm_required(value); } - InternalFunction::SessionSetLength(value) => { - session::privileged::set_length(value); - } + } } } From 4378ce7887b22db104f5b0127e984a434fb93f05 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 16:35:19 +0100 Subject: [PATCH 18/21] fix tests and review grumbles --- substrate/Cargo.lock | 8 +- substrate/client/src/genesis.rs | 15 +- substrate/executor/src/native_executor.rs | 12 +- substrate/primitives/Cargo.toml | 4 +- substrate/primitives/src/lib.rs | 4 +- substrate/primitives/src/runtime_function.rs | 10 +- substrate/primitives/src/tests.rs | 233 ++++++++++++++++++ substrate/wasm-runtime/Cargo.lock | 8 +- .../polkadot/src/runtime/system.rs | 31 ++- .../release/runtime_polkadot.compact.wasm | Bin 66501 -> 67849 bytes .../release/runtime_polkadot.wasm | Bin 66580 -> 67928 bytes 11 files changed, 285 insertions(+), 40 deletions(-) create mode 100644 substrate/primitives/src/tests.rs diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index 8d46cf6766..5261f91b80 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -1077,7 +1077,7 @@ dependencies = [ "polkadot-runtime-codec 0.1.0", "polkadot-serializer 0.1.0", "pretty_assertions 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1332,6 +1332,11 @@ name = "rustc-hex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-hex" +version = "2.0.0" +source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc891d6dc2cc9009d7" + [[package]] name = "rustc-serialize" version = "0.3.24" @@ -1914,6 +1919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" +"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" diff --git a/substrate/client/src/genesis.rs b/substrate/client/src/genesis.rs index 3a8a287e27..9a49df5e08 100644 --- a/substrate/client/src/genesis.rs +++ b/substrate/client/src/genesis.rs @@ -18,17 +18,16 @@ use std::collections::HashMap; use primitives::block::{Block, Header}; -use primitives::H256; use triehash::trie_root; /// Create a genesis block, given the initial storage. pub fn construct_genesis_block(storage: &HashMap, Vec>) -> Block { - let state_root = H256(trie_root(storage.clone().into_iter()).0); + let state_root = trie_root(storage.clone().into_iter()).0.into(); let header = Header { parent_hash: Default::default(), number: 0, state_root, - transaction_root: H256(trie_root(vec![].into_iter()).0), + transaction_root: trie_root(vec![].into_iter()).0.into(), digest: Default::default(), }; Block { @@ -47,7 +46,7 @@ mod tests { use state_machine::OverlayedChanges; use state_machine::backend::InMemory; use polkadot_executor::executor; - use primitives::{AccountId, Hash, H256}; + use primitives::{AccountId, Hash}; use primitives::block::{Number as BlockNumber, Header, Digest}; use primitives::runtime_function::Function; use primitives::transaction::{UncheckedTransaction, Transaction}; @@ -72,7 +71,7 @@ mod tests { UncheckedTransaction { transaction, signature } }).collect::>(); - let transaction_root = H256(ordered_trie_root(transactions.iter().map(Slicable::to_vec)).0); + let transaction_root = ordered_trie_root(transactions.iter().map(Slicable::to_vec)).0.into(); let mut header = Header { parent_hash, @@ -105,7 +104,7 @@ mod tests { ).unwrap(); header = Header::from_slice(&mut &ret_data[..]).unwrap(); - (vec![].join(&Block { header, transactions }), H256(hash)) + (vec![].join(&Block { header, transactions }), hash.into()) } fn block1(genesis_hash: Hash, backend: &InMemory) -> (Vec, Hash) { @@ -113,7 +112,7 @@ mod tests { backend, 1, genesis_hash, - H256(hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c")), + hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(), vec![Transaction { signed: one(), nonce: 0, @@ -128,7 +127,7 @@ mod tests { vec![one(), two()], 1000 ).genesis_map(); let block = construct_genesis_block(&storage); - let genesis_hash = H256(block.header.blake2_256()); + let genesis_hash = block.header.blake2_256().into(); storage.extend(additional_storage_with_genesis(&block).into_iter()); let mut overlay = OverlayedChanges::default(); diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index df6e64908f..5e0bdaa7fb 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -46,7 +46,7 @@ mod tests { use native_runtime::support::{one, two, Hashable}; use native_runtime::runtime::staking::balance; use state_machine::TestExternalities; - use primitives::{twox_128, Hash, H256}; + use primitives::{twox_128, Hash}; use primitives::runtime_function::Function; use primitives::block::{Header, Number as BlockNumber, Block, Digest}; use primitives::transaction::{Transaction, UncheckedTransaction}; @@ -167,7 +167,7 @@ mod tests { UncheckedTransaction { transaction, signature } }).collect::>(); - let transaction_root = H256(ordered_trie_root(transactions.iter().map(Slicable::to_vec)).0); + let transaction_root = ordered_trie_root(transactions.iter().map(Slicable::to_vec)).0.into(); let header = Header { parent_hash, @@ -178,14 +178,14 @@ mod tests { }; let hash = header.blake2_256(); - (Block { header, transactions }.to_vec(), H256(hash)) + (Block { header, transactions }.to_vec(), hash.into()) } fn block1() -> (Vec, Hash) { construct_block( 1, - H256([69u8; 32]), - H256(hex!("2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db")), + [69u8; 32].into(), + hex!("2481853da20b9f4322f34650fea5f240dcbfb266d02db94bfa0153c31f4a29db").into(), vec![Transaction { signed: one(), nonce: 0, @@ -198,7 +198,7 @@ mod tests { construct_block( 2, block1().1, - H256(hex!("2cdbbf9bd766c2286a5f4091c131fe161addd060ba6fc041b3419089f4601bda")), + hex!("e2ba57cfb94b870ea6670b012b49dc33cbb70e3aa8d36cf54dfa5e4e69cd0778").into(), vec![ Transaction { signed: two(), diff --git a/substrate/primitives/Cargo.toml b/substrate/primitives/Cargo.toml index 27c2e70f0e..6e5a4bd0c4 100644 --- a/substrate/primitives/Cargo.toml +++ b/substrate/primitives/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Parity Technologies "] [dependencies] crunchy = "0.1" fixed-hash = { git = "https://github.com/rphmeier/primitives.git", branch = "compile-for-wasm", default_features = false } -rustc-hex = { version = "1.0", optional = true } +rustc-hex = { git = "https://github.com/rphmeier/rustc-hex.git", version = "2.0", default_features = false } serde = { version = "1.0", default_features = false } serde_derive = { version = "1.0", optional = true } uint = { git = "https://github.com/rphmeier/primitives.git", branch = "compile-for-wasm" } @@ -26,7 +26,7 @@ std = [ "fixed-hash/std", "polkadot-runtime-codec/std", "serde/std", - "rustc-hex", + "rustc-hex/std", "twox-hash", "blake2-rfc", "serde_derive", diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index 7b7da0c924..3ecc0a77c0 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -21,7 +21,6 @@ #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), feature(alloc))] -#[cfg(feature = "std")] extern crate rustc_hex; extern crate serde; @@ -77,6 +76,9 @@ pub mod transaction; pub mod uint; pub mod validator; +#[cfg(test)] +mod tests; + #[cfg(feature = "std")] pub mod hashing; diff --git a/substrate/primitives/src/runtime_function.rs b/substrate/primitives/src/runtime_function.rs index 9ec5da029c..48e5afdc61 100644 --- a/substrate/primitives/src/runtime_function.rs +++ b/substrate/primitives/src/runtime_function.rs @@ -82,10 +82,12 @@ impl Slicable for Function { Function::SessionSetKey(try_opt!(Slicable::from_slice(value))), FunctionId::StakingStake => Function::StakingStake, FunctionId::StakingUnstake => Function::StakingUnstake, - FunctionId::StakingTransfer => Function::StakingTransfer( - try_opt!(Slicable::from_slice(value)), - try_opt!(Slicable::from_slice(value)), - ), + FunctionId::StakingTransfer => { + let to = try_opt!(Slicable::from_slice(value)); + let amount = try_opt!(Slicable::from_slice(value)); + + Function::StakingTransfer(to, amount) + } FunctionId::GovernancePropose => Function::GovernancePropose(try_opt!(Slicable::from_slice(value))), FunctionId::GovernanceApprove => diff --git a/substrate/primitives/src/tests.rs b/substrate/primitives/src/tests.rs new file mode 100644 index 0000000000..311f596400 --- /dev/null +++ b/substrate/primitives/src/tests.rs @@ -0,0 +1,233 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Tests. + +use codec::Slicable; + +use ::AccountId; +use block::{Block, Header, Digest, Log}; +use runtime_function::Function; +use transaction::{UncheckedTransaction, Transaction}; + +#[test] +fn serialise_transaction_works() { + let one: AccountId = [1u8; 32]; + let two: AccountId = [2u8; 32]; + let tx = Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransfer(two, 69), + }; + + let serialised = tx.to_vec(); + assert_eq!(serialised, vec![ + 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 69, 0, 0, 0, 0, 0, 0, 0, + 34, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0 + ]); +} + +#[test] +fn deserialise_transaction_works() { + let one: AccountId = [1u8; 32]; + let two: AccountId = [2u8; 32]; + let tx = Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransfer(two, 69), + }; + + let data = [ + 1u8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 69, 0, 0, 0, 0, 0, 0, 0, + 34, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0 + ]; + let deserialised = Transaction::from_slice(&mut &data[..]).unwrap(); + assert_eq!(deserialised, tx); +} + +#[test] +fn serialise_header_works() { + let h = Header { + parent_hash: [4u8; 32].into(), + number: 42, + state_root: [5u8; 32].into(), + transaction_root: [6u8; 32].into(), + digest: Digest { logs: vec![ Log(b"one log".to_vec()), Log(b"another log".to_vec()) ], }, + }; + let serialised = h.to_vec(); + assert_eq!(serialised, vec![ + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 2, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 + ]); +} + +#[test] +fn deserialise_header_works() { + let h = Header { + parent_hash: [4u8; 32].into(), + number: 42, + state_root: [5u8; 32].into(), + transaction_root: [6u8; 32].into(), + digest: Digest { logs: vec![ Log(b"one log".to_vec()), Log(b"another log".to_vec()) ], }, + }; + let data = [ + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 2, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103 + ]; + let deserialised = Header::from_slice(&mut &data[..]).unwrap(); + assert_eq!(deserialised, h); +} + +#[test] +fn serialise_block_works() { + let one: AccountId = [1u8; 32]; + let two: AccountId = [2u8; 32]; + let tx1 = UncheckedTransaction { + transaction: Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransfer(two, 69), + }, + signature: [1u8; 64].into(), + }; + let tx2 = UncheckedTransaction { + transaction: Transaction { + signed: two.clone(), + nonce: 42, + function: Function::StakingStake, + }, + signature: [2u8; 64].into(), + }; + let h = Header { + parent_hash: [4u8; 32].into(), + number: 42, + state_root: [5u8; 32].into(), + transaction_root: [6u8; 32].into(), + digest: Digest { logs: vec![ Log(b"one log".to_vec()), Log(b"another log".to_vec()) ], }, + }; + let b = Block { + header: h, + transactions: vec![tx1, tx2], + }; + let serialised = b.to_vec(); + assert_eq!(serialised, vec![ + // header + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 2, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, + // transactions + 2, 0, 0, 0, + // tx1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 69, 0, 0, 0, 0, 0, 0, 0, + 34, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + // tx2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 42, 0, 0, 0, 0, 0, 0, 0, + 32, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + ]); +} + +#[test] +fn deserialise_block_works() { + let one: AccountId = [1u8; 32]; + let two: AccountId = [2u8; 32]; + let tx1 = UncheckedTransaction { + transaction: Transaction { + signed: one.clone(), + nonce: 69, + function: Function::StakingTransfer(two, 69), + }, + signature: [1u8; 64].into(), + }; + let tx2 = UncheckedTransaction { + transaction: Transaction { + signed: two.clone(), + nonce: 42, + function: Function::StakingStake, + }, + signature: [2u8; 64].into(), + }; + let h = Header { + parent_hash: [4u8; 32].into(), + number: 42, + state_root: [5u8; 32].into(), + transaction_root: [6u8; 32].into(), + digest: Digest { logs: vec![ Log(b"one log".to_vec()), Log(b"another log".to_vec()) ], }, + }; + let b = Block { + header: h, + transactions: vec![tx1, tx2], + }; + let data = [ + // header + 4u8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 42, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 2, 0, 0, 0, + 7, 0, 0, 0, + 111, 110, 101, 32, 108, 111, 103, + 11, 0, 0, 0, + 97, 110, 111, 116, 104, 101, 114, 32, 108, 111, 103, + // transactions + 2, 0, 0, 0, + // tx1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 69, 0, 0, 0, 0, 0, 0, 0, + 34, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 69, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + // tx2 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 42, 0, 0, 0, 0, 0, 0, 0, + 32, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + ]; + let deserialised = Block::from_slice(&mut &data[..]).unwrap(); + assert_eq!(deserialised, b); +} diff --git a/substrate/wasm-runtime/Cargo.lock b/substrate/wasm-runtime/Cargo.lock index 71665b12ce..287249192e 100644 --- a/substrate/wasm-runtime/Cargo.lock +++ b/substrate/wasm-runtime/Cargo.lock @@ -384,7 +384,7 @@ dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "fixed-hash 0.1.3 (git+https://github.com/rphmeier/primitives.git?branch=compile-for-wasm)", "polkadot-runtime-codec 0.1.0", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -568,6 +568,11 @@ name = "rustc-hex" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rustc-hex" +version = "2.0.0" +source = "git+https://github.com/rphmeier/rustc-hex.git#ee2ec40b9062ac7769ccb9dc891d6dc2cc9009d7" + [[package]] name = "rustc_version" version = "0.2.1" @@ -825,6 +830,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" "checksum rlp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "babe6fce20c0ca9b1582998734c4569082d0ad08e43772a1c6c40aef4f106ef9" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" +"checksum rustc-hex 2.0.0 (git+https://github.com/rphmeier/rustc-hex.git)" = "" "checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 6a56698923..22f72fff79 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -21,7 +21,7 @@ use runtime_std::prelude::*; use runtime_std::{mem, storage_root, enumerated_trie_root}; use codec::{KeyedVec, Slicable}; use support::{Hashable, storage, with_env}; -use primitives::{AccountId, Hash, H256, TxOrder}; +use primitives::{AccountId, Hash, TxOrder}; use primitives::block::{Block, Header, Number as BlockNumber}; use primitives::transaction::UncheckedTransaction; use primitives::runtime_function::Function; @@ -78,7 +78,7 @@ pub mod internal { // check transaction trie root represents the transactions. let txs = block.transactions.iter().map(Slicable::to_vec).collect::>(); let txs = txs.iter().map(Vec::as_slice).collect::>(); - let txs_root = H256(enumerated_trie_root(&txs)); + let txs_root = enumerated_trie_root(&txs).into(); debug_assert_hash(&header.transaction_root, &txs_root); assert!(header.transaction_root == txs_root, "Transaction trie root must be valid."); @@ -94,7 +94,7 @@ pub mod internal { final_checks(&block); // check storage root. - let storage_root = H256(storage_root()); + let storage_root = storage_root().into(); debug_assert_hash(&header.state_root, &storage_root); assert!(header.state_root == storage_root, "Storage root must match that calculated."); @@ -125,7 +125,7 @@ pub mod internal { staking::internal::check_new_era(); session::internal::check_rotate_session(); - header.state_root = H256(storage_root()); + header.state_root = storage_root().into(); with_env(|e| { mem::swap(&mut header.digest, &mut e.digest); }); @@ -218,7 +218,6 @@ mod tests { use primitives::transaction::{UncheckedTransaction, Transaction}; use primitives::runtime_function::Function; use primitives::block::{Header, Digest}; - use primitives::hash::{H256, H512}; use runtime::staking; #[test] @@ -236,10 +235,8 @@ mod tests { nonce: 0, function: Function::StakingTransfer(two, 69), }, - signature: "b543b41e4b7a0270eddf57ed6c435df04bb63f71c79f6ae2530ab26c734bb4e8cd57b1c190c41d5791bcdea66a16c7339b1e883e5d0538ea2d9acea800d60a00".parse().unwrap(), + signature: "5f9832c5a4a39e2dd4a3a0c5b400e9836beb362cb8f7d845a8291a2ae6fe366612e080e4acd0b5a75c3d0b6ee69614a68fb63698c1e76bf1f2dcd8fa617ddf05".parse().unwrap(), }; - // tx: 2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000228000000d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000 - // sig: b543b41e4b7a0270eddf57ed6c435df04bb63f71c79f6ae2530ab26c734bb4e8cd57b1c190c41d5791bcdea66a16c7339b1e883e5d0538ea2d9acea800d60a00 with_externalities(&mut t, || { internal::execute_transaction(tx, Header::from_block_number(1)); @@ -280,10 +277,10 @@ mod tests { let mut t = new_test_ext(); let h = Header { - parent_hash: H256([69u8; 32]), + parent_hash: [69u8; 32].into(), number: 1, - state_root: H256(hex!("1ab2dbb7d4868a670b181327b0b6a58dc64b10cfb9876f737a5aa014b8da31e0")), - transaction_root: H256(hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")), + state_root: hex!("1ab2dbb7d4868a670b181327b0b6a58dc64b10cfb9876f737a5aa014b8da31e0").into(), + transaction_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), digest: Digest { logs: vec![], }, }; @@ -306,10 +303,10 @@ mod tests { let mut t = new_test_ext(); let h = Header { - parent_hash: H256([69u8; 32]), + parent_hash: [69u8; 32].into(), number: 1, - state_root: H256([0u8; 32]), - transaction_root: H256(hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")), + state_root: [0u8; 32].into(), + transaction_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), digest: Digest { logs: vec![], }, }; @@ -332,10 +329,10 @@ mod tests { let mut t = new_test_ext(); let h = Header { - parent_hash: H256([69u8; 32]), + parent_hash: [69u8; 32].into(), number: 1, - state_root: H256(hex!("1ab2dbb7d4868a670b181327b0b6a58dc64b10cfb9876f737a5aa014b8da31e0")), - transaction_root: H256([0u8; 32]), + state_root: hex!("1ab2dbb7d4868a670b181327b0b6a58dc64b10cfb9876f737a5aa014b8da31e0").into(), + transaction_root: [0u8; 32].into(), digest: Digest { logs: vec![], }, }; 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 d29436d0d42ab6c117ab733811222fb5594d658d..669fb901a1e40b239ce3879e9156336e82058abc 100644 GIT binary patch delta 18019 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 delta 16966 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 HlTH19zuj)_ delta 16740 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 From 6aaf446352abc963019f8faa9fb00f525e4253f4 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 16:42:32 +0100 Subject: [PATCH 19/21] move function and proposal types to transaction module --- substrate/client/src/genesis.rs | 3 +- substrate/executor/src/native_executor.rs | 28 +- substrate/executor/src/wasm_executor.rs | 3 +- substrate/primitives/src/lib.rs | 2 - substrate/primitives/src/proposal.rs | 164 ----------- substrate/primitives/src/runtime_function.rs | 136 --------- substrate/primitives/src/tests.rs | 3 +- substrate/primitives/src/transaction.rs | 260 +++++++++++++++++- .../polkadot/src/runtime/governance.rs | 6 +- .../polkadot/src/runtime/system.rs | 6 +- .../polkadot/src/support/storage.rs | 2 +- 11 files changed, 289 insertions(+), 324 deletions(-) delete mode 100644 substrate/primitives/src/proposal.rs delete mode 100644 substrate/primitives/src/runtime_function.rs diff --git a/substrate/client/src/genesis.rs b/substrate/client/src/genesis.rs index 9a49df5e08..ebd8326b44 100644 --- a/substrate/client/src/genesis.rs +++ b/substrate/client/src/genesis.rs @@ -48,8 +48,7 @@ mod tests { use polkadot_executor::executor; use primitives::{AccountId, Hash}; use primitives::block::{Number as BlockNumber, Header, Digest}; - use primitives::runtime_function::Function; - use primitives::transaction::{UncheckedTransaction, Transaction}; + use primitives::transaction::{UncheckedTransaction, Transaction, Function}; use primitives::contract::CallData; use ed25519::Pair; diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 5e0bdaa7fb..176b4240d2 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -1,10 +1,27 @@ -use std::panic::catch_unwind; -use primitives::contract::CallData; -use state_machine::{Externalities, CodeExecutor}; +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + use error::{Error, ErrorKind, Result}; -use wasm_executor::WasmExecutor; use native_runtime as runtime; +use primitives::contract::CallData; use runtime_std; +use state_machine::{Externalities, CodeExecutor}; +use wasm_executor::WasmExecutor; + +use std::panic::catch_unwind; pub struct NativeExecutor; @@ -47,9 +64,8 @@ mod tests { use native_runtime::runtime::staking::balance; use state_machine::TestExternalities; use primitives::{twox_128, Hash}; - use primitives::runtime_function::Function; use primitives::block::{Header, Number as BlockNumber, Block, Digest}; - use primitives::transaction::{Transaction, UncheckedTransaction}; + use primitives::transaction::{Transaction, UncheckedTransaction, Function}; use ed25519::Pair; const BLOATY_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index e409d6ab94..520557edd4 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -294,9 +294,8 @@ mod tests { use native_runtime::runtime::staking::balance; use state_machine::TestExternalities; use primitives::{twox_128, AccountId}; - use primitives::runtime_function::Function; use primitives::block::Header; - use primitives::transaction::{Transaction, UncheckedTransaction}; + use primitives::transaction::{Transaction, UncheckedTransaction, Function}; use runtime_std; use ed25519::Pair; diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index 3ecc0a77c0..32cb18f8e1 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -70,8 +70,6 @@ pub mod contract; pub mod hash; pub mod hexdisplay; pub mod parachain; -pub mod proposal; -pub mod runtime_function; pub mod transaction; pub mod uint; pub mod validator; diff --git a/substrate/primitives/src/proposal.rs b/substrate/primitives/src/proposal.rs deleted file mode 100644 index 65e85fa641..0000000000 --- a/substrate/primitives/src/proposal.rs +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Proposals for relay-chain governance. -//! -//! This describes a combination of a function ID and data that can be used to call into -//! an internal function. - -use bytes::Vec; -use block::Number as BlockNumber; -use codec::Slicable; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[repr(u8)] -enum InternalFunctionId { - /// Set the system's code. - SystemSetCode = 0x00, - - /// Set the session length. - SessionSetLength = 0x10, - /// Force a new session. - SessionForceNewSession = 0x11, - - /// Set the number of sessions per era. - StakingSetSessionsPerEra = 0x20, - /// Set the minimum bonding duration for staking. - StakingSetBondingDuration = 0x21, - /// Set the validator count for staking. - StakingSetValidatorCount = 0x22, - /// Force a new staking era. - StakingForceNewEra = 0x23, - - /// Set the per-mille of validator approval required for governance changes. - GovernanceSetApprovalPpmRequired = 0x30, - -} - -impl InternalFunctionId { - /// Derive `Some` value from a `u8`, or `None` if it's invalid. - fn from_u8(value: u8) -> Option { - let functions = [ - InternalFunctionId::SystemSetCode, - InternalFunctionId::SessionSetLength, - InternalFunctionId::SessionForceNewSession, - InternalFunctionId::StakingSetSessionsPerEra, - InternalFunctionId::StakingSetBondingDuration, - InternalFunctionId::StakingSetValidatorCount, - InternalFunctionId::StakingForceNewEra, - InternalFunctionId::GovernanceSetApprovalPpmRequired, - ]; - functions.iter().map(|&f| f).find(|&f| value == f as u8) - } -} - -/// Internal functions that can be dispatched to. -#[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub enum InternalFunction { - /// Set the system's code. - SystemSetCode(Vec), - /// Set the session length. - SessionSetLength(BlockNumber), - /// Force a new session. - SessionForceNewSession, - /// Set the number of sessions per era. - StakingSetSessionsPerEra(BlockNumber), - /// Set the minimum bonding duration for staking. - StakingSetBondingDuration(BlockNumber), - /// Set the validator count for staking. - StakingSetValidatorCount(u32), - /// Force a new staking era. - StakingForceNewEra, - /// Set the per-mille of validator approval required for governance changes. - GovernanceSetApprovalPpmRequired(u32), - -} - -/// An internal function. -#[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct Proposal { - /// The privileged function to call. - pub function: InternalFunction, -} - -impl Slicable for Proposal { - fn from_slice(value: &mut &[u8]) -> Option { - let id = try_opt!(u8::from_slice(value).and_then(InternalFunctionId::from_u8)); - let function = match id { - InternalFunctionId::SystemSetCode => - InternalFunction::SystemSetCode(try_opt!(Slicable::from_slice(value))), - InternalFunctionId::SessionSetLength => - InternalFunction::SessionSetLength(try_opt!(Slicable::from_slice(value))), - InternalFunctionId::SessionForceNewSession => InternalFunction::SessionForceNewSession, - InternalFunctionId::StakingSetSessionsPerEra => - InternalFunction::StakingSetSessionsPerEra(try_opt!(Slicable::from_slice(value))), - InternalFunctionId::StakingSetBondingDuration => - InternalFunction::StakingSetBondingDuration(try_opt!(Slicable::from_slice(value))), - InternalFunctionId::StakingSetValidatorCount => - InternalFunction::StakingSetValidatorCount(try_opt!(Slicable::from_slice(value))), - InternalFunctionId::StakingForceNewEra => InternalFunction::StakingForceNewEra, - InternalFunctionId::GovernanceSetApprovalPpmRequired => - InternalFunction::GovernanceSetApprovalPpmRequired(try_opt!(Slicable::from_slice(value))), - }; - - Some(Proposal { function }) - } - - fn to_vec(&self) -> Vec { - let mut v = Vec::new(); - match self.function { - InternalFunction::SystemSetCode(ref data) => { - (InternalFunctionId::SystemSetCode as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } - InternalFunction::SessionSetLength(ref data) => { - (InternalFunctionId::SessionSetLength as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } - InternalFunction::SessionForceNewSession => { - (InternalFunctionId::SessionForceNewSession as u8).as_slice_then(|s| v.extend(s)); - } - InternalFunction::StakingSetSessionsPerEra(ref data) => { - (InternalFunctionId::StakingSetSessionsPerEra as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } - InternalFunction::StakingSetBondingDuration(ref data) => { - (InternalFunctionId::StakingSetBondingDuration as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } - InternalFunction::StakingSetValidatorCount(ref data) => { - (InternalFunctionId::StakingSetValidatorCount as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } - InternalFunction::StakingForceNewEra => { - (InternalFunctionId::StakingForceNewEra as u8).as_slice_then(|s| v.extend(s)); - } - InternalFunction::GovernanceSetApprovalPpmRequired(ref data) => { - (InternalFunctionId::GovernanceSetApprovalPpmRequired as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } - } - - v - } - - fn as_slice_then R>(&self, f: F) -> R { - f(self.to_vec().as_slice()) - } -} diff --git a/substrate/primitives/src/runtime_function.rs b/substrate/primitives/src/runtime_function.rs deleted file mode 100644 index 48e5afdc61..0000000000 --- a/substrate/primitives/src/runtime_function.rs +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2017 Parity Technologies (UK) Ltd. -// This file is part of Polkadot. - -// Polkadot is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Polkadot is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Polkadot. If not, see . - -//! Polkadot runtime functions. -//! This describes a function that can be called from an external transaction. - -use bytes::Vec; -use codec::Slicable; - -/// Public functions that can be dispatched to. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[repr(u8)] -enum FunctionId { - /// Set the timestamp. - TimestampSet = 0x00, - /// Set temporary session key as a validator. - SessionSetKey = 0x10, - /// Staking subsystem: begin staking. - StakingStake = 0x20, - /// Staking subsystem: stop staking. - StakingUnstake = 0x21, - /// Staking subsystem: transfer stake. - StakingTransfer = 0x22, - /// Make a proposal for the governance system. - GovernancePropose = 0x30, - /// Approve a proposal for the governance system. - GovernanceApprove = 0x31, -} - -impl FunctionId { - /// Derive `Some` value from a `u8`, or `None` if it's invalid. - fn from_u8(value: u8) -> Option { - use self::*; - let functions = [FunctionId::StakingStake, FunctionId::StakingUnstake, - FunctionId::StakingTransfer, FunctionId::SessionSetKey, FunctionId::TimestampSet, - FunctionId::GovernancePropose, FunctionId::GovernanceApprove]; - functions.iter().map(|&f| f).find(|&f| value == f as u8) - } -} - -/// Functions on the runtime. -#[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub enum Function { - /// Set the timestamp. - TimestampSet(::Timestamp), - /// Set temporary session key as a validator. - SessionSetKey(::SessionKey), - /// Staking subsystem: begin staking. - StakingStake, - /// Staking subsystem: stop staking. - StakingUnstake, - /// Staking subsystem: transfer stake. - StakingTransfer(::AccountId, ::Balance), - /// Make a proposal for the governance system. - GovernancePropose(::proposal::Proposal), - /// Approve a proposal for the governance system. - GovernanceApprove(::block::Number), -} - -impl Slicable for Function { - fn from_slice(value: &mut &[u8]) -> Option { - let id = try_opt!(u8::from_slice(value).and_then(FunctionId::from_u8)); - Some(match id { - FunctionId::TimestampSet => - Function::TimestampSet(try_opt!(Slicable::from_slice(value))), - FunctionId::SessionSetKey => - Function::SessionSetKey(try_opt!(Slicable::from_slice(value))), - FunctionId::StakingStake => Function::StakingStake, - FunctionId::StakingUnstake => Function::StakingUnstake, - FunctionId::StakingTransfer => { - let to = try_opt!(Slicable::from_slice(value)); - let amount = try_opt!(Slicable::from_slice(value)); - - Function::StakingTransfer(to, amount) - } - FunctionId::GovernancePropose => - Function::GovernancePropose(try_opt!(Slicable::from_slice(value))), - FunctionId::GovernanceApprove => - Function::GovernanceApprove(try_opt!(Slicable::from_slice(value))), - }) - } - - fn to_vec(&self) -> Vec { - let mut v = Vec::new(); - match *self { - Function::TimestampSet(ref data) => { - (FunctionId::TimestampSet as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } - Function::SessionSetKey(ref data) => { - (FunctionId::SessionSetKey as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } - Function::StakingStake => { - (FunctionId::StakingStake as u8).as_slice_then(|s| v.extend(s)); - } - Function::StakingUnstake => { - (FunctionId::StakingUnstake as u8).as_slice_then(|s| v.extend(s)); - } - Function::StakingTransfer(ref to, ref amount) => { - (FunctionId::StakingTransfer as u8).as_slice_then(|s| v.extend(s)); - to.as_slice_then(|s| v.extend(s)); - amount.as_slice_then(|s| v.extend(s)); - } - Function::GovernancePropose(ref data) => { - (FunctionId::GovernancePropose as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } - Function::GovernanceApprove(ref data) => { - (FunctionId::GovernanceApprove as u8).as_slice_then(|s| v.extend(s)); - data.as_slice_then(|s| v.extend(s)); - } - } - - v - } - - fn as_slice_then R>(&self, f: F) -> R { - f(self.to_vec().as_slice()) - } -} diff --git a/substrate/primitives/src/tests.rs b/substrate/primitives/src/tests.rs index 311f596400..51721ac85c 100644 --- a/substrate/primitives/src/tests.rs +++ b/substrate/primitives/src/tests.rs @@ -20,8 +20,7 @@ use codec::Slicable; use ::AccountId; use block::{Block, Header, Digest, Log}; -use runtime_function::Function; -use transaction::{UncheckedTransaction, Transaction}; +use transaction::{UncheckedTransaction, Transaction, Function}; #[test] fn serialise_transaction_works() { diff --git a/substrate/primitives/src/transaction.rs b/substrate/primitives/src/transaction.rs index c7723a7f1a..ff815ba627 100644 --- a/substrate/primitives/src/transaction.rs +++ b/substrate/primitives/src/transaction.rs @@ -18,7 +18,6 @@ use bytes::Vec; use codec::Slicable; -use runtime_function::Function; #[cfg(feature = "std")] use std::fmt; @@ -26,6 +25,264 @@ use std::fmt; #[cfg(not(feature = "std"))] use alloc::fmt; +use block::Number as BlockNumber; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[repr(u8)] +enum InternalFunctionId { + /// Set the system's code. + SystemSetCode = 0x00, + + /// Set the session length. + SessionSetLength = 0x10, + /// Force a new session. + SessionForceNewSession = 0x11, + + /// Set the number of sessions per era. + StakingSetSessionsPerEra = 0x20, + /// Set the minimum bonding duration for staking. + StakingSetBondingDuration = 0x21, + /// Set the validator count for staking. + StakingSetValidatorCount = 0x22, + /// Force a new staking era. + StakingForceNewEra = 0x23, + + /// Set the per-mille of validator approval required for governance changes. + GovernanceSetApprovalPpmRequired = 0x30, + +} + +impl InternalFunctionId { + /// Derive `Some` value from a `u8`, or `None` if it's invalid. + fn from_u8(value: u8) -> Option { + let functions = [ + InternalFunctionId::SystemSetCode, + InternalFunctionId::SessionSetLength, + InternalFunctionId::SessionForceNewSession, + InternalFunctionId::StakingSetSessionsPerEra, + InternalFunctionId::StakingSetBondingDuration, + InternalFunctionId::StakingSetValidatorCount, + InternalFunctionId::StakingForceNewEra, + InternalFunctionId::GovernanceSetApprovalPpmRequired, + ]; + functions.iter().map(|&f| f).find(|&f| value == f as u8) + } +} + +/// Internal functions that can be dispatched to. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub enum InternalFunction { + /// Set the system's code. + SystemSetCode(Vec), + /// Set the session length. + SessionSetLength(BlockNumber), + /// Force a new session. + SessionForceNewSession, + /// Set the number of sessions per era. + StakingSetSessionsPerEra(BlockNumber), + /// Set the minimum bonding duration for staking. + StakingSetBondingDuration(BlockNumber), + /// Set the validator count for staking. + StakingSetValidatorCount(u32), + /// Force a new staking era. + StakingForceNewEra, + /// Set the per-mille of validator approval required for governance changes. + GovernanceSetApprovalPpmRequired(u32), + +} + +/// An internal function. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Proposal { + /// The privileged function to call. + pub function: InternalFunction, +} + +impl Slicable for Proposal { + fn from_slice(value: &mut &[u8]) -> Option { + let id = try_opt!(u8::from_slice(value).and_then(InternalFunctionId::from_u8)); + let function = match id { + InternalFunctionId::SystemSetCode => + InternalFunction::SystemSetCode(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::SessionSetLength => + InternalFunction::SessionSetLength(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::SessionForceNewSession => InternalFunction::SessionForceNewSession, + InternalFunctionId::StakingSetSessionsPerEra => + InternalFunction::StakingSetSessionsPerEra(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::StakingSetBondingDuration => + InternalFunction::StakingSetBondingDuration(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::StakingSetValidatorCount => + InternalFunction::StakingSetValidatorCount(try_opt!(Slicable::from_slice(value))), + InternalFunctionId::StakingForceNewEra => InternalFunction::StakingForceNewEra, + InternalFunctionId::GovernanceSetApprovalPpmRequired => + InternalFunction::GovernanceSetApprovalPpmRequired(try_opt!(Slicable::from_slice(value))), + }; + + Some(Proposal { function }) + } + + fn to_vec(&self) -> Vec { + let mut v = Vec::new(); + match self.function { + InternalFunction::SystemSetCode(ref data) => { + (InternalFunctionId::SystemSetCode as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + InternalFunction::SessionSetLength(ref data) => { + (InternalFunctionId::SessionSetLength as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + InternalFunction::SessionForceNewSession => { + (InternalFunctionId::SessionForceNewSession as u8).as_slice_then(|s| v.extend(s)); + } + InternalFunction::StakingSetSessionsPerEra(ref data) => { + (InternalFunctionId::StakingSetSessionsPerEra as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + InternalFunction::StakingSetBondingDuration(ref data) => { + (InternalFunctionId::StakingSetBondingDuration as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + InternalFunction::StakingSetValidatorCount(ref data) => { + (InternalFunctionId::StakingSetValidatorCount as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + InternalFunction::StakingForceNewEra => { + (InternalFunctionId::StakingForceNewEra as u8).as_slice_then(|s| v.extend(s)); + } + InternalFunction::GovernanceSetApprovalPpmRequired(ref data) => { + (InternalFunctionId::GovernanceSetApprovalPpmRequired as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + } + + v + } + + fn as_slice_then R>(&self, f: F) -> R { + f(self.to_vec().as_slice()) + } +} + + +/// Public functions that can be dispatched to. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[repr(u8)] +enum FunctionId { + /// Set the timestamp. + TimestampSet = 0x00, + /// Set temporary session key as a validator. + SessionSetKey = 0x10, + /// Staking subsystem: begin staking. + StakingStake = 0x20, + /// Staking subsystem: stop staking. + StakingUnstake = 0x21, + /// Staking subsystem: transfer stake. + StakingTransfer = 0x22, + /// Make a proposal for the governance system. + GovernancePropose = 0x30, + /// Approve a proposal for the governance system. + GovernanceApprove = 0x31, +} + +impl FunctionId { + /// Derive `Some` value from a `u8`, or `None` if it's invalid. + fn from_u8(value: u8) -> Option { + use self::*; + let functions = [FunctionId::StakingStake, FunctionId::StakingUnstake, + FunctionId::StakingTransfer, FunctionId::SessionSetKey, FunctionId::TimestampSet, + FunctionId::GovernancePropose, FunctionId::GovernanceApprove]; + functions.iter().map(|&f| f).find(|&f| value == f as u8) + } +} + +/// Functions on the runtime. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub enum Function { + /// Set the timestamp. + TimestampSet(::Timestamp), + /// Set temporary session key as a validator. + SessionSetKey(::SessionKey), + /// Staking subsystem: begin staking. + StakingStake, + /// Staking subsystem: stop staking. + StakingUnstake, + /// Staking subsystem: transfer stake. + StakingTransfer(::AccountId, ::Balance), + /// Make a proposal for the governance system. + GovernancePropose(Proposal), + /// Approve a proposal for the governance system. + GovernanceApprove(::block::Number), +} + +impl Slicable for Function { + fn from_slice(value: &mut &[u8]) -> Option { + let id = try_opt!(u8::from_slice(value).and_then(FunctionId::from_u8)); + Some(match id { + FunctionId::TimestampSet => + Function::TimestampSet(try_opt!(Slicable::from_slice(value))), + FunctionId::SessionSetKey => + Function::SessionSetKey(try_opt!(Slicable::from_slice(value))), + FunctionId::StakingStake => Function::StakingStake, + FunctionId::StakingUnstake => Function::StakingUnstake, + FunctionId::StakingTransfer => { + let to = try_opt!(Slicable::from_slice(value)); + let amount = try_opt!(Slicable::from_slice(value)); + + Function::StakingTransfer(to, amount) + } + FunctionId::GovernancePropose => + Function::GovernancePropose(try_opt!(Slicable::from_slice(value))), + FunctionId::GovernanceApprove => + Function::GovernanceApprove(try_opt!(Slicable::from_slice(value))), + }) + } + + fn to_vec(&self) -> Vec { + let mut v = Vec::new(); + match *self { + Function::TimestampSet(ref data) => { + (FunctionId::TimestampSet as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + Function::SessionSetKey(ref data) => { + (FunctionId::SessionSetKey as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + Function::StakingStake => { + (FunctionId::StakingStake as u8).as_slice_then(|s| v.extend(s)); + } + Function::StakingUnstake => { + (FunctionId::StakingUnstake as u8).as_slice_then(|s| v.extend(s)); + } + Function::StakingTransfer(ref to, ref amount) => { + (FunctionId::StakingTransfer as u8).as_slice_then(|s| v.extend(s)); + to.as_slice_then(|s| v.extend(s)); + amount.as_slice_then(|s| v.extend(s)); + } + Function::GovernancePropose(ref data) => { + (FunctionId::GovernancePropose as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + Function::GovernanceApprove(ref data) => { + (FunctionId::GovernanceApprove as u8).as_slice_then(|s| v.extend(s)); + data.as_slice_then(|s| v.extend(s)); + } + } + + v + } + + fn as_slice_then R>(&self, f: F) -> R { + f(self.to_vec().as_slice()) + } +} + /// A vetted and verified transaction from the external world. #[derive(Debug, PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -113,7 +370,6 @@ impl fmt::Debug for UncheckedTransaction { #[cfg(test)] mod tests { use ::codec::Slicable; - use runtime_function::Function; use super::*; #[test] diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index ad71a7a236..5c846beea7 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -29,7 +29,7 @@ use runtime_std::prelude::*; use codec::KeyedVec; use support::storage; use primitives::{AccountId, Hash, BlockNumber}; -use primitives::proposal::Proposal; +use primitives::transaction::Proposal; use runtime::{staking, system, session}; const APPROVALS_REQUIRED: &[u8] = b"gov:apr"; @@ -95,7 +95,7 @@ pub mod privileged { pub mod internal { use super::*; - use primitives::proposal::{Proposal, InternalFunction}; + use primitives::transaction::{Proposal, InternalFunction}; /// Current era is ending; we should finish up any proposals. pub fn end_of_an_era() { @@ -150,7 +150,7 @@ mod tests { use codec::{KeyedVec, Joiner}; use support::{one, two, with_env}; use primitives::AccountId; - use primitives::proposal::InternalFunction; + use primitives::transaction::InternalFunction; use runtime::{staking, session}; fn new_test_ext() -> TestExternalities { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index 22f72fff79..2437fec912 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -23,8 +23,7 @@ use codec::{KeyedVec, Slicable}; use support::{Hashable, storage, with_env}; use primitives::{AccountId, Hash, TxOrder}; use primitives::block::{Block, Header, Number as BlockNumber}; -use primitives::transaction::UncheckedTransaction; -use primitives::runtime_function::Function; +use primitives::transaction::{UncheckedTransaction, Function}; use runtime::{staking, session}; const NONCE_OF: &[u8] = b"sys:non:"; @@ -215,8 +214,7 @@ mod tests { use runtime_std::{with_externalities, twox_128, TestExternalities}; use codec::{Joiner, KeyedVec, Slicable}; use support::{StaticHexInto, HexDisplay, one, two}; - use primitives::transaction::{UncheckedTransaction, Transaction}; - use primitives::runtime_function::Function; + use primitives::transaction::{UncheckedTransaction, Transaction, Function}; use primitives::block::{Header, Digest}; use runtime::staking; diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs index 71c6a77e87..5cc1e57845 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -338,7 +338,7 @@ mod tests { #[test] fn proposals_can_be_stored() { - use primitives::proposal::{Proposal, InternalFunction}; + use primitives::transaction::{Proposal, InternalFunction}; let mut t = TestExternalities { storage: HashMap::new(), }; with_externalities(&mut t, || { let x = Proposal { From 10ba24673ee6f04be26a4bdd6930d76b3c68fedd Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 16:44:30 +0100 Subject: [PATCH 20/21] remove debug impl in runtime-std --- substrate/runtime-std/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/substrate/runtime-std/src/lib.rs b/substrate/runtime-std/src/lib.rs index bca0e2018f..5291ca77ec 100644 --- a/substrate/runtime-std/src/lib.rs +++ b/substrate/runtime-std/src/lib.rs @@ -50,7 +50,8 @@ pub mod transaction { use core::ops; /// A type-safe indicator that a transaction has been checked. - #[derive(Debug, PartialEq, Eq, Clone)] + #[derive(PartialEq, Eq, Clone)] + #[cfg_attr(feature = "std", derive(Debug))] pub struct CheckedTransaction(UncheckedTransaction); impl CheckedTransaction { From 8bae8510f681440552cc250a6e2d3723823e05d5 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 18:30:21 +0100 Subject: [PATCH 21/21] combine relay chain primitives into one module --- substrate/client/src/backend.rs | 2 +- substrate/client/src/blockchain.rs | 2 +- substrate/client/src/genesis.rs | 5 ++--- substrate/client/src/in_mem.rs | 4 ++-- substrate/client/src/lib.rs | 2 +- substrate/executor/src/native_executor.rs | 3 +-- substrate/executor/src/wasm_executor.rs | 3 +-- substrate/network/src/blocks.rs | 4 ++-- substrate/network/src/chain.rs | 2 +- substrate/network/src/lib.rs | 2 +- substrate/network/src/message.rs | 2 +- substrate/network/src/protocol.rs | 2 +- substrate/network/src/service.rs | 2 +- substrate/network/src/sync.rs | 2 +- substrate/primitives/src/lib.rs | 7 ++----- substrate/primitives/src/{ => relay}/block.rs | 2 +- substrate/primitives/src/relay/mod.rs | 9 +++++++++ substrate/primitives/src/{ => relay}/transaction.rs | 4 ++-- substrate/primitives/src/tests.rs | 4 ++-- substrate/rpc/src/chain/mod.rs | 2 +- substrate/rpc/src/state/mod.rs | 2 +- substrate/runtime-std/src/lib.rs | 2 +- substrate/wasm-runtime/polkadot/src/lib.rs | 3 +-- .../wasm-runtime/polkadot/src/runtime/genesismap.rs | 2 +- .../wasm-runtime/polkadot/src/runtime/governance.rs | 6 +++--- substrate/wasm-runtime/polkadot/src/runtime/system.rs | 10 ++++------ .../wasm-runtime/polkadot/src/support/environment.rs | 2 +- substrate/wasm-runtime/polkadot/src/support/storage.rs | 2 +- 28 files changed, 47 insertions(+), 47 deletions(-) rename substrate/primitives/src/{ => relay}/block.rs (99%) create mode 100644 substrate/primitives/src/relay/mod.rs rename substrate/primitives/src/{ => relay}/transaction.rs (99%) diff --git a/substrate/client/src/backend.rs b/substrate/client/src/backend.rs index 76422528e7..2af11f3254 100644 --- a/substrate/client/src/backend.rs +++ b/substrate/client/src/backend.rs @@ -18,7 +18,7 @@ use state_machine; use error; -use primitives::block; +use primitives::relay::block; use blockchain::{self, BlockId}; /// Block insertion transction. Keeps hold if the inseted block state and data. diff --git a/substrate/client/src/blockchain.rs b/substrate/client/src/blockchain.rs index d8881fe5cf..0b5e715731 100644 --- a/substrate/client/src/blockchain.rs +++ b/substrate/client/src/blockchain.rs @@ -17,7 +17,7 @@ //! Polkadot blockchain trait use std::fmt::{Display, Formatter, Error as FmtError}; -use primitives::block; +use primitives::relay::block; use error::Result; /// Block indentification. diff --git a/substrate/client/src/genesis.rs b/substrate/client/src/genesis.rs index ebd8326b44..b2781668dd 100644 --- a/substrate/client/src/genesis.rs +++ b/substrate/client/src/genesis.rs @@ -17,7 +17,7 @@ //! Tool for creating the genesis block. use std::collections::HashMap; -use primitives::block::{Block, Header}; +use primitives::relay::{Block, Header}; use triehash::trie_root; /// Create a genesis block, given the initial storage. @@ -47,8 +47,7 @@ mod tests { use state_machine::backend::InMemory; use polkadot_executor::executor; use primitives::{AccountId, Hash}; - use primitives::block::{Number as BlockNumber, Header, Digest}; - use primitives::transaction::{UncheckedTransaction, Transaction, Function}; + use primitives::relay::{BlockNumber, Header, Digest, UncheckedTransaction, Transaction, Function}; use primitives::contract::CallData; use ed25519::Pair; diff --git a/substrate/client/src/in_mem.rs b/substrate/client/src/in_mem.rs index 5a71b8c62f..c1f9d113a4 100644 --- a/substrate/client/src/in_mem.rs +++ b/substrate/client/src/in_mem.rs @@ -23,10 +23,10 @@ use error; use backend; use primitives; use ser; -use primitives::block::{self, HeaderHash}; +use primitives::relay::block::{self, HeaderHash}; use blockchain::{self, BlockId, BlockStatus}; -fn header_hash(header: &primitives::block::Header) -> primitives::block::HeaderHash { +fn header_hash(header: &block::Header) -> block::HeaderHash { primitives::hashing::blake2_256(&ser::to_vec(header)).into() } diff --git a/substrate/client/src/lib.rs b/substrate/client/src/lib.rs index 9d0513bc6a..591c216145 100644 --- a/substrate/client/src/lib.rs +++ b/substrate/client/src/lib.rs @@ -47,7 +47,7 @@ pub use genesis::construct_genesis_block; pub use blockchain::Info as ChainInfo; pub use blockchain::BlockId; -use primitives::{block}; +use primitives::relay::block; use primitives::contract::{CallData, StorageKey, StorageData}; use blockchain::Backend as BlockchainBackend; diff --git a/substrate/executor/src/native_executor.rs b/substrate/executor/src/native_executor.rs index 176b4240d2..d2ea75413a 100644 --- a/substrate/executor/src/native_executor.rs +++ b/substrate/executor/src/native_executor.rs @@ -64,8 +64,7 @@ mod tests { use native_runtime::runtime::staking::balance; use state_machine::TestExternalities; use primitives::{twox_128, Hash}; - use primitives::block::{Header, Number as BlockNumber, Block, Digest}; - use primitives::transaction::{Transaction, UncheckedTransaction, Function}; + use primitives::relay::{Header, BlockNumber, Block, Digest, Transaction, UncheckedTransaction, Function}; use ed25519::Pair; const BLOATY_CODE: &[u8] = include_bytes!("../../wasm-runtime/target/wasm32-unknown-unknown/release/runtime_polkadot.wasm"); diff --git a/substrate/executor/src/wasm_executor.rs b/substrate/executor/src/wasm_executor.rs index 520557edd4..d8912c1703 100644 --- a/substrate/executor/src/wasm_executor.rs +++ b/substrate/executor/src/wasm_executor.rs @@ -294,8 +294,7 @@ mod tests { use native_runtime::runtime::staking::balance; use state_machine::TestExternalities; use primitives::{twox_128, AccountId}; - use primitives::block::Header; - use primitives::transaction::{Transaction, UncheckedTransaction, Function}; + use primitives::relay::{Header, Transaction, UncheckedTransaction, Function}; use runtime_std; use ed25519::Pair; diff --git a/substrate/network/src/blocks.rs b/substrate/network/src/blocks.rs index 52a72e022f..e79aff2c65 100644 --- a/substrate/network/src/blocks.rs +++ b/substrate/network/src/blocks.rs @@ -20,7 +20,7 @@ use std::ops::Range; use std::collections::{HashMap, BTreeMap}; use std::collections::hash_map::Entry; use network::PeerId; -use primitives::block::{Number as BlockNumber}; +use primitives::relay::BlockNumber; use message; const MAX_PARALLEL_DOWNLOADS: u32 = 1; @@ -190,7 +190,7 @@ impl BlockCollection { mod test { use super::{BlockCollection, BlockData}; use message; - use primitives::block::{HeaderHash}; + use primitives::relay::{HeaderHash}; fn is_empty(bc: &BlockCollection) -> bool { bc.blocks.is_empty() && diff --git a/substrate/network/src/chain.rs b/substrate/network/src/chain.rs index c125434710..cd6ebb8563 100644 --- a/substrate/network/src/chain.rs +++ b/substrate/network/src/chain.rs @@ -19,7 +19,7 @@ use client::{self, Client as PolkadotClient, ImportResult, ClientInfo, BlockStatus}; use client::error::Error; use state_machine; -use primitives::block; +use primitives::relay::block; pub trait Client : Send + Sync { /// Given a hash return a header diff --git a/substrate/network/src/lib.rs b/substrate/network/src/lib.rs index 75f416f97b..df06532289 100644 --- a/substrate/network/src/lib.rs +++ b/substrate/network/src/lib.rs @@ -56,7 +56,7 @@ pub use protocol::{ProtocolStatus}; pub use network::{NonReservedPeerMode, ConnectionFilter, ConnectionDirection, NetworkConfiguration}; // TODO: move it elsewhere -fn header_hash(header: &primitives::block::Header) -> primitives::block::HeaderHash { +fn header_hash(header: &primitives::relay::Header) -> primitives::relay::HeaderHash { primitives::hashing::blake2_256(&ser::to_vec(header)).into() } diff --git a/substrate/network/src/message.rs b/substrate/network/src/message.rs index 807bb02f8a..daa6b5520a 100644 --- a/substrate/network/src/message.rs +++ b/substrate/network/src/message.rs @@ -19,7 +19,7 @@ use std::borrow::Borrow; use primitives::parachain::Id as ParachainId; use primitives::AccountId; -use primitives::block::{Number as BlockNumber, HeaderHash, Header, Body}; +use primitives::relay::{BlockNumber, HeaderHash, Header, Body}; use service::Role as RoleFlags; pub type RequestId = u64; diff --git a/substrate/network/src/protocol.rs b/substrate/network/src/protocol.rs index 3b0a5a801a..3d5d14dbdd 100644 --- a/substrate/network/src/protocol.rs +++ b/substrate/network/src/protocol.rs @@ -20,7 +20,7 @@ use std::sync::Arc; use parking_lot::RwLock; use serde_json; use std::time; -use primitives::block::{HeaderHash, TransactionHash, Number as BlockNumber, Header}; +use primitives::relay::{HeaderHash, TransactionHash, BlockNumber, Header}; use network::{PeerId, NodeId}; use message::{self, Message}; diff --git a/substrate/network/src/service.rs b/substrate/network/src/service.rs index e3832249db..565f7f5249 100644 --- a/substrate/network/src/service.rs +++ b/substrate/network/src/service.rs @@ -19,7 +19,7 @@ use std::collections::{BTreeMap}; use std::io; use network::{NetworkProtocolHandler, NetworkService, NetworkContext, HostInfo, PeerId, ProtocolId, NetworkConfiguration , NonReservedPeerMode, ErrorKind}; -use primitives::block::{TransactionHash, Header}; +use primitives::relay::{TransactionHash, Header}; use core_io::{TimerToken}; use io::NetSyncIo; use protocol::{Protocol, ProtocolStatus, PeerInfo as ProtocolPeerInfo, TransactionStats}; diff --git a/substrate/network/src/sync.rs b/substrate/network/src/sync.rs index ec5b1ee67b..6bed7ec6a2 100644 --- a/substrate/network/src/sync.rs +++ b/substrate/network/src/sync.rs @@ -19,7 +19,7 @@ use io::SyncIo; use protocol::Protocol; use network::PeerId; use client::{ImportResult, BlockStatus, ClientInfo}; -use primitives::block::{HeaderHash, Number as BlockNumber, Header}; +use primitives::relay::{HeaderHash, BlockNumber, Header}; use blocks::{self, BlockCollection}; use message::{self, Message}; use super::header_hash; diff --git a/substrate/primitives/src/lib.rs b/substrate/primitives/src/lib.rs index 32cb18f8e1..e16aa8ef50 100644 --- a/substrate/primitives/src/lib.rs +++ b/substrate/primitives/src/lib.rs @@ -65,12 +65,11 @@ macro_rules! try_opt { } mod bytes; -pub mod block; pub mod contract; pub mod hash; pub mod hexdisplay; pub mod parachain; -pub mod transaction; +pub mod relay; pub mod uint; pub mod validator; @@ -81,6 +80,7 @@ mod tests; pub mod hashing; pub use self::hash::{H160, H256}; +pub use self::relay::BlockNumber; pub use self::uint::{U256, U512}; #[cfg(feature = "std")] @@ -101,9 +101,6 @@ pub type SessionKey = AccountId; /// Indentifier for a chain. pub type ChainID = u64; -/// Index of a block in the chain. -pub type BlockNumber = u64; - /// Index of a transaction. pub type TxOrder = u64; diff --git a/substrate/primitives/src/block.rs b/substrate/primitives/src/relay/block.rs similarity index 99% rename from substrate/primitives/src/block.rs rename to substrate/primitives/src/relay/block.rs index ca84ba6c88..e488d3c1f0 100644 --- a/substrate/primitives/src/block.rs +++ b/substrate/primitives/src/relay/block.rs @@ -22,7 +22,7 @@ use bytes::Vec; use codec::Slicable; use hash::H256; use parachain; -use transaction::UncheckedTransaction; +use relay::transaction::UncheckedTransaction; /// Used to refer to a block number. pub type Number = u64; diff --git a/substrate/primitives/src/relay/mod.rs b/substrate/primitives/src/relay/mod.rs new file mode 100644 index 0000000000..c4f22ac55f --- /dev/null +++ b/substrate/primitives/src/relay/mod.rs @@ -0,0 +1,9 @@ +//! Relay chain primitives. + +pub mod block; +pub mod transaction; + +pub use self::block::*; +pub use self::transaction::*; + +pub use self::block::Number as BlockNumber; diff --git a/substrate/primitives/src/transaction.rs b/substrate/primitives/src/relay/transaction.rs similarity index 99% rename from substrate/primitives/src/transaction.rs rename to substrate/primitives/src/relay/transaction.rs index ff815ba627..1432693e6e 100644 --- a/substrate/primitives/src/transaction.rs +++ b/substrate/primitives/src/relay/transaction.rs @@ -25,7 +25,7 @@ use std::fmt; #[cfg(not(feature = "std"))] use alloc::fmt; -use block::Number as BlockNumber; +use relay::block::Number as BlockNumber; #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -217,7 +217,7 @@ pub enum Function { /// Make a proposal for the governance system. GovernancePropose(Proposal), /// Approve a proposal for the governance system. - GovernanceApprove(::block::Number), + GovernanceApprove(BlockNumber), } impl Slicable for Function { diff --git a/substrate/primitives/src/tests.rs b/substrate/primitives/src/tests.rs index 51721ac85c..88710c4412 100644 --- a/substrate/primitives/src/tests.rs +++ b/substrate/primitives/src/tests.rs @@ -19,8 +19,8 @@ use codec::Slicable; use ::AccountId; -use block::{Block, Header, Digest, Log}; -use transaction::{UncheckedTransaction, Transaction, Function}; +use relay::block::{Block, Header, Digest, Log}; +use relay::transaction::{UncheckedTransaction, Transaction, Function}; #[test] fn serialise_transaction_works() { diff --git a/substrate/rpc/src/chain/mod.rs b/substrate/rpc/src/chain/mod.rs index 519bdefb4a..b69c2af8a0 100644 --- a/substrate/rpc/src/chain/mod.rs +++ b/substrate/rpc/src/chain/mod.rs @@ -16,7 +16,7 @@ //! Polkadot blockchain API. -use primitives::block; +use primitives::relay::block; use client; use state_machine; diff --git a/substrate/rpc/src/state/mod.rs b/substrate/rpc/src/state/mod.rs index 12905b7545..07b78a97c8 100644 --- a/substrate/rpc/src/state/mod.rs +++ b/substrate/rpc/src/state/mod.rs @@ -22,7 +22,7 @@ mod error; mod tests; use client::{self, Client}; -use primitives::{block}; +use primitives::relay::block; use primitives::contract::{CallData, StorageKey, StorageData}; use state_machine; diff --git a/substrate/runtime-std/src/lib.rs b/substrate/runtime-std/src/lib.rs index 5291ca77ec..6cee2e3326 100644 --- a/substrate/runtime-std/src/lib.rs +++ b/substrate/runtime-std/src/lib.rs @@ -40,7 +40,7 @@ pub mod prelude { /// Type definitions and helpers for transactions. pub mod transaction { - pub use primitives::transaction::{Transaction, UncheckedTransaction}; + pub use primitives::relay::{Transaction, UncheckedTransaction}; use primitives::Signature; #[cfg(feature = "std")] diff --git a/substrate/wasm-runtime/polkadot/src/lib.rs b/substrate/wasm-runtime/polkadot/src/lib.rs index e3881434ea..a6cd2c1f69 100644 --- a/substrate/wasm-runtime/polkadot/src/lib.rs +++ b/substrate/wasm-runtime/polkadot/src/lib.rs @@ -40,8 +40,7 @@ pub mod runtime; use runtime_std::prelude::*; use codec::Slicable; -use primitives::transaction::UncheckedTransaction; -use primitives::block::{Header, Block}; +use primitives::relay::{Header, Block, UncheckedTransaction}; /// Execute a block, with `input` being the canonical serialisation of the block. Returns the /// empty vector. diff --git a/substrate/wasm-runtime/polkadot/src/runtime/genesismap.rs b/substrate/wasm-runtime/polkadot/src/runtime/genesismap.rs index a2da04427c..38099f22f3 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/genesismap.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/genesismap.rs @@ -20,7 +20,7 @@ use std::collections::HashMap; use runtime_std::twox_128; use codec::{KeyedVec, Joiner}; use support::Hashable; -use primitives::block::{Number as BlockNumber, Block}; +use primitives::relay::{Number as BlockNumber, Block}; use primitives::AccountId; use runtime::staking::Balance; diff --git a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs index 6ab07169a7..298add1c40 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/governance.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/governance.rs @@ -29,7 +29,7 @@ use runtime_std::prelude::*; use codec::KeyedVec; use support::storage; use primitives::{AccountId, Hash, BlockNumber}; -use primitives::transaction::Proposal; +use primitives::relay::Proposal; use runtime::{staking, system, session}; const APPROVALS_REQUIRED: &[u8] = b"gov:apr"; @@ -95,7 +95,7 @@ pub mod privileged { pub mod internal { use super::*; - use primitives::transaction::{Proposal, InternalFunction}; + use primitives::relay::{Proposal, InternalFunction}; /// Current era is ending; we should finish up any proposals. pub fn end_of_an_era() { @@ -150,7 +150,7 @@ mod tests { use codec::{KeyedVec, Joiner}; use support::{one, two, with_env}; use primitives::AccountId; - use primitives::transaction::InternalFunction; + use primitives::relay::InternalFunction; use runtime::{staking, session}; fn new_test_ext() -> TestExternalities { diff --git a/substrate/wasm-runtime/polkadot/src/runtime/system.rs b/substrate/wasm-runtime/polkadot/src/runtime/system.rs index c47058c8ea..aa96548aa3 100644 --- a/substrate/wasm-runtime/polkadot/src/runtime/system.rs +++ b/substrate/wasm-runtime/polkadot/src/runtime/system.rs @@ -21,9 +21,8 @@ use runtime_std::prelude::*; use runtime_std::{mem, storage_root, enumerated_trie_root}; use codec::{KeyedVec, Slicable}; use support::{Hashable, storage, with_env}; -use primitives::{AccountId, Hash, TxOrder}; -use primitives::block::{Block, Header, Number as BlockNumber}; -use primitives::transaction::{UncheckedTransaction, Function}; +use primitives::{AccountId, Hash, TxOrder, BlockNumber}; +use primitives::relay::{Block, Header, UncheckedTransaction, Function, Log}; use runtime::{staking, session}; const NONCE_OF: &[u8] = b"sys:non:"; @@ -55,7 +54,7 @@ pub mod internal { struct CheckedTransaction(UncheckedTransaction); /// Deposits a log and ensures it matches the blocks log data. - pub fn deposit_log(log: ::primitives::block::Log) { + pub fn deposit_log(log: Log) { with_env(|e| e.digest.logs.push(log)); } @@ -222,8 +221,7 @@ mod tests { use runtime_std::{with_externalities, twox_128, TestExternalities}; use codec::{Joiner, KeyedVec, Slicable}; use support::{StaticHexInto, HexDisplay, one, two}; - use primitives::transaction::{UncheckedTransaction, Transaction, Function}; - use primitives::block::{Header, Digest}; + use primitives::relay::{Header, Digest, UncheckedTransaction, Transaction, Function}; use runtime::staking; #[test] diff --git a/substrate/wasm-runtime/polkadot/src/support/environment.rs b/substrate/wasm-runtime/polkadot/src/support/environment.rs index 3e846b34a6..b2ab7e8798 100644 --- a/substrate/wasm-runtime/polkadot/src/support/environment.rs +++ b/substrate/wasm-runtime/polkadot/src/support/environment.rs @@ -21,7 +21,7 @@ use runtime_std::mem; use runtime_std::cell::RefCell; use runtime_std::rc::Rc; -use primitives::block::{Number as BlockNumber, Digest}; +use primitives::relay::{BlockNumber, Digest}; use primitives::Hash; #[derive(Default)] diff --git a/substrate/wasm-runtime/polkadot/src/support/storage.rs b/substrate/wasm-runtime/polkadot/src/support/storage.rs index 5cc1e57845..f0e5f1c82e 100644 --- a/substrate/wasm-runtime/polkadot/src/support/storage.rs +++ b/substrate/wasm-runtime/polkadot/src/support/storage.rs @@ -338,7 +338,7 @@ mod tests { #[test] fn proposals_can_be_stored() { - use primitives::transaction::{Proposal, InternalFunction}; + use primitives::relay::{Proposal, InternalFunction}; let mut t = TestExternalities { storage: HashMap::new(), }; with_externalities(&mut t, || { let x = Proposal {