diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock index b054204d41..e30c0343d5 100644 --- a/substrate/Cargo.lock +++ b/substrate/Cargo.lock @@ -2222,6 +2222,7 @@ dependencies = [ "substrate-consensus-aura-primitives 2.0.0", "substrate-consensus-common 2.0.0", "substrate-finality-grandpa 2.0.0", + "substrate-finality-grandpa-primitives 2.0.0", "substrate-inherents 2.0.0", "substrate-keyring 2.0.0", "substrate-keystore 2.0.0", diff --git a/substrate/core/consensus/babe/src/lib.rs b/substrate/core/consensus/babe/src/lib.rs index 8557d611ff..7bc66f1357 100644 --- a/substrate/core/consensus/babe/src/lib.rs +++ b/substrate/core/consensus/babe/src/lib.rs @@ -45,7 +45,7 @@ use std::{sync::Arc, u64, fmt::{Debug, Display}, time::{Instant, Duration}}; use runtime_support::serde::{Serialize, Deserialize}; use parity_codec::{Decode, Encode}; use parking_lot::Mutex; -use primitives::{crypto::Pair, sr25519}; +use primitives::{Pair, Public, sr25519}; use merlin::Transcript; use inherents::{InherentDataProviders, InherentData}; use substrate_telemetry::{ diff --git a/substrate/core/keyring/src/ed25519.rs b/substrate/core/keyring/src/ed25519.rs index 9c303b62bc..bec4c80156 100644 --- a/substrate/core/keyring/src/ed25519.rs +++ b/substrate/core/keyring/src/ed25519.rs @@ -18,7 +18,7 @@ use std::{collections::HashMap, ops::Deref}; use lazy_static::lazy_static; -use substrate_primitives::{ed25519::{Pair, Public, Signature}, Pair as PairT, H256}; +use substrate_primitives::{ed25519::{Pair, Public, Signature}, Pair as PairT, Public as PublicT, H256}; pub use substrate_primitives::ed25519; /// Set of test accounts. diff --git a/substrate/core/keyring/src/sr25519.rs b/substrate/core/keyring/src/sr25519.rs index 24a83ab798..8db66ab5dd 100644 --- a/substrate/core/keyring/src/sr25519.rs +++ b/substrate/core/keyring/src/sr25519.rs @@ -19,7 +19,7 @@ use std::collections::HashMap; use std::ops::Deref; use lazy_static::lazy_static; -use substrate_primitives::{sr25519::{Pair, Public, Signature}, Pair as PairT, H256}; +use substrate_primitives::{sr25519::{Pair, Public, Signature}, Pair as PairT, Public as PublicT, H256}; pub use substrate_primitives::sr25519; /// Set of test accounts. @@ -68,7 +68,7 @@ impl Keyring { } pub fn to_raw_public_vec(self) -> Vec { - Public::from(self).into_raw_vec() + Public::from(self).to_raw_vec() } pub fn sign(self, msg: &[u8]) -> Signature { diff --git a/substrate/core/keystore/src/lib.rs b/substrate/core/keystore/src/lib.rs index c36c6504c0..882807e36e 100644 --- a/substrate/core/keystore/src/lib.rs +++ b/substrate/core/keystore/src/lib.rs @@ -23,7 +23,7 @@ use std::path::PathBuf; use std::fs::{self, File}; use std::io::{self, Write}; -use substrate_primitives::{ed25519::{Pair, Public}, Pair as PairT}; +use substrate_primitives::crypto::{KeyTypeId, Pair, Public, TypedKey}; /// Keystore error. #[derive(Debug, derive_more::Display, derive_more::From)] @@ -59,7 +59,7 @@ impl std::error::Error for Error { /// Key store. pub struct Store { path: PathBuf, - additional: HashMap, + additional: HashMap<(KeyTypeId, Vec), Vec>, } impl Store { @@ -69,33 +69,49 @@ impl Store { Ok(Store { path, additional: HashMap::new() }) } + fn get_pair(&self, public: &TPair::Public) -> Result> { + let key = (TPair::KEY_TYPE, public.to_raw_vec()); + if let Some(bytes) = self.additional.get(&key) { + let pair = TPair::from_seed_slice(bytes) + .map_err(|_| Error::InvalidSeed)?; + return Ok(Some(pair)); + } + Ok(None) + } + + fn insert_pair(&mut self, pair: &TPair) { + let key = (TPair::KEY_TYPE, pair.public().to_raw_vec()); + self.additional.insert(key, pair.to_raw_vec()); + } + /// Generate a new key, placing it into the store. - pub fn generate(&self, password: &str) -> Result { - let (pair, phrase, _) = Pair::generate_with_phrase(Some(password)); - let mut file = File::create(self.key_file_path(&pair.public()))?; + pub fn generate(&self, password: &str) -> Result { + let (pair, phrase, _) = TPair::generate_with_phrase(Some(password)); + let mut file = File::create(self.key_file_path::(&pair.public()))?; ::serde_json::to_writer(&file, &phrase)?; file.flush()?; Ok(pair) } /// Create a new key from seed. Do not place it into the store. - pub fn generate_from_seed(&mut self, seed: &str) -> Result { - let pair = Pair::from_string(seed, None) + pub fn generate_from_seed(&mut self, seed: &str) -> Result { + let pair = TPair::from_string(seed, None) .ok().ok_or(Error::InvalidSeed)?; - self.additional.insert(pair.public(), pair.clone()); + self.insert_pair(&pair); Ok(pair) } /// Load a key file with given public key. - pub fn load(&self, public: &Public, password: &str) -> Result { - if let Some(pair) = self.additional.get(public) { - return Ok(pair.clone()); + pub fn load(&self, public: &TPair::Public, password: &str) -> Result { + if let Some(pair) = self.get_pair(public)? { + return Ok(pair) } - let path = self.key_file_path(public); + + let path = self.key_file_path::(public); let file = File::open(path)?; let phrase: String = ::serde_json::from_reader(&file)?; - let (pair, _) = Pair::from_phrase(&phrase, Some(password)) + let (pair, _) = TPair::from_phrase(&phrase, Some(password)) .ok().ok_or(Error::InvalidPhrase)?; if &pair.public() != public { return Err(Error::InvalidPassword); @@ -104,22 +120,28 @@ impl Store { } /// Get public keys of all stored keys. - pub fn contents(&self) -> Result> { - let mut public_keys: Vec = self.additional.keys().cloned().collect(); + pub fn contents(&self) -> Result> { + let mut public_keys: Vec = self.additional.keys() + .filter_map(|(ty, public)| { + if *ty != TPublic::KEY_TYPE { + return None + } + Some(TPublic::from_slice(public)) + }) + .collect(); + + let key_type: [u8; 4] = TPublic::KEY_TYPE.to_le_bytes(); for entry in fs::read_dir(&self.path)? { let entry = entry?; let path = entry.path(); // skip directories and non-unicode file names (hex is unicode) if let Some(name) = path.file_name().and_then(|n| n.to_str()) { - if name.len() != 64 { continue } - match hex::decode(name) { - Ok(ref hex) if hex.len() == 32 => { - let mut buf = [0; 32]; - buf.copy_from_slice(&hex[..]); - - public_keys.push(Public(buf)); + Ok(ref hex) => { + if hex[0..4] != key_type { continue } + let public = TPublic::from_slice(&hex[4..]); + public_keys.push(public); } _ => continue, } @@ -129,9 +151,12 @@ impl Store { Ok(public_keys) } - fn key_file_path(&self, public: &Public) -> PathBuf { + fn key_file_path(&self, public: &TPair::Public) -> PathBuf { let mut buf = self.path.clone(); - buf.push(hex::encode(public.as_slice())); + let bytes: [u8; 4] = TPair::KEY_TYPE.to_le_bytes(); + let key_type = hex::encode(bytes); + let key = hex::encode(public.as_slice()); + buf.push(key_type + key.as_str()); buf } } @@ -140,6 +165,7 @@ impl Store { mod tests { use super::*; use tempdir::TempDir; + use substrate_primitives::ed25519; use substrate_primitives::crypto::Ss58Codec; #[test] @@ -147,16 +173,16 @@ mod tests { let temp_dir = TempDir::new("keystore").unwrap(); let store = Store::open(temp_dir.path().to_owned()).unwrap(); - assert!(store.contents().unwrap().is_empty()); + assert!(store.contents::().unwrap().is_empty()); - let key = store.generate("thepassword").unwrap(); - let key2 = store.load(&key.public(), "thepassword").unwrap(); + let key: ed25519::Pair = store.generate("thepassword").unwrap(); + let key2: ed25519::Pair = store.load(&key.public(), "thepassword").unwrap(); - assert!(store.load(&key.public(), "notthepassword").is_err()); + assert!(store.load::(&key.public(), "notthepassword").is_err()); assert_eq!(key.public(), key2.public()); - assert_eq!(store.contents().unwrap()[0], key.public()); + assert_eq!(store.contents::().unwrap()[0], key.public()); } #[test] @@ -164,7 +190,9 @@ mod tests { let temp_dir = TempDir::new("keystore").unwrap(); let mut store = Store::open(temp_dir.path().to_owned()).unwrap(); - let pair = store.generate_from_seed("0x3d97c819d68f9bafa7d6e79cb991eebcd77d966c5334c0b94d9e1fa7ad0869dc").unwrap(); + let pair: ed25519::Pair = store + .generate_from_seed("0x3d97c819d68f9bafa7d6e79cb991eebcd77d966c5334c0b94d9e1fa7ad0869dc") + .unwrap(); assert_eq!("5DKUrgFqCPV8iAXx9sjy1nyBygQCeiUYRFWurZGhnrn3HJCA", pair.public().to_ss58check()); } } diff --git a/substrate/core/primitives/src/crypto.rs b/substrate/core/primitives/src/crypto.rs index 9ddc9a93f7..0d01da1b48 100644 --- a/substrate/core/primitives/src/crypto.rs +++ b/substrate/core/primitives/src/crypto.rs @@ -26,6 +26,8 @@ use parity_codec::{Encode, Decode}; use regex::Regex; #[cfg(feature = "std")] use base58::{FromBase58, ToBase58}; +#[cfg(feature = "std")] +use std::hash::Hash; /// The root phrase for our publicly known keys. pub const DEV_PHRASE: &str = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; @@ -286,13 +288,30 @@ impl + AsRef<[u8]> + Default + Derive> Ss58Codec for T { } } +/// Trait suitable for typical cryptographic PKI key public type. +pub trait Public: PartialEq + Eq { + /// A new instance from the given slice that should be 32 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! + fn from_slice(data: &[u8]) -> Self; + + /// Return a `Vec` filled with raw data. + #[cfg(feature = "std")] + fn to_raw_vec(&self) -> Vec; + + /// Return a slice filled with raw data. + fn as_slice(&self) -> &[u8]; +} + /// Trait suitable for typical cryptographic PKI key pair type. /// /// For now it just specifies how to create a key from a phrase and derivation path. #[cfg(feature = "std")] -pub trait Pair: Sized + 'static { +pub trait Pair: Sized + 'static +{ /// TThe type which is used to encode a public key. - type Public; + type Public: Public + Hash; /// The type used to (minimally) encode the data required to securely create /// a new key pair. @@ -412,6 +431,31 @@ pub trait Pair: Sized + 'static { path, ) } + + /// Return a vec filled with raw data. + fn to_raw_vec(&self) -> Vec; +} + +/// An identifier for a type of cryptographic key. +/// +/// 0-1024 are reserved. +pub type KeyTypeId = u32; + +/// Constant key types. +pub mod key_types { + use super::KeyTypeId; + + /// ED25519 public key. + pub const ED25519: KeyTypeId = 10; + + /// SR25519 public key. + pub const SR25519: KeyTypeId = 20; +} + +/// A trait for something that has a key type ID. +pub trait TypedKey { + /// The type ID of this key. + const KEY_TYPE: KeyTypeId; } #[cfg(test)] @@ -429,8 +473,21 @@ mod tests { Seed(Vec), } + #[derive(PartialEq, Eq, Hash)] + struct TestPublic; + impl Public for TestPublic { + fn from_slice(bytes: &[u8]) -> Self { + Self + } + fn as_slice(&self) -> &[u8] { + &[] + } + fn to_raw_vec(&self) -> Vec { + vec![] + } + } impl Pair for TestPair { - type Public = (); + type Public = TestPublic; type Seed = [u8; 0]; type Signature = (); type DeriveError = (); @@ -464,7 +521,7 @@ mod tests { _message: M, _pubkey: P ) -> bool { true } - fn public(&self) -> Self::Public { () } + fn public(&self) -> Self::Public { TestPublic } fn from_standard_components>( phrase: &str, password: Option<&str>, @@ -481,6 +538,9 @@ mod tests { { Ok(TestPair::Seed(seed.to_owned())) } + fn to_raw_vec(&self) -> Vec { + vec![] + } } #[test] diff --git a/substrate/core/primitives/src/ed25519.rs b/substrate/core/primitives/src/ed25519.rs index 26086816a3..5d1fe884a5 100644 --- a/substrate/core/primitives/src/ed25519.rs +++ b/substrate/core/primitives/src/ed25519.rs @@ -32,7 +32,7 @@ use bip39::{Mnemonic, Language, MnemonicType}; use crate::crypto::{Pair as TraitPair, DeriveJunction, SecretStringError, Derive, Ss58Codec}; #[cfg(feature = "std")] use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; -use crate::crypto::UncheckedFrom; +use crate::crypto::{key_types, KeyTypeId, Public as TraitPublic, TypedKey, UncheckedFrom}; /// A secret seed. It's not called a "secret key" because ring doesn't expose the secret keys /// of the key pair (yeah, dumb); as such we're forced to remember the seed manually if we @@ -282,16 +282,6 @@ impl Public { Public(data) } - /// A new instance from the given slice that should be 32 bytes long. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_slice(data: &[u8]) -> Self { - let mut r = [0u8; 32]; - r.copy_from_slice(data); - Public(r) - } - /// A new instance from an H256. /// /// NOTE: No checking goes on to ensure this is a real public key. Only use it if @@ -300,23 +290,35 @@ impl Public { Public(x.into()) } + /// Return a slice filled with raw data. + pub fn as_array_ref(&self) -> &[u8; 32] { + self.as_ref() + } +} + +impl TraitPublic for Public { + /// A new instance from the given slice that should be 32 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! + fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(data); + Public(r) + } + /// Return a `Vec` filled with raw data. #[cfg(feature = "std")] - pub fn to_raw_vec(self) -> Vec { + fn to_raw_vec(&self) -> Vec { let r: &[u8; 32] = self.as_ref(); r.to_vec() } /// Return a slice filled with raw data. - pub fn as_slice(&self) -> &[u8] { + fn as_slice(&self) -> &[u8] { let r: &[u8; 32] = self.as_ref(); &r[..] } - - /// Return a slice filled with raw data. - pub fn as_array_ref(&self) -> &[u8; 32] { - self.as_ref() - } } #[cfg(feature = "std")] @@ -460,6 +462,11 @@ impl TraitPair for Pair { _ => false, } } + + /// Return a vec filled with raw data. + fn to_raw_vec(&self) -> Vec { + self.seed().to_vec() + } } #[cfg(feature = "std")] @@ -481,6 +488,19 @@ impl Pair { } } +impl TypedKey for Public { + const KEY_TYPE: KeyTypeId = key_types::ED25519; +} + +impl TypedKey for Signature { + const KEY_TYPE: KeyTypeId = key_types::ED25519; +} + +#[cfg(feature = "std")] +impl TypedKey for Pair { + const KEY_TYPE: KeyTypeId = key_types::ED25519; +} + #[cfg(test)] mod test { use super::*; diff --git a/substrate/core/primitives/src/lib.rs b/substrate/core/primitives/src/lib.rs index 7c0fd324fe..4fabb04ccb 100644 --- a/substrate/core/primitives/src/lib.rs +++ b/substrate/core/primitives/src/lib.rs @@ -69,7 +69,7 @@ pub use self::hash::{H160, H256, H512, convert_hash}; pub use self::uint::U256; pub use changes_trie::ChangesTrieConfiguration; #[cfg(feature = "std")] -pub use crypto::{DeriveJunction, Pair}; +pub use crypto::{DeriveJunction, Pair, Public}; pub use hash_db::Hasher; // Switch back to Blake after PoC-3 is out diff --git a/substrate/core/primitives/src/sr25519.rs b/substrate/core/primitives/src/sr25519.rs index aa2db2dc12..e92b9f0003 100644 --- a/substrate/core/primitives/src/sr25519.rs +++ b/substrate/core/primitives/src/sr25519.rs @@ -31,13 +31,14 @@ use substrate_bip39::mini_secret_from_entropy; use bip39::{Mnemonic, Language, MnemonicType}; #[cfg(feature = "std")] use crate::crypto::{Pair as TraitPair, DeriveJunction, Infallible, SecretStringError, Derive, Ss58Codec}; -use crate::{hash::{H256, H512}, crypto::UncheckedFrom}; +use crate::crypto::{key_types, KeyTypeId, Public as TraitPublic, TypedKey, UncheckedFrom}; +use crate::hash::{H256, H512}; use parity_codec::{Encode, Decode}; #[cfg(feature = "std")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "std")] -use schnorrkel::keys::MINI_SECRET_KEY_LENGTH; +use schnorrkel::keys::{MINI_SECRET_KEY_LENGTH, SECRET_KEY_LENGTH}; // signing context #[cfg(feature = "std")] @@ -51,6 +52,17 @@ pub struct Public(pub [u8; 32]); #[cfg(feature = "std")] pub struct Pair(Keypair); +#[cfg(feature = "std")] +impl Clone for Pair { + fn clone(&self) -> Self { + Pair(schnorrkel::Keypair { + public: self.0.public.clone(), + secret: schnorrkel::SecretKey::from_bytes(&self.0.secret.to_bytes()[..]) + .expect("key is always the correct size; qed") + }) + } +} + impl AsRef for Public { fn as_ref(&self) -> &Public { &self @@ -282,16 +294,6 @@ impl Public { Public(data) } - /// A new instance from the given slice that should be 32 bytes long. - /// - /// NOTE: No checking goes on to ensure this is a real public key. Only use it if - /// you are certain that the array actually is a pubkey. GIGO! - pub fn from_slice(data: &[u8]) -> Self { - let mut r = [0u8; 32]; - r.copy_from_slice(data); - Public(r) - } - /// A new instance from an H256. /// /// NOTE: No checking goes on to ensure this is a real public key. Only use it if @@ -300,21 +302,33 @@ impl Public { Public(x.into()) } + /// Return a slice filled with raw data. + pub fn as_array_ref(&self) -> &[u8; 32] { + self.as_ref() + } +} + +impl TraitPublic for Public { + /// A new instance from the given slice that should be 32 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real public key. Only use it if + /// you are certain that the array actually is a pubkey. GIGO! + fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 32]; + r.copy_from_slice(data); + Public(r) + } + /// Return a `Vec` filled with raw data. #[cfg(feature = "std")] - pub fn into_raw_vec(self) -> Vec { + fn to_raw_vec(&self) -> Vec { self.0.to_vec() } /// Return a slice filled with raw data. - pub fn as_slice(&self) -> &[u8] { + fn as_slice(&self) -> &[u8] { &self.0 } - - /// Return a slice filled with raw data. - pub fn as_array_ref(&self) -> &[u8; 32] { - self.as_ref() - } } #[cfg(feature = "std")] @@ -397,14 +411,22 @@ impl TraitPair for Pair { /// /// You should never need to use this; generate(), generate_with_phrase(), from_phrase() fn from_seed_slice(seed: &[u8]) -> Result { - if seed.len() != MINI_SECRET_KEY_LENGTH { - Err(SecretStringError::InvalidSeedLength) - } else { - Ok(Pair( - MiniSecretKey::from_bytes(seed) - .map_err(|_| SecretStringError::InvalidSeed)? - .expand_to_keypair() - )) + match seed.len() { + MINI_SECRET_KEY_LENGTH => { + Ok(Pair( + MiniSecretKey::from_bytes(seed) + .map_err(|_| SecretStringError::InvalidSeed)? + .expand_to_keypair() + )) + } + SECRET_KEY_LENGTH => { + Ok(Pair( + SecretKey::from_bytes(seed) + .map_err(|_| SecretStringError::InvalidSeed)? + .to_keypair() + )) + } + _ => Err(SecretStringError::InvalidSeedLength) } } @@ -478,6 +500,11 @@ impl TraitPair for Pair { Err(_) => false, } } + + /// Return a vec filled with raw data. + fn to_raw_vec(&self) -> Vec { + self.0.secret.to_bytes().to_vec() + } } #[cfg(feature = "std")] @@ -495,6 +522,19 @@ impl Pair { } } +impl TypedKey for Public { + const KEY_TYPE: KeyTypeId = key_types::SR25519; +} + +impl TypedKey for Signature { + const KEY_TYPE: KeyTypeId = key_types::SR25519; +} + +#[cfg(feature = "std")] +impl TypedKey for Pair { + const KEY_TYPE: KeyTypeId = key_types::SR25519; +} + #[cfg(test)] mod test { use super::*; diff --git a/substrate/core/service/src/lib.rs b/substrate/core/service/src/lib.rs index 15978ec21f..8f4f9184cf 100644 --- a/substrate/core/service/src/lib.rs +++ b/substrate/core/service/src/lib.rs @@ -38,7 +38,7 @@ use futures::prelude::*; use keystore::Store as Keystore; use log::{info, warn, debug, error}; use parity_codec::{Encode, Decode}; -use primitives::Pair; +use primitives::{Pair, Public, crypto::TypedKey, ed25519}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{Header, NumberFor, SaturatedConversion}; use substrate_executor::NativeExecutor; @@ -182,13 +182,13 @@ impl Service { // FIXME #1063 remove this if let Some(keystore) = keystore.as_mut() { for seed in &config.keys { - keystore.generate_from_seed(seed)?; + keystore.generate_from_seed::(seed)?; } - public_key = match keystore.contents()?.get(0) { + public_key = match keystore.contents::()?.get(0) { Some(public_key) => public_key.to_string(), None => { - let key = keystore.generate(&config.password)?; + let key: ed25519::Pair = keystore.generate(&config.password)?; let public_key = key.public(); info!("Generated a new keypair: {:?}", public_key); public_key.to_string() @@ -542,11 +542,15 @@ impl Service { } /// give the authority key, if we are an authority and have a key - pub fn authority_key(&self) -> Option { + pub fn authority_key(&self) -> Option + where + TPair: Pair + TypedKey, + ::Public: Public + TypedKey, + { if self.config.roles != Roles::AUTHORITY { return None } if let Some(keystore) = &self.keystore { - if let Ok(Some(Ok(key))) = keystore.contents().map(|keys| keys.get(0) - .map(|k| keystore.load(k, &self.config.password))) + if let Ok(Some(Ok(key))) = keystore.contents::().map(|keys| keys.get(0) + .map(|k| keystore.load::(k, &self.config.password))) { Some(key) } else { @@ -856,7 +860,6 @@ fn build_system_rpc_handler( /// # use transaction_pool::{self, txpool::{Pool as TransactionPool}}; /// # use network::construct_simple_protocol; /// # use client::{self, LongestChain}; -/// # use primitives::{Pair as PairT, ed25519}; /// # use consensus_common::import_queue::{BasicQueue, Verifier}; /// # use consensus_common::{BlockOrigin, ImportBlock, well_known_cache_keys::Id as CacheKeyId}; /// # use node_runtime::{GenesisConfig, RuntimeApi}; @@ -903,7 +906,7 @@ fn build_system_rpc_handler( /// { |config| >::new(config) }, /// // Setup as Consensus Authority (if the role and key are given) /// AuthoritySetup = { -/// |service: Self::FullService, key: Option>| { +/// |service: Self::FullService| { /// Ok(service) /// }}, /// LightService = LightComponents @@ -1029,8 +1032,7 @@ macro_rules! construct_service_factory { ) -> Result { ( $( $full_service_init )* ) (config).and_then(|service| { - let key = (&service).authority_key().map(Arc::new); - ($( $authority_setup )*)(service, key) + ($( $authority_setup )*)(service) }) } } diff --git a/substrate/node-template/src/service.rs b/substrate/node-template/src/service.rs index 0d2fe06088..38a2481a71 100644 --- a/substrate/node-template/src/service.rs +++ b/substrate/node-template/src/service.rs @@ -65,8 +65,8 @@ construct_service_factory! { FullComponents::::new(config) }, AuthoritySetup = { - |service: Self::FullService, key: Option>| { - if let Some(key) = key { + |service: Self::FullService| { + if let Some(key) = service.authority_key::() { info!("Using authority key {}", key.public()); let proposer = Arc::new(ProposerFactory { client: service.client(), @@ -77,7 +77,7 @@ construct_service_factory! { .ok_or_else(|| ServiceError::SelectChainRequired)?; let aura = start_aura( SlotDuration::get_or_compute(&*client)?, - key.clone(), + Arc::new(key), client.clone(), select_chain, client, diff --git a/substrate/node/cli/Cargo.toml b/substrate/node/cli/Cargo.toml index a97234e7c8..ad49cbe36c 100644 --- a/substrate/node/cli/Cargo.toml +++ b/substrate/node/cli/Cargo.toml @@ -24,10 +24,11 @@ substrate-basic-authorship = { path = "../../core/basic-authorship" } substrate-service = { path = "../../core/service" } transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" } network = { package = "substrate-network", path = "../../core/network" } -consensus = { package = "substrate-consensus-aura", path = "../../core/consensus/aura" } -grandpa = { package = "substrate-finality-grandpa", path = "../../core/finality-grandpa" } -sr-primitives = { path = "../../core/sr-primitives" } +aura = { package = "substrate-consensus-aura", path = "../../core/consensus/aura" } aura_primitives = { package = "substrate-consensus-aura-primitives", path = "../../core/consensus/aura/primitives" } +grandpa = { package = "substrate-finality-grandpa", path = "../../core/finality-grandpa" } +grandpa_primitives = { package = "substrate-finality-grandpa-primitives", path = "../../core/finality-grandpa/primitives" } +sr-primitives = { path = "../../core/sr-primitives" } node-executor = { path = "../executor" } substrate-keystore = { path = "../../core/keystore" } substrate-telemetry = { package = "substrate-telemetry", path = "../../core/telemetry" } diff --git a/substrate/node/cli/src/service.rs b/substrate/node/cli/src/service.rs index 4fe3c7ef9c..f3efdfd982 100644 --- a/substrate/node/cli/src/service.rs +++ b/substrate/node/cli/src/service.rs @@ -21,13 +21,13 @@ use std::sync::Arc; use std::time::Duration; +use aura::{import_queue, start_aura, AuraImportQueue, SlotDuration}; use client::{self, LongestChain}; -use consensus::{import_queue, start_aura, AuraImportQueue, SlotDuration}; use grandpa::{self, FinalityProofProvider as GrandpaFinalityProofProvider}; use node_executor; -use primitives::{Pair as PairT, ed25519}; +use primitives::Pair; use futures::prelude::*; -use node_primitives::Block; +use node_primitives::{AuraPair, Block}; use node_runtime::{GenesisConfig, RuntimeApi}; use substrate_service::{ FactoryFullConfiguration, LightComponents, FullComponents, FullBackend, @@ -79,12 +79,13 @@ construct_service_factory! { { |config: FactoryFullConfiguration| FullComponents::::new(config) }, AuthoritySetup = { - |mut service: Self::FullService, local_key: Option>| { + |mut service: Self::FullService| { let (block_import, link_half) = service.config.custom.grandpa_import_setup.take() .expect("Link Half and Block Import are present for Full Services or setup failed before. qed"); - if let Some(ref key) = local_key { - info!("Using authority key {}", key.public()); + if let Some(aura_key) = service.authority_key::() { + info!("Using aura key {}", aura_key.public()); + let proposer = Arc::new(substrate_basic_authorship::ProposerFactory { client: service.client(), transaction_pool: service.transaction_pool(), @@ -93,9 +94,10 @@ construct_service_factory! { let client = service.client(); let select_chain = service.select_chain() .ok_or(ServiceError::SelectChainRequired)?; + let aura = start_aura( SlotDuration::get_or_compute(&*client)?, - key.clone(), + Arc::new(aura_key), client, select_chain, block_import.clone(), @@ -104,19 +106,18 @@ construct_service_factory! { service.config.custom.inherent_data_providers.clone(), service.config.force_authoring, )?; - service.spawn_task(Box::new(aura.select(service.on_exit()).then(|_| Ok(())))); - - info!("Running Grandpa session as Authority {}", key.public()); + let select = aura.select(service.on_exit()).then(|_| Ok(())); + service.spawn_task(Box::new(select)); } - let local_key = if service.config.disable_grandpa { + let grandpa_key = if service.config.disable_grandpa { None } else { - local_key + service.authority_key::() }; let config = grandpa::Config { - local_key, + local_key: grandpa_key.map(Arc::new), // FIXME #1578 make this available through chainspec gossip_duration: Duration::from_millis(333), justification_period: 4096, @@ -165,7 +166,7 @@ construct_service_factory! { config.custom.grandpa_import_setup = Some((block_import.clone(), link_half)); - import_queue::<_, _, ed25519::Pair>( + import_queue::<_, _, AuraPair>( slot_duration, block_import, Some(justification_import), @@ -189,7 +190,7 @@ construct_service_factory! { let finality_proof_import = block_import.clone(); let finality_proof_request_builder = finality_proof_import.create_finality_proof_request_builder(); - import_queue::<_, _, ed25519::Pair>( + import_queue::<_, _, AuraPair>( SlotDuration::get_or_compute(&*client)?, block_import, None, @@ -215,7 +216,7 @@ construct_service_factory! { #[cfg(test)] mod tests { use std::sync::Arc; - use consensus::CompatibleDigestItem; + use aura::CompatibleDigestItem; use consensus_common::{Environment, Proposer, ImportBlock, BlockOrigin, ForkChoiceStrategy}; use node_primitives::DigestItem; use node_runtime::{BalancesCall, Call, CENTS, UncheckedExtrinsic}; diff --git a/substrate/node/primitives/src/lib.rs b/substrate/node/primitives/src/lib.rs index f6238907d5..351bb4fa12 100644 --- a/substrate/node/primitives/src/lib.rs +++ b/substrate/node/primitives/src/lib.rs @@ -44,12 +44,16 @@ pub type Balance = u128; /// Type used for expressing timestamp. pub type Moment = u64; -/// Alias to the signature scheme used for Aura authority signatures. -pub type AuraSignature = primitives::ed25519::Signature; +/// The aura crypto scheme defined via the keypair type. +#[cfg(feature = "std")] +pub type AuraPair = primitives::ed25519::Pair; -/// The Ed25519 pub key of an session that belongs to an Aura authority of the chain. +/// Identity of an Aura authority. pub type AuraId = primitives::ed25519::Public; +/// Signature for an Aura authority. +pub type AuraSignature = primitives::ed25519::Signature; + /// Index of a transaction in the chain. pub type Index = u64; diff --git a/substrate/subkey/src/main.rs b/substrate/subkey/src/main.rs index b38bffd772..7cff0d6414 100644 --- a/substrate/subkey/src/main.rs +++ b/substrate/subkey/src/main.rs @@ -22,7 +22,7 @@ use std::{str::FromStr, io::{stdin, Read}}; use hex_literal::hex; use clap::load_yaml; use bip39::{Mnemonic, Language, MnemonicType}; -use substrate_primitives::{ed25519, sr25519, hexdisplay::HexDisplay, Pair, crypto::Ss58Codec, blake2_256}; +use substrate_primitives::{ed25519, sr25519, hexdisplay::HexDisplay, Pair, Public, crypto::Ss58Codec, blake2_256}; use parity_codec::{Encode, Decode, Compact}; use sr_primitives::generic::Era; use node_primitives::{Balance, Index, Hash}; @@ -32,7 +32,7 @@ mod vanity; trait Crypto { type Pair: Pair; - type Public: Ss58Codec + AsRef<[u8]>; + type Public: Public + Ss58Codec + AsRef<[u8]> + std::hash::Hash; fn pair_from_suri(suri: &str, password: Option<&str>) -> Self::Pair { Self::Pair::from_string(suri, password).expect("Invalid phrase") }