diff --git a/Cargo.lock b/Cargo.lock index c49662d9772d4..ce26093f6c1ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -193,6 +193,11 @@ name = "bs58" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "byte-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byte-tools" version = "0.2.0" @@ -1918,7 +1923,7 @@ dependencies = [ "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.41 (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.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2777,6 +2782,8 @@ dependencies = [ name = "substrate-runtime-primitives" version = "0.1.0" dependencies = [ + "byte-num 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519 0.1.0", "integer-sqrt 0.1.0 (git+https://github.com/paritytech/integer-sqrt-rs.git)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2828,6 +2835,8 @@ dependencies = [ name = "substrate-runtime-staking" version = "0.1.0" dependencies = [ + "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519 0.1.0", "hex-literal 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3720,6 +3729,7 @@ dependencies = [ "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" "checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" "checksum bs58 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e6ea4851598d7433fbdba71fa2509d9b0df68124b9c0effe7588f5149692d9f" +"checksum byte-num 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac0bdba75808434f04270f3b7976ea6a662dc367d264feb54c5953258d59c66" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96c8b41881888cc08af32d47ac4edd52bc7fa27fef774be47a92443756451304" "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" diff --git a/substrate/runtime-support/src/dispatch.rs b/substrate/runtime-support/src/dispatch.rs index 9b26493839bff..aab0e3b551e2c 100644 --- a/substrate/runtime-support/src/dispatch.rs +++ b/substrate/runtime-support/src/dispatch.rs @@ -192,6 +192,37 @@ macro_rules! decl_dispatch { $($rest)* } }; + // WITH MANY TRAIT BOUNDS + ( + impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; + $(#[$attr:meta])* + pub enum $call_type:ident where aux: $aux_type:ty, + $($tr:ident : $bound:ty)* + { + $( + fn $fn_name:ident(aux, + $( + , $param_name:ident : $param:ty + )* + ) -> $result:ty + = $id:expr ; + )* + } + $($rest:tt)* + ) => { + __decl_dispatch_module_with_aux! { + impl for $mod_type<$trait_instance: $trait_name>; + $(#[$attr])* + pub enum $call_type where $($tr : $bound),* ; + $( + fn $fn_name(aux $(, $param_name: $param )*) -> $result = $id; + )* + } + decl_dispatch! { + impl for $mod_type<$trait_instance: $trait_name>; + $($rest)* + } + }; // BASE CASE ( impl for $mod_type:ident<$trait_instance:ident: $trait_name:ident>; diff --git a/substrate/runtime/primitives/Cargo.toml b/substrate/runtime/primitives/Cargo.toml index e7adc094d6789..d622094cdb9db 100644 --- a/substrate/runtime/primitives/Cargo.toml +++ b/substrate/runtime/primitives/Cargo.toml @@ -14,7 +14,9 @@ substrate-primitives = { path = "../../primitives", default_features = false } substrate-runtime-std = { path = "../../runtime-std", default_features = false } substrate-runtime-io = { path = "../../runtime-io", default_features = false } substrate-runtime-support = { path = "../../runtime-support", default_features = false } +ed25519 = { path = "../../ed25519", default_features = false } log = {version = "0.3", optional = true } +byte-num = "0.1" [dev-dependencies] serde_json = "1.0" diff --git a/substrate/runtime/primitives/src/address_format.rs b/substrate/runtime/primitives/src/address_format.rs new file mode 100644 index 0000000000000..7c62f868522f7 --- /dev/null +++ b/substrate/runtime/primitives/src/address_format.rs @@ -0,0 +1,79 @@ +// Copyright 2017 Parity Technologies (UK) Ltd. +// This file is part of Substrate Demo. + +// Substrate Demo 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. + +// Substrate Demo 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 Substrate Demo. If not, see . + +use byte_num::convert::IntoAscii; +use testing::Digest; +use substrate_primitives::H256; +use generic::Digest as GenericDigest; +use ed25519::Public; + +#[derive(Clone, Debug)] +pub struct SS58Compatible ( pub Public); + +pub trait SS58: Into { + fn encode(self) -> String { + self.into().0.to_ss58check() + } +} + +impl From for SS58Compatible { + fn from(x: u64) -> Self { + SS58Compatible (Public::from_slice(&x.itoa())) + } +} + +impl SS58 for u64 {} + +impl From for SS58Compatible { + fn from(x: Digest) -> Self { + SS58Compatible (Public::from_slice(&x + .logs + .iter() + .map(|digest| digest.itoa()) + .flatten() + .collect::>() + )) + } +} +impl SS58 for Digest {} + +impl From for SS58Compatible { + fn from(x: H256) -> Self { + SS58Compatible (Public::from_slice(&x[..])) + } +} + +impl SS58 for H256 {} + +impl> From> for SS58Compatible where + Vec : From> +{ + fn from(x: GenericDigest) -> Self { + SS58Compatible (Public::from_slice(Vec::from(x.logs).as_slice())) + } +} + +impl> SS58 for GenericDigest where + Vec: From> +{} + +impl> From> for Vec +{ + fn from(x: GenericDigest) -> Self { + x.logs.into_iter().map(|element| Into::::into(element)).collect() + } + +} diff --git a/substrate/runtime/primitives/src/generic.rs b/substrate/runtime/primitives/src/generic.rs index f1a9448c8fafc..5316b9908c5ba 100644 --- a/substrate/runtime/primitives/src/generic.rs +++ b/substrate/runtime/primitives/src/generic.rs @@ -317,7 +317,7 @@ impl Encode for Header where impl traits::Header for Header where Number: Member + ::rstd::hash::Hash + Copy + Codec + MaybeDisplay + SimpleArithmetic + Codec, Hash: HashT, - DigestItem: Member + Default + Codec, + DigestItem: Member + Default + Codec + Into>, Hash::Output: Default + ::rstd::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec, { type Number = Number; diff --git a/substrate/runtime/primitives/src/lib.rs b/substrate/runtime/primitives/src/lib.rs index a1ff760f7608f..08d6d0a2b4d56 100644 --- a/substrate/runtime/primitives/src/lib.rs +++ b/substrate/runtime/primitives/src/lib.rs @@ -40,6 +40,8 @@ extern crate substrate_runtime_io as runtime_io; extern crate substrate_runtime_support as runtime_support; extern crate substrate_codec as codec; extern crate substrate_primitives; +extern crate ed25519; +extern crate byte_num; #[cfg(test)] extern crate serde_json; @@ -59,6 +61,7 @@ pub mod testing; pub mod traits; pub mod generic; pub mod bft; +pub mod address_format; use traits::{Verify, Lazy}; diff --git a/substrate/runtime/primitives/src/testing.rs b/substrate/runtime/primitives/src/testing.rs index eab978d3b8951..2415d819aacfb 100644 --- a/substrate/runtime/primitives/src/testing.rs +++ b/substrate/runtime/primitives/src/testing.rs @@ -21,6 +21,7 @@ use std::fmt::Debug; use codec::Codec; use runtime_support::AuxDispatchable; use traits::{self, Checkable, Applyable, BlakeTwo256}; +use address_format::SS58; pub use substrate_primitives::H256; diff --git a/substrate/runtime/primitives/src/traits.rs b/substrate/runtime/primitives/src/traits.rs index 3c89087d70dc3..4fa6fbd5399f9 100644 --- a/substrate/runtime/primitives/src/traits.rs +++ b/substrate/runtime/primitives/src/traits.rs @@ -27,6 +27,7 @@ pub use integer_sqrt::IntegerSquareRoot; pub use num_traits::{Zero, One, Bounded}; pub use num_traits::ops::checked::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv}; use rstd::ops::{Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, RemAssign}; +use address_format::SS58; /// A lazy value. pub trait Lazy { @@ -426,4 +427,4 @@ pub trait Applyable: Sized + Send + Sync { fn index(&self) -> &Self::Index; fn sender(&self) -> &Self::AccountId; fn apply(self) -> Result<(), &'static str>; -} +} \ No newline at end of file diff --git a/substrate/runtime/staking/Cargo.toml b/substrate/runtime/staking/Cargo.toml index 4ca513a1f0c9d..fd896ca0eb389 100644 --- a/substrate/runtime/staking/Cargo.toml +++ b/substrate/runtime/staking/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Parity Technologies "] [dependencies] hex-literal = "0.1.0" +base58 = "0.1" serde = { version = "1.0", default_features = false } serde_derive = { version = "1.0", optional = true } safe-mix = { version = "1.0", default_features = false} @@ -20,6 +21,7 @@ substrate-runtime-consensus = { path = "../consensus", default_features = false substrate-runtime-system = { path = "../system", default_features = false } substrate-runtime-session = { path = "../session", default_features = false } substrate-runtime-timestamp = { path = "../timestamp", default_features = false } +ed25519 = { path = "../../ed25519", default_features = false } [dev-dependencies] wabt = "0.4" diff --git a/substrate/runtime/staking/src/address.rs b/substrate/runtime/staking/src/address.rs index 249e0b20db225..1576aa6af5a43 100644 --- a/substrate/runtime/staking/src/address.rs +++ b/substrate/runtime/staking/src/address.rs @@ -19,13 +19,15 @@ #[cfg(feature = "std")] use std::fmt; use super::{Member, Decode, Encode, As, Input, Output}; +use primitives::address_format::{SS58, SS58Compatible}; +use ed25519::Public; /// A vetted and verified extrinsic from the external world. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash))] pub enum Address where - AccountId: Member, - AccountIndex: Member, + AccountId: Member + fmt::Display + Into, + AccountIndex: Member + fmt::Display + Into, { /// It's an account ID (pubkey). #[cfg_attr(feature = "std", serde(deserialize_with="AccountId::deserialize"))] @@ -37,17 +39,18 @@ pub enum Address where #[cfg(feature = "std")] impl fmt::Display for Address where - AccountId: Member, - AccountIndex: Member, + AccountId: Member + Sized + fmt::Display + Into + Default + fmt::Debug + Sync, + AccountIndex: Member + Sized + fmt::Display + Into + fmt::Debug + Sync, + Public: From { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { - write!(f, "{:?}", self) + write!(f, "{:?}", &self.clone().encode()) } } impl From for Address where - AccountId: Member, - AccountIndex: Member, + AccountId: Member + fmt::Display + Into, + AccountIndex: Member + fmt::Display + Into, { fn from(a: AccountId) -> Self { Address::Id(a) @@ -59,8 +62,8 @@ fn need_more_than(a: T, b: T) -> Option { } impl Decode for Address where - AccountId: Member + Decode, - AccountIndex: Member + Decode + PartialOrd + Ord + As + As + As + Copy, + AccountId: Member + fmt::Display + Decode, + AccountIndex: Member + fmt::Display + Decode + PartialOrd + Ord + As + As + As + Copy, { fn decode(input: &mut I) -> Option { Some(match input.read_byte()? { @@ -75,8 +78,8 @@ impl Decode for Address where } impl Encode for Address where - AccountId: Member + Encode, - AccountIndex: Member + Encode + PartialOrd + Ord + As + As + As + Copy, + AccountId: Member + fmt::Display + Encode, + AccountIndex: Member + fmt::Display + Encode + PartialOrd + Ord + As + As + As + Copy, { fn encode_to(&self, dest: &mut T) { match *self { @@ -102,10 +105,40 @@ impl Encode for Address where } impl Default for Address where - AccountId: Member + Default, - AccountIndex: Member, + AccountId: Member + fmt::Display + Into + Default, + AccountIndex: Member + fmt::Display + Into, { fn default() -> Self { Address::Id(Default::default()) } } + +impl Into for Address where + AccountId: Member + fmt::Display + Into + Default + fmt::Debug + Sync, + AccountIndex: Member + fmt::Display + Into + fmt::Debug + Sync, + + +{ + fn into(self) -> Public { + match self { + Address::Id(id) => Into::::into(id), + Address::Index(id) => Into::::into(id) + } + } +} + +impl SS58 for Address where + AccountId: Member + fmt::Display + Into + Default + fmt::Debug + Sync, + AccountIndex: Member + fmt::Display + Into + fmt::Debug + Sync, + Vec: From +{} + +impl Into for Address where + AccountId: Member + fmt::Display + Into + Default + fmt::Debug + Sync, + AccountIndex: Member + fmt::Display + Into + fmt::Debug + Sync, + Vec: From +{ + fn into(self) -> SS58Compatible { + SS58Compatible(self.into()) + } +} \ No newline at end of file diff --git a/substrate/runtime/staking/src/lib.rs b/substrate/runtime/staking/src/lib.rs index b62b585dbbaa2..01f0d64b27164 100644 --- a/substrate/runtime/staking/src/lib.rs +++ b/substrate/runtime/staking/src/lib.rs @@ -28,6 +28,8 @@ extern crate serde_derive; #[cfg(test)] extern crate wabt; +extern crate base58; + #[macro_use] extern crate substrate_runtime_support as runtime_support; @@ -43,6 +45,7 @@ extern crate substrate_runtime_sandbox as sandbox; extern crate substrate_runtime_session as session; extern crate substrate_runtime_system as system; extern crate substrate_runtime_timestamp as timestamp; +extern crate ed25519; #[cfg(test)] use std::fmt::Debug; use rstd::prelude::*; @@ -53,7 +56,9 @@ use runtime_support::dispatch::Result; use session::OnSessionChange; use primitives::traits::{Zero, One, Bounded, RefInto, SimpleArithmetic, Executable, MakePayment, As, AuxLookup, Member, CheckedAdd, CheckedSub}; +use primitives::address_format::{SS58, SS58Compatible}; use address::Address as RawAddress; +use std::fmt; mod mock; @@ -103,7 +108,7 @@ pub trait Trait: system::Trait + session::Trait { type Balance: Parameter + SimpleArithmetic + Codec + Default + Copy + As + As + As; /// Type used for storing an account's index; implies the maximum number of accounts the system /// can hold. - type AccountIndex: Parameter + Member + Codec + SimpleArithmetic + As + As + As + As + As + Copy; + type AccountIndex: Parameter + Member + Codec + SimpleArithmetic + As + As + As + As + As + Copy + fmt::Display; /// A function which is invoked when the given account is dead. /// /// Gives a chance to clean up resources associated with the given account. @@ -114,7 +119,11 @@ decl_module! { pub struct Module; #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] - pub enum Call where aux: T::PublicAux { + pub enum Call + where + aux: T::PublicAux, + SS58Compatible: From<::AccountId> + From<::AccountIndex> + { fn transfer(aux, dest: RawAddress, value: T::Balance) -> Result = 0; fn stake(aux) -> Result = 1; fn unstake(aux, index: u32) -> Result = 2; @@ -233,7 +242,9 @@ pub enum UpdateBalanceOutcome { AccountKilled, } -impl Module { +impl Module +where SS58Compatible: From +{ // PUBLIC IMMUTABLES @@ -845,7 +856,9 @@ impl OnSessionChange for Module { } } -impl AuxLookup for Module { +impl AuxLookup for Module +where SS58Compatible: From<::AccountId> + From<::AccountIndex> +{ type Source = address::Address; type Target = T::AccountId; fn lookup(a: Self::Source) -> result::Result { diff --git a/substrate/runtime/system/src/lib.rs b/substrate/runtime/system/src/lib.rs index 60dd6059b4070..1e83b4130dfc0 100644 --- a/substrate/runtime/system/src/lib.rs +++ b/substrate/runtime/system/src/lib.rs @@ -40,6 +40,7 @@ extern crate safe_mix; use rstd::prelude::*; use primitives::traits::{self, CheckEqual, SimpleArithmetic, SimpleBitOps, Zero, One, Bounded, Hash, Member, MaybeDisplay}; +use primitives::address_format::SS58Compatible; use runtime_support::{StorageValue, StorageMap, Parameter}; use safe_mix::TripletMix; @@ -68,7 +69,7 @@ pub trait Trait: Eq + Clone { type Hash: Parameter + Member + MaybeDisplay + SimpleBitOps + Default + Copy + CheckEqual + rstd::hash::Hash + AsRef<[u8]>; type Hashing: Hash; type Digest: Parameter + Member + Default + traits::Digest; - type AccountId: Parameter + Member + MaybeDisplay + Ord + Default; + type AccountId: Parameter + Member + MaybeDisplay + Ord + Default + Into; type Header: Parameter + traits::Header< Number = Self::BlockNumber, Hash = Self::Hash, @@ -212,7 +213,7 @@ impl primitives::BuildStorage for GenesisConfig Ok(map![ Self::hash(&>::key_for(T::BlockNumber::zero())).to_vec() => [69u8; 32].encode(), - Self::hash(>::key()).to_vec() => 1u64.encode(), + Self::hash(>::key()).to_vec() => Encode::encode(&1u64), Self::hash(>::key()).to_vec() => [69u8; 32].encode(), Self::hash(>::key()).to_vec() => [0u8; 32].encode(), Self::hash(>::key()).to_vec() => [0u8; 4].encode()