diff --git a/Cargo.lock b/Cargo.lock index 58af885709038..0da61066df86a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3269,6 +3269,7 @@ dependencies = [ "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-std 0.1.0", + "srml-consensus 0.1.0", "srml-finality-tracker 0.1.0", "srml-session 0.1.0", "srml-support 0.1.0", @@ -3576,9 +3577,10 @@ dependencies = [ [[package]] name = "subkey" -version = "0.1.0" +version = "0.2.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", @@ -3981,12 +3983,14 @@ dependencies = [ "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", @@ -4020,6 +4024,7 @@ dependencies = [ "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 0.1.0", "sr-primitives 0.1.0", "sr-version 0.1.0", "substrate-client 0.1.0", @@ -4029,6 +4034,7 @@ dependencies = [ "substrate-primitives 0.1.0", "substrate-state-machine 0.1.0", "substrate-test-client 0.1.0", + "substrate-test-runtime 0.1.0", "substrate-transaction-pool 0.1.0", "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4187,6 +4193,7 @@ dependencies = [ "substrate-inherents 0.1.0", "substrate-keyring 0.1.0", "substrate-primitives 0.1.0", + "substrate-test-client 0.1.0", ] [[package]] diff --git a/build.rs b/build.rs index 9981ae31d7b73..273700c525c88 100644 --- a/build.rs +++ b/build.rs @@ -16,7 +16,7 @@ use vergen::{ConstantsFlags, generate_cargo_keys}; -const ERROR_MSG: &'static str = "Failed to generate metadata files"; +const ERROR_MSG: &str = "Failed to generate metadata files"; fn main() { generate_cargo_keys(ConstantsFlags::all()).expect(ERROR_MSG); diff --git a/core/basic-authorship/src/basic_authorship.rs b/core/basic-authorship/src/basic_authorship.rs index f074b739ff02e..71114ad2da689 100644 --- a/core/basic-authorship/src/basic_authorship.rs +++ b/core/basic-authorship/src/basic_authorship.rs @@ -273,17 +273,16 @@ mod tests { use codec::Encode; use std::cell::RefCell; use consensus_common::{Environment, Proposer}; - use test_client::keyring::Keyring; - use test_client::{self, runtime::{Extrinsic, Transfer}}; + use test_client::{self, runtime::{Extrinsic, Transfer}, AccountKeyring}; fn extrinsic(nonce: u64) -> Extrinsic { let tx = Transfer { amount: Default::default(), nonce, - from: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Alice.into(), to: Default::default(), }; - let signature = Keyring::from_raw_public(tx.from.to_fixed_bytes()).unwrap().sign(&tx.encode()).into(); + let signature = AccountKeyring::from_public(&tx.from).unwrap().sign(&tx.encode()).into(); Extrinsic::Transfer(tx, signature) } diff --git a/core/cli/src/lib.rs b/core/cli/src/lib.rs index 88d9b5728dc4e..864fda3805f2f 100644 --- a/core/cli/src/lib.rs +++ b/core/cli/src/lib.rs @@ -63,6 +63,9 @@ use substrate_telemetry::TelemetryEndpoints; const MAX_NODE_NAME_LENGTH: usize = 32; +/// The root phrase for our development network keys. +pub const DEV_PHRASE: &str = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; + /// Executable version. Used to pass version information from the root crate. pub struct VersionInfo { /// Implemtation name. @@ -387,7 +390,7 @@ where } if cli.shared_params.dev { - config.keys.push("Alice".into()); + config.keys.push(format!("{}//Alice", DEV_PHRASE)); } let rpc_interface: &str = if cli.rpc_external { "0.0.0.0" } else { "127.0.0.1" }; diff --git a/core/client/db/src/light.rs b/core/client/db/src/light.rs index 7162971b36678..d99ef503b2f81 100644 --- a/core/client/db/src/light.rs +++ b/core/client/db/src/light.rs @@ -541,6 +541,7 @@ pub(crate) mod tests { use super::*; type Block = RawBlock>; + type AuthorityId = AuthorityIdFor; pub fn default_header(parent: &Hash, number: u64) -> Header { Header { @@ -831,10 +832,10 @@ pub(crate) mod tests { let checks = vec![ (0, None), (1, None), - (2, Some(vec![[1u8; 32].into()])), - (3, Some(vec![[1u8; 32].into()])), - (4, Some(vec![[1u8; 32].into(), [2u8; 32].into()])), - (5, Some(vec![[1u8; 32].into(), [2u8; 32].into()])), + (2, Some(vec![AuthorityId::from_raw([1u8; 32])])), + (3, Some(vec![AuthorityId::from_raw([1u8; 32])])), + (4, Some(vec![AuthorityId::from_raw([1u8; 32]), AuthorityId::from_raw([2u8; 32])])), + (5, Some(vec![AuthorityId::from_raw([1u8; 32]), AuthorityId::from_raw([2u8; 32])])), (6, None), (7, None), // block will work for 'future' block too ]; @@ -843,13 +844,13 @@ pub(crate) mod tests { run_checks(&db, 0, &checks); let hash1 = insert_final_block(&db, None, || default_header(&hash0, 1)); run_checks(&db, 1, &checks); - let hash2 = insert_final_block(&db, Some(vec![[1u8; 32].into()]), || default_header(&hash1, 2)); + let hash2 = insert_final_block(&db, Some(vec![AuthorityId::from_raw([1u8; 32])]), || default_header(&hash1, 2)); run_checks(&db, 2, &checks); - let hash3 = insert_final_block(&db, Some(vec![[1u8; 32].into()]), || default_header(&hash2, 3)); + let hash3 = insert_final_block(&db, Some(vec![AuthorityId::from_raw([1u8; 32])]), || default_header(&hash2, 3)); run_checks(&db, 3, &checks); - let hash4 = insert_final_block(&db, Some(vec![[1u8; 32].into(), [2u8; 32].into()]), || default_header(&hash3, 4)); + let hash4 = insert_final_block(&db, Some(vec![AuthorityId::from_raw([1u8; 32]), AuthorityId::from_raw([2u8; 32])]), || default_header(&hash3, 4)); run_checks(&db, 4, &checks); - let hash5 = insert_final_block(&db, Some(vec![[1u8; 32].into(), [2u8; 32].into()]), || default_header(&hash4, 5)); + let hash5 = insert_final_block(&db, Some(vec![AuthorityId::from_raw([1u8; 32]), AuthorityId::from_raw([2u8; 32])]), || default_header(&hash4, 5)); run_checks(&db, 5, &checks); let hash6 = insert_final_block(&db, None, || default_header(&hash5, 6)); run_checks(&db, 7, &checks); @@ -861,9 +862,9 @@ pub(crate) mod tests { // some older non-best blocks are inserted // ... -> B2(1) -> B2_1(1) -> B2_2(2) // => the cache ignores all writes before best finalized block - let hash2_1 = insert_non_best_block(&db, Some(vec![[1u8; 32].into()]), || default_header(&hash2, 3)); + let hash2_1 = insert_non_best_block(&db, Some(vec![AuthorityId::from_raw([1u8; 32])]), || default_header(&hash2, 3)); assert_eq!(None, db.cache().authorities_at(BlockId::Hash(hash2_1))); - let hash2_2 = insert_non_best_block(&db, Some(vec![[1u8; 32].into(), [2u8; 32].into()]), || default_header(&hash2_1, 4)); + let hash2_2 = insert_non_best_block(&db, Some(vec![AuthorityId::from_raw([1u8; 32]), AuthorityId::from_raw([2u8; 32])]), || default_header(&hash2_1, 4)); assert_eq!(None, db.cache().authorities_at(BlockId::Hash(hash2_2))); } @@ -874,39 +875,39 @@ pub(crate) mod tests { // \> B6_1_1(5) // \> B6_1_2(6) -> B6_1_3(7) - let hash7 = insert_block(&db, Some(vec![[3u8; 32].into()]), || default_header(&hash6, 7)); + let hash7 = insert_block(&db, Some(vec![AuthorityId::from_raw([3u8; 32])]), || default_header(&hash6, 7)); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - let hash8 = insert_block(&db, Some(vec![[3u8; 32].into()]), || default_header(&hash7, 8)); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + let hash8 = insert_block(&db, Some(vec![AuthorityId::from_raw([3u8; 32])]), || default_header(&hash7, 8)); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - let hash6_1 = insert_block(&db, Some(vec![[4u8; 32].into()]), || default_header(&hash6, 7)); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + let hash6_1 = insert_block(&db, Some(vec![AuthorityId::from_raw([4u8; 32])]), || default_header(&hash6, 7)); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - let hash6_1_1 = insert_non_best_block(&db, Some(vec![[5u8; 32].into()]), || default_header(&hash6_1, 8)); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![AuthorityId::from_raw([4u8; 32])])); + let hash6_1_1 = insert_non_best_block(&db, Some(vec![AuthorityId::from_raw([5u8; 32])]), || default_header(&hash6_1, 8)); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![[5u8; 32].into()])); - let hash6_1_2 = insert_non_best_block(&db, Some(vec![[6u8; 32].into()]), || default_header(&hash6_1, 8)); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![AuthorityId::from_raw([4u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![AuthorityId::from_raw([5u8; 32])])); + let hash6_1_2 = insert_non_best_block(&db, Some(vec![AuthorityId::from_raw([6u8; 32])]), || default_header(&hash6_1, 8)); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![[5u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![[6u8; 32].into()])); - let hash6_2 = insert_block(&db, Some(vec![[4u8; 32].into()]), || default_header(&hash6_1, 8)); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![AuthorityId::from_raw([4u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![AuthorityId::from_raw([5u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![AuthorityId::from_raw([6u8; 32])])); + let hash6_2 = insert_block(&db, Some(vec![AuthorityId::from_raw([4u8; 32])]), || default_header(&hash6_1, 8)); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![[3u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![[5u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![[6u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![[4u8; 32].into()])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), Some(vec![AuthorityId::from_raw([3u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![AuthorityId::from_raw([4u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![AuthorityId::from_raw([5u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![AuthorityId::from_raw([6u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![AuthorityId::from_raw([4u8; 32])])); (hash7, hash8, hash6_1, hash6_2, hash6_1_1, hash6_1_2) }; @@ -917,19 +918,19 @@ pub(crate) mod tests { assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), None); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![[5u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![[6u8; 32].into()])); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![[4u8; 32].into()])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![AuthorityId::from_raw([4u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), Some(vec![AuthorityId::from_raw([5u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), Some(vec![AuthorityId::from_raw([6u8; 32])])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![AuthorityId::from_raw([4u8; 32])])); // finalize block hash6_2 db.finalize_header(BlockId::Hash(hash6_2)).unwrap(); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6)), None); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash7)), None); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash8)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![[4u8; 32].into()])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1)), Some(vec![AuthorityId::from_raw([4u8; 32])])); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_1)), None); assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_1_2)), None); - assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![[4u8; 32].into()])); + assert_eq!(db.cache().authorities_at(BlockId::Hash(hash6_2)), Some(vec![AuthorityId::from_raw([4u8; 32])])); } } diff --git a/core/client/src/client.rs b/core/client/src/client.rs index 23a6061e36e96..34723deb8cca1 100644 --- a/core/client/src/client.rs +++ b/core/client/src/client.rs @@ -1520,11 +1520,10 @@ impl backend::AuxStore for Client pub(crate) mod tests { use std::collections::HashMap; use super::*; - use keyring::Keyring; use primitives::twox_128; use runtime_primitives::traits::DigestItem as DigestItemT; use runtime_primitives::generic::DigestItem; - use test_client::{self, TestClient}; + use test_client::{self, TestClient, AccountKeyring, AuthorityKeyring}; use consensus::BlockOrigin; use test_client::client::backend::Backend as TestBackend; use test_client::BlockBuilderExt; @@ -1541,10 +1540,10 @@ pub(crate) mod tests { ) { // prepare block structure let blocks_transfers = vec![ - vec![(Keyring::Alice, Keyring::Dave), (Keyring::Bob, Keyring::Dave)], - vec![(Keyring::Charlie, Keyring::Eve)], + vec![(AccountKeyring::Alice, AccountKeyring::Dave), (AccountKeyring::Bob, AccountKeyring::Dave)], + vec![(AccountKeyring::Charlie, AccountKeyring::Eve)], vec![], - vec![(Keyring::Alice, Keyring::Dave)], + vec![(AccountKeyring::Alice, AccountKeyring::Dave)], ]; // prepare client ang import blocks @@ -1555,8 +1554,8 @@ pub(crate) mod tests { let mut builder = remote_client.new_block().unwrap(); for (from, to) in block_transfers { builder.push_transfer(Transfer { - from: from.to_raw_public().into(), - to: to.to_raw_public().into(), + from: from.into(), + to: to.into(), amount: 1, nonce: *nonces.entry(from).and_modify(|n| { *n = *n + 1 }).or_default(), }).unwrap(); @@ -1571,12 +1570,12 @@ pub(crate) mod tests { } // prepare test cases - let alice = twox_128(&runtime::system::balance_of_key(Keyring::Alice.to_raw_public().into())).to_vec(); - let bob = twox_128(&runtime::system::balance_of_key(Keyring::Bob.to_raw_public().into())).to_vec(); - let charlie = twox_128(&runtime::system::balance_of_key(Keyring::Charlie.to_raw_public().into())).to_vec(); - let dave = twox_128(&runtime::system::balance_of_key(Keyring::Dave.to_raw_public().into())).to_vec(); - let eve = twox_128(&runtime::system::balance_of_key(Keyring::Eve.to_raw_public().into())).to_vec(); - let ferdie = twox_128(&runtime::system::balance_of_key(Keyring::Ferdie.to_raw_public().into())).to_vec(); + let alice = twox_128(&runtime::system::balance_of_key(AccountKeyring::Alice.into())).to_vec(); + let bob = twox_128(&runtime::system::balance_of_key(AccountKeyring::Bob.into())).to_vec(); + let charlie = twox_128(&runtime::system::balance_of_key(AccountKeyring::Charlie.into())).to_vec(); + let dave = twox_128(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); + let eve = twox_128(&runtime::system::balance_of_key(AccountKeyring::Eve.into())).to_vec(); + let ferdie = twox_128(&runtime::system::balance_of_key(AccountKeyring::Ferdie.into())).to_vec(); let test_cases = vec![ (1, 4, alice.clone(), vec![(4, 0), (1, 0)]), (1, 3, alice.clone(), vec![(1, 0)]), @@ -1610,14 +1609,14 @@ pub(crate) mod tests { assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - Keyring::Alice.to_raw_public().into() + AccountKeyring::Alice.into() ).unwrap(), 1000 ); assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - Keyring::Ferdie.to_raw_public().into() + AccountKeyring::Ferdie.into() ).unwrap(), 0 ); @@ -1629,9 +1628,9 @@ pub(crate) mod tests { assert_eq!(client.info().unwrap().chain.best_number, 0); assert_eq!(client.authorities_at(&BlockId::Number(0)).unwrap(), vec![ - Keyring::Alice.to_raw_public().into(), - Keyring::Bob.to_raw_public().into(), - Keyring::Charlie.to_raw_public().into() + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Bob.into(), + AuthorityKeyring::Charlie.into() ]); } @@ -1653,8 +1652,8 @@ pub(crate) mod tests { let mut builder = client.new_block().unwrap(); builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); @@ -1666,14 +1665,14 @@ pub(crate) mod tests { assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - Keyring::Alice.to_raw_public().into() + AccountKeyring::Alice.into() ).unwrap(), 958 ); assert_eq!( client.runtime_api().balance_of( &BlockId::Number(client.info().unwrap().chain.best_number), - Keyring::Ferdie.to_raw_public().into() + AccountKeyring::Ferdie.into() ).unwrap(), 42 ); @@ -1695,15 +1694,15 @@ pub(crate) mod tests { let mut builder = client.new_block().unwrap(); builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); assert!(builder.push_transfer(Transfer { - from: Keyring::Eve.to_raw_public().into(), - to: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Eve.into(), + to: AccountKeyring::Alice.into(), amount: 42, nonce: 0, }).is_err()); @@ -1789,8 +1788,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 41, nonce: 0, }).unwrap(); @@ -1809,8 +1808,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 1, }).unwrap(); @@ -1821,8 +1820,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 0, }).unwrap(); @@ -1910,8 +1909,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 41, nonce: 0, }).unwrap(); @@ -1930,8 +1929,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 1, }).unwrap(); @@ -1942,8 +1941,8 @@ pub(crate) mod tests { let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 0, }).unwrap(); diff --git a/core/client/src/genesis.rs b/core/client/src/genesis.rs index 77861a606d017..9ee003368524e 100644 --- a/core/client/src/genesis.rs +++ b/core/client/src/genesis.rs @@ -41,14 +41,16 @@ pub fn construct_genesis_block< mod tests { use super::*; use parity_codec::{Encode, Decode, Joiner}; - use keyring::Keyring; use executor::{NativeExecutionDispatch, native_executor_instance}; use state_machine::{self, OverlayedChanges, ExecutionStrategy, InMemoryChangesTrieStorage}; use state_machine::backend::InMemory; - use test_client::runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; - use test_client::runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest, Extrinsic}; + use test_client::{ + runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}, + runtime::{Hash, Transfer, Block, BlockNumber, Header, Digest, Extrinsic}, + AccountKeyring, AuthorityKeyring + }; use runtime_primitives::traits::BlakeTwo256; - use primitives::{Blake2Hasher, ed25519::{Public, Pair}}; + use primitives::Blake2Hasher; use hex::*; native_executor_instance!(Executor, test_client::runtime::api::dispatch, test_client::runtime::native_version, include_bytes!("../../test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm")); @@ -67,7 +69,7 @@ mod tests { use trie::ordered_trie_root; let transactions = txs.into_iter().map(|tx| { - let signature = Pair::from(Keyring::from_public(Public::from_raw(tx.from.to_fixed_bytes())).unwrap()) + let signature = AccountKeyring::from_public(&tx.from).unwrap() .sign(&tx.encode()).into(); Extrinsic::Transfer(tx, signature) @@ -75,7 +77,6 @@ mod tests { let extrinsics_root = ordered_trie_root::(transactions.iter().map(Encode::encode)).into(); - println!("root before: {:?}", extrinsics_root); let mut header = Header { parent_hash, number, @@ -121,7 +122,6 @@ mod tests { ExecutionStrategy::NativeElseWasm, ).unwrap(); header = Header::decode(&mut &ret_data[..]).unwrap(); - println!("root after: {:?}", header.extrinsics_root); (vec![].and(&Block { header, extrinsics: transactions }), hash) } @@ -133,8 +133,8 @@ mod tests { genesis_hash, hex!("25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c").into(), vec![Transfer { - from: Keyring::One.to_raw_public().into(), - to: Keyring::Two.to_raw_public().into(), + from: AccountKeyring::One.into(), + to: AccountKeyring::Two.into(), amount: 69, nonce: 0, }] @@ -143,8 +143,10 @@ mod tests { #[test] fn construct_genesis_should_work_with_native() { - let mut storage = GenesisConfig::new_simple( - vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into()], 1000 + let mut storage = GenesisConfig::new(false, + vec![AuthorityKeyring::One.into(), AuthorityKeyring::Two.into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 1000 ).genesis_map(); let state_root = BlakeTwo256::trie_root(storage.clone().into_iter()); let block = construct_genesis_block::(state_root); @@ -169,8 +171,10 @@ mod tests { #[test] fn construct_genesis_should_work_with_wasm() { - let mut storage = GenesisConfig::new_simple( - vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into()], 1000 + let mut storage = GenesisConfig::new(false, + vec![AuthorityKeyring::One.into(), AuthorityKeyring::Two.into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 1000 ).genesis_map(); let state_root = BlakeTwo256::trie_root(storage.clone().into_iter()); let block = construct_genesis_block::(state_root); @@ -194,10 +198,11 @@ mod tests { } #[test] - #[should_panic] fn construct_genesis_with_bad_transaction_should_panic() { - let mut storage = GenesisConfig::new_simple( - vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into()], 68 + let mut storage = GenesisConfig::new(false, + vec![AuthorityKeyring::One.into(), AuthorityKeyring::Two.into()], + vec![AccountKeyring::One.into(), AccountKeyring::Two.into()], + 68 ).genesis_map(); let state_root = BlakeTwo256::trie_root(storage.clone().into_iter()); let block = construct_genesis_block::(state_root); @@ -208,7 +213,7 @@ mod tests { let (b1data, _b1hash) = block1(genesis_hash, &backend); let mut overlay = OverlayedChanges::default(); - let _ = state_machine::new( + let r = state_machine::new( &backend, Some(&InMemoryChangesTrieStorage::new()), &mut overlay, @@ -217,6 +222,7 @@ mod tests { &b1data, ).execute( ExecutionStrategy::NativeElseWasm, - ).unwrap(); + ); + assert!(r.is_err()); } } diff --git a/core/client/src/light/backend.rs b/core/client/src/light/backend.rs index 03d83c4e30fdc..a00d42e67394f 100644 --- a/core/client/src/light/backend.rs +++ b/core/client/src/light/backend.rs @@ -35,7 +35,7 @@ use hash_db::Hasher; use trie::MemoryDB; use heapsize::HeapSizeOf; -const IN_MEMORY_EXPECT_PROOF: &'static str = "InMemory state backend has Void error type and always suceeds; qed"; +const IN_MEMORY_EXPECT_PROOF: &str = "InMemory state backend has Void error type and always suceeds; qed"; /// Light client backend. pub struct Backend { diff --git a/core/client/src/light/fetcher.rs b/core/client/src/light/fetcher.rs index f9b28da0544d5..bb6624f91f1a9 100644 --- a/core/client/src/light/fetcher.rs +++ b/core/client/src/light/fetcher.rs @@ -390,12 +390,13 @@ impl<'a, H, Number, Hash> ChangesTrieRootsStorage for RootsStorage<'a, Number pub mod tests { use futures::future::{ok, err, FutureResult}; use parking_lot::Mutex; - use keyring::Keyring; use crate::client::tests::prepare_client_with_key_changes; use executor::{self, NativeExecutionDispatch}; use crate::error::Error as ClientError; - use test_client::{self, TestClient, blockchain::HeaderBackend}; - use test_client::runtime::{self, Hash, Block, Header}; + use test_client::{ + self, TestClient, blockchain::HeaderBackend, AccountKeyring, + runtime::{self, Hash, Block, Header} + }; use consensus::BlockOrigin; use crate::in_mem::{Blockchain as InMemoryBlockchain}; @@ -583,7 +584,7 @@ pub mod tests { // we're testing this test case here: // (1, 4, dave.clone(), vec![(4, 0), (1, 1), (1, 0)]), let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); - let dave = twox_128(&runtime::system::balance_of_key(Keyring::Dave.to_raw_public().into())).to_vec(); + let dave = twox_128(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); let dave = StorageKey(dave); // 'fetch' changes proof from remote node: @@ -695,7 +696,7 @@ pub mod tests { let (remote_client, remote_roots, _) = prepare_client_with_key_changes(); let local_cht_root = cht::compute_root::( 4, 0, remote_roots.iter().cloned().map(|ct| Ok(Some(ct)))).unwrap(); - let dave = twox_128(&runtime::system::balance_of_key(Keyring::Dave.to_raw_public().into())).to_vec(); + let dave = twox_128(&runtime::system::balance_of_key(AccountKeyring::Dave.into())).to_vec(); let dave = StorageKey(dave); // 'fetch' changes proof from remote node: diff --git a/core/consensus/aura/src/lib.rs b/core/consensus/aura/src/lib.rs index a2e1c3f871c64..3990535401bca 100644 --- a/core/consensus/aura/src/lib.rs +++ b/core/consensus/aura/src/lib.rs @@ -41,7 +41,7 @@ use runtime_primitives::{generic, generic::BlockId, Justification}; use runtime_primitives::traits::{ Block, Header, Digest, DigestItemFor, DigestItem, ProvideRuntimeApi }; -use primitives::{Ed25519AuthorityId, ed25519}; +use primitives::{ed25519, Pair}; use inherents::{InherentDataProviders, InherentData, RuntimeString}; use futures::{Stream, Future, IntoFuture, future}; @@ -60,6 +60,9 @@ pub use aura_slots::SlotDuration; pub use aura_primitives::*; pub use consensus_common::SyncOracle; +type AuthorityId = ed25519::Public; +type Signature = ed25519::Signature; + /// A handle to the network. This is generally implemented by providing some /// handle to a gossip service or similar. /// @@ -73,16 +76,17 @@ pub trait Network: Clone { } /// Get slot author for given block along with authorities. -fn slot_author(slot_num: u64, authorities: &[Ed25519AuthorityId]) -> Option { +fn slot_author(slot_num: u64, authorities: &[AuthorityId]) -> Option { if authorities.is_empty() { return None } let idx = slot_num % (authorities.len() as u64); assert!(idx <= usize::max_value() as u64, "It is impossible to have a vector with length beyond the address space; qed"); - let current_author = *authorities.get(idx as usize) + let current_author = authorities.get(idx as usize) .expect("authorities not empty; index constrained to list length;\ - this is a valid index; qed"); + this is a valid index; qed") + .clone(); Some(current_author) } @@ -109,22 +113,22 @@ fn inherent_to_common_error(err: RuntimeString) -> consensus_common::Error { pub trait CompatibleDigestItem: Sized { /// Construct a digest item which is a slot number and a signature on the /// hash. - fn aura_seal(slot_number: u64, signature: ed25519::Signature) -> Self; + fn aura_seal(slot_number: u64, signature: Signature) -> Self; /// If this item is an Aura seal, return the slot number and signature. - fn as_aura_seal(&self) -> Option<(u64, &ed25519::Signature)>; + fn as_aura_seal(&self) -> Option<(u64, Signature)>; } -impl CompatibleDigestItem for generic::DigestItem { +impl CompatibleDigestItem for generic::DigestItem { /// Construct a digest item which is a slot number and a signature on the /// hash. - fn aura_seal(slot_number: u64, signature: ed25519::Signature) -> Self { + fn aura_seal(slot_number: u64, signature: Signature) -> Self { generic::DigestItem::Seal(slot_number, signature) } /// If this item is an Aura seal, return the slot number and signature. - fn as_aura_seal(&self) -> Option<(u64, &ed25519::Signature)> { + fn as_aura_seal(&self) -> Option<(u64, Signature)> { match self { - generic::DigestItem::Seal(slot, ref sign) => Some((*slot, sign)), + generic::DigestItem::Seal(slot, ref sig) => Some((*slot, sig.clone().into())), _ => None } } @@ -162,7 +166,7 @@ pub fn start_aura_thread( Error: From + From + 'static, SO: SyncOracle + Send + Sync + Clone + 'static, OnExit: Future + Send + 'static, - DigestItemFor: CompatibleDigestItem + DigestItem + 'static, + DigestItemFor: CompatibleDigestItem + DigestItem + 'static, Error: ::std::error::Error + Send + From<::consensus_common::Error> + 'static, { let worker = AuraWorker { @@ -198,7 +202,7 @@ pub fn start_aura( I: BlockImport + Send + Sync + 'static, Error: From + From, SO: SyncOracle + Send + Sync + Clone, - DigestItemFor: CompatibleDigestItem + DigestItem, + DigestItemFor: CompatibleDigestItem + DigestItem, Error: ::std::error::Error + Send + 'static + From<::consensus_common::Error>, OnExit: Future, { @@ -232,7 +236,7 @@ impl SlotWorker for AuraWorker whe I: BlockImport + Send + Sync + 'static, Error: From + From, SO: SyncOracle + Send + Clone, - DigestItemFor: CompatibleDigestItem + DigestItem, + DigestItemFor: CompatibleDigestItem + DigestItem, Error: ::std::error::Error + Send + 'static + From<::consensus_common::Error>, { type OnSlot = Box + Send>; @@ -387,7 +391,7 @@ impl SlotWorker for AuraWorker whe /// if it's successful, returns the pre-header, the slot number, and the signat. // // FIXME #1018 needs misbehavior types -fn check_header(slot_now: u64, mut header: B::Header, hash: B::Hash, authorities: &[Ed25519AuthorityId]) +fn check_header(slot_now: u64, mut header: B::Header, hash: B::Hash, authorities: &[AuthorityId]) -> Result, String> where DigestItemFor: CompatibleDigestItem { @@ -395,7 +399,7 @@ fn check_header(slot_now: u64, mut header: B::Header, hash: B::Hash, a Some(x) => x, None => return Err(format!("Header {:?} is unsealed", hash)), }; - let (slot_num, &sig) = match digest_item.as_aura_seal() { + let (slot_num, sig) = match digest_item.as_aura_seal() { Some(x) => x, None => return Err(format!("Header {:?} is unsealed", hash)), }; @@ -416,7 +420,7 @@ fn check_header(slot_now: u64, mut header: B::Header, hash: B::Hash, a let to_sign = (slot_num, pre_hash).encode(); let public = ed25519::Public(expected_author.0); - if ed25519::verify_strong(&sig, &to_sign[..], public) { + if ed25519::Pair::verify(&sig, &to_sign[..], public) { Ok(CheckedHeader::Checked(header, slot_num, sig)) } else { Err(format!("Bad signature on {:?}", hash)) @@ -555,7 +559,7 @@ impl ExtraVerification for NothingExtra { impl Verifier for AuraVerifier where C: Authorities + ProvideRuntimeApi + Send + Sync, C::Api: BlockBuilderApi, - DigestItemFor: CompatibleDigestItem + DigestItem, + DigestItemFor: CompatibleDigestItem + DigestItem, E: ExtraVerification, { fn verify( @@ -564,7 +568,7 @@ impl Verifier for AuraVerifier where header: B::Header, justification: Option, mut body: Option>, - ) -> Result<(ImportBlock, Option>), String> { + ) -> Result<(ImportBlock, Option>), String> { let mut inherent_data = self.inherent_data_providers.create_inherent_data().map_err(String::from)?; let (timestamp_now, slot_now) = AuraSlotCompatible::extract_timestamp_and_slot(&inherent_data) .map_err(|e| format!("Could not extract timestamp and slot: {:?}", e))?; @@ -675,7 +679,7 @@ pub fn import_queue( B: Block, C: 'static + Authorities + ProvideRuntimeApi + Send + Sync, C::Api: BlockBuilderApi, - DigestItemFor: CompatibleDigestItem + DigestItem, + DigestItemFor: CompatibleDigestItem + DigestItem, E: 'static + ExtraVerification, { register_aura_inherent_data_provider(&inherent_data_providers, slot_duration.get())?; @@ -696,7 +700,7 @@ mod tests { use network::config::ProtocolConfig; use parking_lot::Mutex; use tokio::runtime::current_thread; - use keyring::Keyring; + use keyring::ed25519::Keyring; use client::BlockchainEvents; use test_client; @@ -711,7 +715,7 @@ mod tests { type Proposer = DummyProposer; type Error = Error; - fn init(&self, parent_header: &::Header, _authorities: &[Ed25519AuthorityId]) + fn init(&self, parent_header: &::Header, _authorities: &[AuthorityId]) -> Result { Ok(DummyProposer(parent_header.number + 1, self.0.clone())) diff --git a/core/consensus/common/src/error.rs b/core/consensus/common/src/error.rs index b4276a08b4f8b..58362b8e80e2e 100644 --- a/core/consensus/common/src/error.rs +++ b/core/consensus/common/src/error.rs @@ -18,6 +18,7 @@ use runtime_version::RuntimeVersion; use error_chain::{error_chain, error_chain_processing, impl_error_chain_processed, impl_extract_backtrace, impl_error_chain_kind}; +use primitives::ed25519::{Public, Signature}; error_chain! { errors { @@ -52,13 +53,13 @@ error_chain! { } /// Error checking signature - InvalidSignature(s: ::primitives::ed25519::Signature, a: ::primitives::Ed25519AuthorityId) { + InvalidSignature(s: Signature, a: Public) { description("Message signature is invalid"), display("Message signature {:?} by {:?} is invalid.", s, a), } /// Account is not an authority. - InvalidAuthority(a: ::primitives::Ed25519AuthorityId) { + InvalidAuthority(a: Public) { description("Message sender is not a valid authority"), display("Message sender {:?} is not a valid authority.", a), } diff --git a/core/consensus/common/src/offline_tracker.rs b/core/consensus/common/src/offline_tracker.rs index d9afb68416def..3c6755d9411d7 100644 --- a/core/consensus/common/src/offline_tracker.rs +++ b/core/consensus/common/src/offline_tracker.rs @@ -112,25 +112,25 @@ impl OfflineTracker { #[cfg(test)] mod tests { use super::*; - use primitives::Ed25519AuthorityId; + use primitives::ed25519::Public as AuthorityId; #[test] fn validator_offline() { - let mut tracker = OfflineTracker::::new(); - let v = [0; 32].into(); - let v2 = [1; 32].into(); - let v3 = [2; 32].into(); - tracker.note_round_end(v, true); - tracker.note_round_end(v2, true); - tracker.note_round_end(v3, true); + let mut tracker = OfflineTracker::::new(); + let v = AuthorityId::from_raw([0; 32]); + let v2 = AuthorityId::from_raw([1; 32]); + let v3 = AuthorityId::from_raw([2; 32]); + tracker.note_round_end(v.clone(), true); + tracker.note_round_end(v2.clone(), true); + tracker.note_round_end(v3.clone(), true); let slash_time = REPORT_TIME + Duration::from_secs(5); tracker.observed.get_mut(&v).unwrap().offline_since -= slash_time; tracker.observed.get_mut(&v2).unwrap().offline_since -= slash_time; - assert_eq!(tracker.reports(&[v, v2, v3]), vec![0, 1]); + assert_eq!(tracker.reports(&[v.clone(), v2.clone(), v3.clone()]), vec![0, 1]); - tracker.note_new_block(&[v, v3]); + tracker.note_new_block(&[v.clone(), v3.clone()]); assert_eq!(tracker.reports(&[v, v2, v3]), vec![0]); } } diff --git a/core/consensus/rhd/src/lib.rs b/core/consensus/rhd/src/lib.rs index 65401c92a9b72..e42083a40b309 100644 --- a/core/consensus/rhd/src/lib.rs +++ b/core/consensus/rhd/src/lib.rs @@ -762,7 +762,7 @@ fn check_justification_signed_message( let auth_id = sig.signer.clone().into(); if !authorities.contains(&auth_id) { return None } - if ed25519::verify_strong(&sig.signature, message, &sig.signer) { + if ed25519::Pair::verify(&sig.signature, message, &sig.signer) { Some(sig.signer.0) } else { None @@ -838,7 +838,7 @@ pub fn check_vote( fn check_action(action: Action, parent_hash: &B::Hash, sig: &LocalizedSignature) -> Result<(), Error> { let message = localized_encode(*parent_hash, action); - if ed25519::verify_strong(&sig.signature, &message, &sig.signer) { + if ed25519::Pair::verify(&sig.signature, &message, &sig.signer) { Ok(()) } else { Err(CommonErrorKind::InvalidSignature(sig.signature.into(), sig.signer.clone().into()).into()) @@ -1315,7 +1315,7 @@ mod tests { use runtime_primitives::testing::{Block as GenericTestBlock, Header as TestHeader}; use primitives::H256; - use self::keyring::Keyring; + use keyring::AuthorityKeyring; type TestBlock = GenericTestBlock<()>; @@ -1420,7 +1420,7 @@ mod tests { start_round: 0, })), round_timeout_multiplier: 10, - key: Arc::new(Keyring::One.into()), + key: Arc::new(AuthorityKeyring::One.into()), factory: DummyFactory } } @@ -1446,10 +1446,10 @@ mod tests { fn future_gets_preempted() { let client = FakeClient { authorities: vec![ - Keyring::One.to_raw_public().into(), - Keyring::Two.to_raw_public().into(), - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ], imported_heights: Mutex::new(HashSet::new()), }; @@ -1493,17 +1493,17 @@ mod tests { let hash = [0xff; 32].into(); let authorities = vec![ - Keyring::One.to_raw_public().into(), - Keyring::Two.to_raw_public().into(), - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ]; let authorities_keys = vec![ - Keyring::One.into(), - Keyring::Two.into(), - Keyring::Alice.into(), - Keyring::Eve.into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ]; let unchecked = UncheckedJustification(rhododendron::UncheckedJustification { @@ -1554,8 +1554,8 @@ mod tests { let parent_hash = Default::default(); let authorities = vec![ - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ]; let block = TestBlock { @@ -1563,7 +1563,7 @@ mod tests { extrinsics: Default::default() }; - let proposal = sign_message(rhododendron::Message::Propose(1, block.clone()), &Keyring::Alice.pair(), parent_hash);; + let proposal = sign_message(rhododendron::Message::Propose(1, block.clone()), &AuthorityKeyring::Alice.pair(), parent_hash);; if let rhododendron::LocalizedMessage::Propose(proposal) = proposal { assert!(check_proposal(&authorities, &parent_hash, &proposal).is_ok()); let mut invalid_round = proposal.clone(); @@ -1577,7 +1577,7 @@ mod tests { } // Not an authority - let proposal = sign_message::(rhododendron::Message::Propose(1, block), &Keyring::Bob.pair(), parent_hash);; + let proposal = sign_message::(rhododendron::Message::Propose(1, block), &AuthorityKeyring::Bob.pair(), parent_hash);; if let rhododendron::LocalizedMessage::Propose(proposal) = proposal { assert!(check_proposal(&authorities, &parent_hash, &proposal).is_err()); } else { @@ -1591,8 +1591,8 @@ mod tests { let hash: H256 = [0xff; 32].into(); let authorities = vec![ - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ]; let vote = sign_message::(rhododendron::Message::Vote(rhododendron::Vote::Prepare(1, hash)), &Keyring::Alice.pair(), parent_hash);; @@ -1618,10 +1618,10 @@ mod tests { fn drop_bft_future_does_not_deadlock() { let client = FakeClient { authorities: vec![ - Keyring::One.to_raw_public().into(), - Keyring::Two.to_raw_public().into(), - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ], imported_heights: Mutex::new(HashSet::new()), }; @@ -1643,10 +1643,10 @@ mod tests { fn bft_can_build_though_skipped() { let client = FakeClient { authorities: vec![ - Keyring::One.to_raw_public().into(), - Keyring::Two.to_raw_public().into(), - Keyring::Alice.to_raw_public().into(), - Keyring::Eve.to_raw_public().into(), + AuthorityKeyring::One.into(), + AuthorityKeyring::Two.into(), + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Eve.into(), ], imported_heights: Mutex::new(HashSet::new()), }; diff --git a/core/consensus/rhd/src/misbehaviour_check.rs b/core/consensus/rhd/src/misbehaviour_check.rs index a0c61bb4a6f39..58b36542f692b 100644 --- a/core/consensus/rhd/src/misbehaviour_check.rs +++ b/core/consensus/rhd/src/misbehaviour_check.rs @@ -74,8 +74,7 @@ pub fn evaluate_misbehavior( mod tests { use super::*; - use keyring::ed25519; - use keyring::Keyring; + use keyring::AuthorityKeyring; use rhododendron; use runtime_primitives::testing::{H256, Block as RawBlock}; @@ -110,7 +109,7 @@ mod tests { #[test] fn evaluates_double_prepare() { - let key: ed25519::Pair = Keyring::One.into(); + let key = AuthorityKeyring::One.pair(); let parent_hash = [0xff; 32].into(); let hash_1 = [0; 32].into(); let hash_2 = [1; 32].into(); @@ -127,7 +126,7 @@ mod tests { // same signature twice is not misbehavior. let signed = sign_prepare(&key, 1, hash_1, parent_hash); - assert!(evaluate_misbehavior::( + assert!(!evaluate_misbehavior::( &key.public().into(), parent_hash, &MisbehaviorKind::BftDoublePrepare( @@ -135,23 +134,23 @@ mod tests { signed, signed, ) - ) == false); + )); // misbehavior has wrong target. - assert!(evaluate_misbehavior::( - &Keyring::Two.to_raw_public().into(), + assert!(!evaluate_misbehavior::( + &AuthorityKeyring::Two.into(), parent_hash, &MisbehaviorKind::BftDoublePrepare( 1, sign_prepare(&key, 1, hash_1, parent_hash), sign_prepare(&key, 1, hash_2, parent_hash), ) - ) == false); + )); } #[test] fn evaluates_double_commit() { - let key: ed25519::Pair = Keyring::One.into(); + let key = AuthorityKeyring::One.pair(); let parent_hash = [0xff; 32].into(); let hash_1 = [0; 32].into(); let hash_2 = [1; 32].into(); @@ -168,7 +167,7 @@ mod tests { // same signature twice is not misbehavior. let signed = sign_commit(&key, 1, hash_1, parent_hash); - assert!(evaluate_misbehavior::( + assert!(!evaluate_misbehavior::( &key.public().into(), parent_hash, &MisbehaviorKind::BftDoubleCommit( @@ -176,17 +175,17 @@ mod tests { signed, signed, ) - ) == false); + )); // misbehavior has wrong target. - assert!(evaluate_misbehavior::( - &Keyring::Two.to_raw_public().into(), + assert!(!evaluate_misbehavior::( + &AuthorityKeyring::Two.into(), parent_hash, &MisbehaviorKind::BftDoubleCommit( 1, sign_commit(&key, 1, hash_1, parent_hash), sign_commit(&key, 1, hash_2, parent_hash), ) - ) == false); + )); } } diff --git a/core/executor/src/wasm_executor.rs b/core/executor/src/wasm_executor.rs index 044397ae3a803..7e459826989d4 100644 --- a/core/executor/src/wasm_executor.rs +++ b/core/executor/src/wasm_executor.rs @@ -28,7 +28,7 @@ use wasmi::memory_units::{Pages}; use state_machine::Externalities; use crate::error::{Error, ErrorKind, Result}; use crate::wasm_utils::UserError; -use primitives::{blake2_256, twox_128, twox_256, ed25519, sr25519}; +use primitives::{blake2_256, twox_128, twox_256, ed25519, sr25519, Pair}; use primitives::hexdisplay::HexDisplay; use primitives::sandbox as sandbox_primitives; use primitives::{H256, Blake2Hasher}; @@ -474,7 +474,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| UserError("Invalid attempt to get pubkey in ext_ed25519_verify"))?; let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| UserError("Invalid attempt to get message in ext_ed25519_verify"))?; - Ok(if ed25519::verify(&sig, &msg, &pubkey) { + Ok(if ed25519::Pair::verify_weak(&sig, &msg, &pubkey) { 0 } else { 5 @@ -487,7 +487,7 @@ impl_function_executor!(this: FunctionExecutor<'e, E>, this.memory.get_into(pubkey_data, &mut pubkey[..]).map_err(|_| UserError("Invalid attempt to get pubkey in ext_sr25519_verify"))?; let msg = this.memory.get(msg_data, msg_len as usize).map_err(|_| UserError("Invalid attempt to get message in ext_sr25519_verify"))?; - Ok(if sr25519::verify(&sig, &msg, &pubkey) { + Ok(if sr25519::Pair::verify_weak(&sig, &msg, &pubkey) { 0 } else { 5 @@ -759,7 +759,9 @@ impl WasmExecutor { #[cfg(test)] mod tests { use super::*; + use parity_codec::Encode; + use state_machine::TestExternalities; use hex_literal::{hex, hex_impl}; use primitives::map; @@ -875,7 +877,7 @@ mod tests { fn ed25519_verify_should_work() { let mut ext = TestExternalities::::default(); let test_code = include_bytes!("../wasm/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()); @@ -901,7 +903,7 @@ mod tests { fn sr25519_verify_should_work() { let mut ext = TestExternalities::::default(); let test_code = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/runtime_test.compact.wasm"); - let key = sr25519::Pair::from_seed(&blake2_256(b"test")); + let key = sr25519::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/core/finality-grandpa/primitives/src/lib.rs b/core/finality-grandpa/primitives/src/lib.rs index 9c20483305590..92bd0e4584c83 100644 --- a/core/finality-grandpa/primitives/src/lib.rs +++ b/core/finality-grandpa/primitives/src/lib.rs @@ -23,17 +23,19 @@ extern crate alloc; use parity_codec::{Encode, Decode}; -use substrate_primitives::Ed25519AuthorityId; +use substrate_primitives::ed25519; use sr_primitives::traits::{DigestFor, NumberFor}; use client::decl_runtime_apis; use rstd::vec::Vec; +use ed25519::Public as AuthorityId; + /// A scheduled change of authority set. #[cfg_attr(feature = "std", derive(Debug, PartialEq))] #[derive(Clone, Encode, Decode)] pub struct ScheduledChange { /// The new authorities after the change, along with their respective weights. - pub next_authorities: Vec<(Ed25519AuthorityId, u64)>, + pub next_authorities: Vec<(AuthorityId, u64)>, /// The number of blocks to delay. pub delay: N, } @@ -106,6 +108,6 @@ decl_runtime_apis! { /// When called at block B, it will return the set of authorities that should be /// used to finalize descendants of this block (B+1, B+2, ...). The block B itself /// is finalized by the authorities from block B-1. - fn grandpa_authorities() -> Vec<(Ed25519AuthorityId, u64)>; + fn grandpa_authorities() -> Vec<(AuthorityId, u64)>; } } diff --git a/core/finality-grandpa/src/authorities.rs b/core/finality-grandpa/src/authorities.rs index cc35cca822542..98b3973855b90 100644 --- a/core/finality-grandpa/src/authorities.rs +++ b/core/finality-grandpa/src/authorities.rs @@ -18,7 +18,7 @@ use fork_tree::ForkTree; use parking_lot::RwLock; -use substrate_primitives::Ed25519AuthorityId; +use substrate_primitives::ed25519; use grandpa::VoterSet; use parity_codec::{Encode, Decode}; use log::{debug, info}; @@ -28,6 +28,8 @@ use std::fmt::Debug; use std::ops::Add; use std::sync::Arc; +use ed25519::Public as AuthorityId; + /// A shared authority set. pub(crate) struct SharedAuthoritySet { inner: Arc>>, @@ -61,7 +63,7 @@ where N: Add + Ord + Clone + Debug, } /// Get the current authorities and their weights (for the current set ID). - pub(crate) fn current_authorities(&self) -> VoterSet { + pub(crate) fn current_authorities(&self) -> VoterSet { self.inner.read().current_authorities.iter().cloned().collect() } } @@ -85,7 +87,7 @@ pub(crate) struct Status { /// A set of authorities. #[derive(Debug, Clone, Encode, Decode, PartialEq)] pub(crate) struct AuthoritySet { - pub(crate) current_authorities: Vec<(Ed25519AuthorityId, u64)>, + pub(crate) current_authorities: Vec<(AuthorityId, u64)>, pub(crate) set_id: u64, // Tree of pending standard changes across forks. Standard changes are // enacted on finality and must be enacted (i.e. finalized) in-order across @@ -102,7 +104,7 @@ where H: PartialEq, N: Ord, { /// Get a genesis set with given authorities. - pub(crate) fn genesis(initial: Vec<(Ed25519AuthorityId, u64)>) -> Self { + pub(crate) fn genesis(initial: Vec<(AuthorityId, u64)>) -> Self { AuthoritySet { current_authorities: initial, set_id: 0, @@ -112,7 +114,7 @@ where H: PartialEq, } /// Get the current set id and a reference to the current authority set. - pub(crate) fn current(&self) -> (u64, &[(Ed25519AuthorityId, u64)]) { + pub(crate) fn current(&self) -> (u64, &[(AuthorityId, u64)]) { (self.set_id, &self.current_authorities[..]) } } @@ -379,7 +381,7 @@ pub(crate) enum DelayKind { #[derive(Debug, Clone, Encode, PartialEq)] pub(crate) struct PendingChange { /// The new authorities and weights to apply. - pub(crate) next_authorities: Vec<(Ed25519AuthorityId, u64)>, + pub(crate) next_authorities: Vec<(AuthorityId, u64)>, /// How deep in the chain the announcing block must be /// before the change is applied. pub(crate) delay: N, @@ -509,8 +511,8 @@ mod tests { pending_forced_changes: Vec::new(), }; - let set_a = vec![([1; 32].into(), 5)]; - let set_b = vec![([2; 32].into(), 5)]; + let set_a = vec![(AuthorityId([1; 32]), 5)]; + let set_b = vec![(AuthorityId([2; 32]), 5)]; // two competing changes at the same height on different forks let change_a = PendingChange { @@ -574,8 +576,8 @@ mod tests { pending_forced_changes: Vec::new(), }; - let set_a = vec![([1; 32].into(), 5)]; - let set_c = vec![([2; 32].into(), 5)]; + let set_a = vec![(AuthorityId([1; 32]), 5)]; + let set_c = vec![(AuthorityId([2; 32]), 5)]; // two competing changes at the same height on different forks let change_a = PendingChange { @@ -640,7 +642,7 @@ mod tests { pending_forced_changes: Vec::new(), }; - let set_a = vec![([1; 32].into(), 5)]; + let set_a = vec![(AuthorityId([1; 32]), 5)]; let change_a = PendingChange { next_authorities: set_a.clone(), @@ -676,8 +678,8 @@ mod tests { pending_forced_changes: Vec::new(), }; - let set_a = vec![([1; 32].into(), 5)]; - let set_b = vec![([2; 32].into(), 5)]; + let set_a = vec![(AuthorityId([1; 32]), 5)]; + let set_b = vec![(AuthorityId([2; 32]), 5)]; let change_a = PendingChange { next_authorities: set_a.clone(), diff --git a/core/finality-grandpa/src/aux_schema.rs b/core/finality-grandpa/src/aux_schema.rs index 930329344b8fb..eb187d877bf26 100644 --- a/core/finality-grandpa/src/aux_schema.rs +++ b/core/finality-grandpa/src/aux_schema.rs @@ -16,20 +16,20 @@ //! Schema for stuff in the aux-db. +use std::fmt::Debug; +use std::sync::Arc; use parity_codec::{Encode, Decode}; use client::backend::AuxStore; use client::error::{Result as ClientResult, Error as ClientError, ErrorKind as ClientErrorKind}; use fork_tree::ForkTree; use grandpa::round::State as RoundState; -use substrate_primitives::Ed25519AuthorityId; use log::{info, warn}; use crate::authorities::{AuthoritySet, SharedAuthoritySet, PendingChange, DelayKind}; use crate::consensus_changes::{SharedConsensusChanges, ConsensusChanges}; use crate::NewAuthoritySet; -use std::fmt::Debug; -use std::sync::Arc; +use substrate_primitives::ed25519::Public as AuthorityId; const VERSION_KEY: &[u8] = b"grandpa_schema_version"; const SET_STATE_KEY: &[u8] = b"grandpa_completed_round"; @@ -61,7 +61,7 @@ type V0VoterSetState = (u64, RoundState); #[derive(Debug, Clone, Encode, Decode, PartialEq)] struct V0PendingChange { - next_authorities: Vec<(Ed25519AuthorityId, u64)>, + next_authorities: Vec<(AuthorityId, u64)>, delay: N, canon_height: N, canon_hash: H, @@ -69,7 +69,7 @@ struct V0PendingChange { #[derive(Debug, Clone, Encode, Decode, PartialEq)] struct V0AuthoritySet { - current_authorities: Vec<(Ed25519AuthorityId, u64)>, + current_authorities: Vec<(AuthorityId, u64)>, set_id: u64, pending_changes: Vec>, } @@ -141,7 +141,7 @@ pub(crate) fn load_persistent( B: AuxStore, H: Debug + Decode + Encode + Clone + PartialEq, N: Debug + Decode + Encode + Clone + Ord, - G: FnOnce() -> ClientResult> + G: FnOnce() -> ClientResult> { let version: Option = load_decode(backend, VERSION_KEY)?; let consensus_changes = load_decode(backend, CONSENSUS_CHANGES_KEY)? diff --git a/core/finality-grandpa/src/communication.rs b/core/finality-grandpa/src/communication.rs index f392d3278b3a2..54de53e7bb29e 100644 --- a/core/finality-grandpa/src/communication.rs +++ b/core/finality-grandpa/src/communication.rs @@ -25,11 +25,12 @@ use futures::prelude::*; use futures::sync::mpsc; use log::{debug, trace}; use parity_codec::{Encode, Decode}; -use substrate_primitives::{ed25519, Ed25519AuthorityId}; +use substrate_primitives::{ed25519, Pair}; use runtime_primitives::traits::Block as BlockT; use tokio::timer::Interval; use crate::{Error, Network, Message, SignedMessage, Commit, CompactCommit, GossipMessage, FullCommitMessage, VoteOrPrecommitMessage}; +use ed25519::{Public as AuthorityId, Signature as AuthoritySignature}; fn localized_payload(round: u64, set_id: u64, message: &E) -> Vec { (message, round, set_id).encode() @@ -242,14 +243,14 @@ impl> Network for BroadcastHandle { // check a message. pub(crate) fn check_message_sig( message: &Message, - id: &Ed25519AuthorityId, - signature: &ed25519::Signature, + id: &AuthorityId, + signature: &AuthoritySignature, round: u64, set_id: u64, ) -> Result<(), ()> { - let as_public = ed25519::Public::from_raw(id.0); + let as_public = AuthorityId::from_raw(id.0); let encoded_raw = localized_payload(round, set_id, message); - if ed25519::verify_strong(signature, &encoded_raw, as_public) { + if ed25519::Pair::verify(signature, &encoded_raw, as_public) { Ok(()) } else { debug!(target: "afg", "Bad signature on message from {:?}", id); @@ -261,7 +262,7 @@ pub(crate) fn check_message_sig( /// the output stream checks signatures also. pub(crate) fn checked_message_stream( inner: S, - voters: Arc>, + voters: Arc>, ) -> impl Stream,Error=Error> where S: Stream,Error=()> @@ -297,7 +298,7 @@ pub(crate) fn checked_message_stream( pub(crate) struct OutgoingMessages> { round: u64, set_id: u64, - locals: Option<(Arc, Ed25519AuthorityId)>, + locals: Option<(Arc, AuthorityId)>, sender: mpsc::UnboundedSender>, network: N, } @@ -309,7 +310,7 @@ impl> Sink for OutgoingMessages fn start_send(&mut self, msg: Message) -> StartSend, Error> { // when locals exist, sign messages on import - if let Some((ref pair, local_id)) = self.locals { + if let Some((ref pair, ref local_id)) = self.locals { let encoded = localized_payload(self.round, self.set_id, &msg); let signature = pair.sign(&encoded[..]); @@ -317,7 +318,7 @@ impl> Sink for OutgoingMessages let signed = SignedMessage:: { message: msg, signature, - id: local_id, + id: local_id.clone(), }; let message = GossipMessage::VoteOrPrecommit(VoteOrPrecommitMessage:: { @@ -361,7 +362,7 @@ pub(crate) fn outgoing_messages>( round: u64, set_id: u64, local_key: Option>, - voters: Arc>, + voters: Arc>, network: N, ) -> ( impl Stream,Error=Error>, @@ -369,7 +370,7 @@ pub(crate) fn outgoing_messages>( ) { let locals = local_key.and_then(|pair| { let public = pair.public(); - let id = Ed25519AuthorityId(public.0); + let id = AuthorityId(public.0); if voters.contains_key(&id) { Some((pair, id)) } else { @@ -395,7 +396,7 @@ pub(crate) fn outgoing_messages>( fn check_compact_commit( msg: CompactCommit, - voters: &VoterSet, + voters: &VoterSet, ) -> Option> { if msg.precommits.len() != msg.auth_data.len() || msg.precommits.is_empty() { debug!(target: "afg", "Skipping malformed compact commit"); @@ -417,7 +418,7 @@ fn check_compact_commit( /// messages. pub(crate) fn checked_commit_stream( inner: S, - voters: Arc>, + voters: Arc>, ) -> impl Stream),Error=Error> where S: Stream,Error=()> diff --git a/core/finality-grandpa/src/environment.rs b/core/finality-grandpa/src/environment.rs index 857d6eafd7113..a9b5a43d01144 100644 --- a/core/finality-grandpa/src/environment.rs +++ b/core/finality-grandpa/src/environment.rs @@ -33,7 +33,7 @@ use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{ As, Block as BlockT, Header as HeaderT, NumberFor, One, Zero, }; -use substrate_primitives::{Blake2Hasher, ed25519,Ed25519AuthorityId, H256}; +use substrate_primitives::{Blake2Hasher, ed25519, H256, Pair}; use crate::{ Commit, Config, Error, Network, Precommit, Prevote, @@ -45,6 +45,8 @@ use crate::consensus_changes::SharedConsensusChanges; use crate::justification::GrandpaJustification; use crate::until_imported::UntilVoteTargetImported; +use ed25519::Public as AuthorityId; + /// Data about a completed round. pub(crate) type CompletedRound = (u64, RoundState); @@ -75,7 +77,7 @@ impl LastCompletedRound { /// The environment we run GRANDPA in. pub(crate) struct Environment, RA> { pub(crate) inner: Arc>, - pub(crate) voters: Arc>, + pub(crate) voters: Arc>, pub(crate) config: Config, pub(crate) authority_set: SharedAuthoritySet>, pub(crate) consensus_changes: SharedConsensusChanges>, @@ -205,7 +207,7 @@ impl, N, RA> voter::Environment: BlockNumberOps, { type Timer = Box + Send>; - type Id = Ed25519AuthorityId; + type Id = AuthorityId; type Signature = ed25519::Signature; // regular round message streams diff --git a/core/finality-grandpa/src/finality_proof.rs b/core/finality-grandpa/src/finality_proof.rs index eef705c4ff714..daebe3b72a585 100644 --- a/core/finality-grandpa/src/finality_proof.rs +++ b/core/finality-grandpa/src/finality_proof.rs @@ -42,7 +42,8 @@ use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{ NumberFor, Block as BlockT, Header as HeaderT, One, }; -use substrate_primitives::{Ed25519AuthorityId, H256}; +use substrate_primitives::{ed25519, H256}; +use ed25519::Public as AuthorityId; use crate::justification::GrandpaJustification; @@ -189,7 +190,7 @@ fn do_check_finality_proof, C, J>( call_data: vec![], retry_count: None, })?; - let grandpa_authorities: Vec<(Ed25519AuthorityId, u64)> = Decode::decode(&mut &grandpa_authorities[..]) + let grandpa_authorities: Vec<(AuthorityId, u64)> = Decode::decode(&mut &grandpa_authorities[..]) .ok_or_else(|| ClientErrorKind::BadJustification("failed to decode GRANDPA authorities set proof".into()))?; // and now check justification @@ -222,7 +223,7 @@ trait ProvableJustification: Encode + Decode { fn target_block(&self) -> (Header::Number, Header::Hash); /// Verify justification with respect to authorities set and authorities set id. - fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()>; + fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()>; } impl> ProvableJustification for GrandpaJustification @@ -233,7 +234,7 @@ impl> ProvableJustification for GrandpaJ (self.commit.target_number, self.commit.target_hash) } - fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()> { + fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()> { GrandpaJustification::verify(self, set_id, authorities) } } @@ -253,12 +254,12 @@ mod tests { impl ProvableJustification
for ValidFinalityProof { fn target_block(&self) -> (u64, H256) { (3, header(3).hash()) } - fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()> { + fn verify(&self, set_id: u64, authorities: &VoterSet) -> ClientResult<()> { assert_eq!(set_id, 1); assert_eq!(authorities, &vec![ - (Ed25519AuthorityId([1u8; 32]), 1), - (Ed25519AuthorityId([2u8; 32]), 2), - (Ed25519AuthorityId([3u8; 32]), 3), + (AuthorityId([1u8; 32]), 1), + (AuthorityId([2u8; 32]), 2), + (AuthorityId([3u8; 32]), 3), ].into_iter().collect()); Ok(()) } @@ -387,7 +388,7 @@ mod tests { impl ProvableJustification
for InvalidFinalityProof { fn target_block(&self) -> (u64, H256) { (3, header(3).hash()) } - fn verify(&self, _set_id: u64, _authorities: &VoterSet) -> ClientResult<()> { + fn verify(&self, _set_id: u64, _authorities: &VoterSet) -> ClientResult<()> { Err(ClientErrorKind::Backend("test error".into()).into()) } } @@ -415,9 +416,9 @@ mod tests { .unwrap().unwrap(); assert_eq!(do_check_finality_proof::( |_| Ok(vec![ - (Ed25519AuthorityId([1u8; 32]), 1u64), - (Ed25519AuthorityId([2u8; 32]), 2u64), - (Ed25519AuthorityId([3u8; 32]), 3u64), + (AuthorityId([1u8; 32]), 1u64), + (AuthorityId([2u8; 32]), 2u64), + (AuthorityId([3u8; 32]), 3u64), ].encode()), header(1), (2, header(2).hash()), diff --git a/core/finality-grandpa/src/import.rs b/core/finality-grandpa/src/import.rs index 3f4dbb3650a86..7e1582645f7f7 100644 --- a/core/finality-grandpa/src/import.rs +++ b/core/finality-grandpa/src/import.rs @@ -36,7 +36,7 @@ use runtime_primitives::traits::{ Block as BlockT, DigestFor, DigestItemFor, DigestItem, Header as HeaderT, NumberFor, ProvideRuntimeApi, }; -use substrate_primitives::{H256, Ed25519AuthorityId, Blake2Hasher}; +use substrate_primitives::{H256, ed25519, Blake2Hasher}; use crate::{Error, CommandOrError, NewAuthoritySet, VoterCommand}; use crate::authorities::{AuthoritySet, SharedAuthoritySet, DelayKind, PendingChange}; @@ -44,6 +44,8 @@ use crate::consensus_changes::SharedConsensusChanges; use crate::environment::{finalize_block, is_descendent_of}; use crate::justification::GrandpaJustification; +use ed25519::Public as AuthorityId; + /// A block-import handler for GRANDPA. /// /// This scans each imported block for signals of changing authority set. @@ -67,7 +69,7 @@ impl, RA, PRA> JustificationImport B: Backend + 'static, E: CallExecutor + 'static + Clone + Send + Sync, DigestFor: Encode, - DigestItemFor: DigestItem, + DigestItemFor: DigestItem, RA: Send + Sync, PRA: ProvideRuntimeApi, PRA::Api: GrandpaApi, @@ -161,7 +163,7 @@ impl, RA, PRA> GrandpaBlockImport + 'static, E: CallExecutor + 'static + Clone + Send + Sync, DigestFor: Encode, - DigestItemFor: DigestItem, + DigestItemFor: DigestItem, RA: Send + Sync, PRA: ProvideRuntimeApi, PRA::Api: GrandpaApi, @@ -379,14 +381,14 @@ impl, RA, PRA> BlockImport B: Backend + 'static, E: CallExecutor + 'static + Clone + Send + Sync, DigestFor: Encode, - DigestItemFor: DigestItem, + DigestItemFor: DigestItem, RA: Send + Sync, PRA: ProvideRuntimeApi, PRA::Api: GrandpaApi, { type Error = ConsensusError; - fn import_block(&self, mut block: ImportBlock, new_authorities: Option>) + fn import_block(&self, mut block: ImportBlock, new_authorities: Option>) -> Result { let hash = block.post_header().hash(); diff --git a/core/finality-grandpa/src/justification.rs b/core/finality-grandpa/src/justification.rs index 52ce9006e19ab..d837e6a30862e 100644 --- a/core/finality-grandpa/src/justification.rs +++ b/core/finality-grandpa/src/justification.rs @@ -25,11 +25,13 @@ use grandpa::VoterSet; use grandpa::{Error as GrandpaError}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{NumberFor, Block as BlockT, Header as HeaderT}; -use substrate_primitives::{H256, Ed25519AuthorityId, Blake2Hasher}; +use substrate_primitives::{H256, ed25519, Blake2Hasher}; use crate::{Commit, Error}; use crate::communication; +use ed25519::Public as AuthorityId; + /// A GRANDPA justification for block finality, it includes a commit message and /// an ancestry proof including all headers routing all precommit target blocks /// to the commit target block. Due to the current voting strategy the precommit @@ -95,7 +97,7 @@ impl> GrandpaJustification { pub(crate) fn decode_and_verify( encoded: Vec, set_id: u64, - voters: &VoterSet, + voters: &VoterSet, ) -> Result, ClientError> where NumberFor: grandpa::BlockNumberOps, { @@ -106,7 +108,7 @@ impl> GrandpaJustification { } /// Validate the commit and the votes' ancestry proofs. - pub(crate) fn verify(&self, set_id: u64, voters: &VoterSet) -> Result<(), ClientError> + pub(crate) fn verify(&self, set_id: u64, voters: &VoterSet) -> Result<(), ClientError> where NumberFor: grandpa::BlockNumberOps, { diff --git a/core/finality-grandpa/src/lib.rs b/core/finality-grandpa/src/lib.rs index 07f35ebc63763..67953489e8905 100644 --- a/core/finality-grandpa/src/lib.rs +++ b/core/finality-grandpa/src/lib.rs @@ -68,7 +68,7 @@ use runtime_primitives::traits::{ use fg_primitives::GrandpaApi; use inherents::InherentDataProviders; use runtime_primitives::generic::BlockId; -use substrate_primitives::{ed25519, H256, Ed25519AuthorityId, Blake2Hasher}; +use substrate_primitives::{ed25519, H256, Blake2Hasher, Pair}; use substrate_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_WARN}; use srml_finality_tracker; @@ -106,6 +106,8 @@ pub use finality_proof::{prove_finality, check_finality_proof}; use import::GrandpaBlockImport; use until_imported::UntilCommitBlocksImported; +use ed25519::{Public as AuthorityId, Signature as AuthoritySignature}; + #[cfg(test)] mod tests; @@ -118,8 +120,8 @@ pub type Message = grandpa::Message<::Hash, NumberFor = grandpa::SignedMessage< ::Hash, NumberFor, - ed25519::Signature, - Ed25519AuthorityId, + AuthoritySignature, + AuthorityId, >; /// Grandpa gossip message type. @@ -148,15 +150,15 @@ pub type Precommit = grandpa::Precommit<::Hash, NumberFo pub type Commit = grandpa::Commit< ::Hash, NumberFor, - ed25519::Signature, - Ed25519AuthorityId + AuthoritySignature, + AuthorityId >; /// A compact commit message for this chain's block type. pub type CompactCommit = grandpa::CompactCommit< ::Hash, NumberFor, - ed25519::Signature, - Ed25519AuthorityId + AuthoritySignature, + AuthorityId >; /// Network level commit message with topic information. @@ -560,7 +562,7 @@ pub(crate) struct NewAuthoritySet { pub(crate) canon_number: N, pub(crate) canon_hash: H, pub(crate) set_id: u64, - pub(crate) authorities: Vec<(Ed25519AuthorityId, u64)>, + pub(crate) authorities: Vec<(AuthorityId, u64)>, } /// Commands issued to the voter. @@ -684,16 +686,16 @@ pub fn block_import, RA, PRA>( fn committer_communication, B, E, N, RA>( local_key: Option>, set_id: u64, - voters: &Arc>, + voters: &Arc>, client: &Arc>, network: &N, ) -> ( impl Stream< - Item = (u64, ::grandpa::CompactCommit, ed25519::Signature, Ed25519AuthorityId>), + Item = (u64, ::grandpa::CompactCommit, AuthoritySignature, AuthorityId>), Error = CommandOrError>, >, impl Sink< - SinkItem = (u64, ::grandpa::Commit, ed25519::Signature, Ed25519AuthorityId>), + SinkItem = (u64, ::grandpa::Commit, AuthoritySignature, AuthorityId>), SinkError = CommandOrError>, >, ) where @@ -702,7 +704,7 @@ fn committer_communication, B, E, N, RA>( N: Network, RA: Send + Sync, NumberFor: BlockNumberOps, - DigestItemFor: DigestItem, + DigestItemFor: DigestItem, { // verification stream let commit_in = crate::communication::checked_commit_stream::( @@ -773,7 +775,7 @@ pub fn run_grandpa, N, RA>( N::In: Send + 'static, NumberFor: BlockNumberOps, DigestFor: Encode, - DigestItemFor: DigestItem, + DigestItemFor: DigestItem, RA: Send + Sync + 'static, { use futures::future::{self, Loop as FutureLoop}; diff --git a/core/finality-grandpa/src/tests.rs b/core/finality-grandpa/src/tests.rs index 3eb7d556551ec..9aed819b25036 100644 --- a/core/finality-grandpa/src/tests.rs +++ b/core/finality-grandpa/src/tests.rs @@ -22,7 +22,7 @@ use network::test::{PassThroughVerifier}; use network::config::{ProtocolConfig, Roles}; use parking_lot::Mutex; use tokio::runtime::current_thread; -use keyring::Keyring; +use keyring::AuthorityKeyring; use client::{ BlockchainEvents, error::Result, blockchain::Backend as BlockchainBackend, @@ -238,13 +238,13 @@ impl Network for MessageRouting { #[derive(Default, Clone)] struct TestApi { - genesis_authorities: Vec<(Ed25519AuthorityId, u64)>, + genesis_authorities: Vec<(AuthorityId, u64)>, scheduled_changes: Arc>>>, forced_changes: Arc)>>>, } impl TestApi { - fn new(genesis_authorities: Vec<(Ed25519AuthorityId, u64)>) -> Self { + fn new(genesis_authorities: Vec<(AuthorityId, u64)>) -> Self { TestApi { genesis_authorities, scheduled_changes: Arc::new(Mutex::new(HashMap::new())), @@ -282,7 +282,7 @@ impl Core for RuntimeApi { _: ExecutionContext, _: Option<()>, _: Vec, - ) -> Result>> { + ) -> Result>> { unimplemented!("Not required for testing!") } @@ -327,7 +327,7 @@ impl GrandpaApi for RuntimeApi { _: ExecutionContext, _: Option<()>, _: Vec, - ) -> Result>> { + ) -> Result>> { if at == &BlockId::Number(0) { Ok(self.inner.genesis_authorities.clone()).map(NativeOrEncoded::Native) } else { @@ -374,9 +374,9 @@ impl GrandpaApi for RuntimeApi { const TEST_GOSSIP_DURATION: Duration = Duration::from_millis(500); const TEST_ROUTING_INTERVAL: Duration = Duration::from_millis(50); -fn make_ids(keys: &[Keyring]) -> Vec<(Ed25519AuthorityId, u64)> { +fn make_ids(keys: &[AuthorityKeyring]) -> Vec<(AuthorityId, u64)> { keys.iter() - .map(|key| Ed25519AuthorityId(key.to_raw_public())) + .map(|key| AuthorityId(key.to_raw_public())) .map(|id| (id, 1)) .collect() } @@ -386,7 +386,7 @@ fn make_ids(keys: &[Keyring]) -> Vec<(Ed25519AuthorityId, u64)> { fn run_to_completion_with( blocks: u64, net: Arc>, - peers: &[Keyring], + peers: &[AuthorityKeyring], before_waiting: F, ) -> u64 { use parking_lot::RwLock; @@ -462,14 +462,14 @@ fn run_to_completion_with( highest_finalized } -fn run_to_completion(blocks: u64, net: Arc>, peers: &[Keyring]) -> u64 { +fn run_to_completion(blocks: u64, net: Arc>, peers: &[AuthorityKeyring]) -> u64 { run_to_completion_with(blocks, net, peers, || {}) } #[test] fn finalize_3_voters_no_observers() { let _ = env_logger::try_init(); - let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let voters = make_ids(peers); let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); @@ -491,7 +491,7 @@ fn finalize_3_voters_no_observers() { #[test] fn finalize_3_voters_1_observer() { - let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let voters = make_ids(peers); let mut net = GrandpaTestNet::new(TestApi::new(voters), 4); @@ -554,24 +554,24 @@ fn finalize_3_voters_1_observer() { fn transition_3_voters_twice_1_observer() { let _ = env_logger::try_init(); let peers_a = &[ - Keyring::Alice, - Keyring::Bob, - Keyring::Charlie, + AuthorityKeyring::Alice, + AuthorityKeyring::Bob, + AuthorityKeyring::Charlie, ]; let peers_b = &[ - Keyring::Dave, - Keyring::Eve, - Keyring::Ferdie, + AuthorityKeyring::Dave, + AuthorityKeyring::Eve, + AuthorityKeyring::Ferdie, ]; let peers_c = &[ - Keyring::Alice, - Keyring::Eve, - Keyring::Two, + AuthorityKeyring::Alice, + AuthorityKeyring::Eve, + AuthorityKeyring::Two, ]; - let observer = &[Keyring::One]; + let observer = &[AuthorityKeyring::One]; let genesis_voters = make_ids(peers_a); @@ -719,11 +719,11 @@ fn transition_3_voters_twice_1_observer() { #[test] fn justification_is_emitted_when_consensus_data_changes() { - let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let mut net = GrandpaTestNet::new(TestApi::new(make_ids(peers)), 3); // import block#1 WITH consensus data change - let new_authorities = vec![Ed25519AuthorityId::from([42; 32])]; + let new_authorities = vec![AuthorityId::from_raw([42; 32])]; net.peer(0).push_authorities_change_block(new_authorities); net.sync(); let net = Arc::new(Mutex::new(net)); @@ -736,7 +736,7 @@ fn justification_is_emitted_when_consensus_data_changes() { #[test] fn justification_is_generated_periodically() { - let peers = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let peers = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let voters = make_ids(peers); let mut net = GrandpaTestNet::new(TestApi::new(voters), 3); @@ -775,8 +775,8 @@ fn consensus_changes_works() { #[test] fn sync_justifications_on_change_blocks() { - let peers_a = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; - let peers_b = &[Keyring::Alice, Keyring::Bob]; + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let peers_b = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob]; let voters = make_ids(peers_b); // 4 peers, 3 of them are authorities and participate in grandpa @@ -825,13 +825,13 @@ fn sync_justifications_on_change_blocks() { fn finalizes_multiple_pending_changes_in_order() { let _ = env_logger::try_init(); - let peers_a = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; - let peers_b = &[Keyring::Dave, Keyring::Eve, Keyring::Ferdie]; - let peers_c = &[Keyring::Dave, Keyring::Alice, Keyring::Bob]; + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let peers_b = &[AuthorityKeyring::Dave, AuthorityKeyring::Eve, AuthorityKeyring::Ferdie]; + let peers_c = &[AuthorityKeyring::Dave, AuthorityKeyring::Alice, AuthorityKeyring::Bob]; let all_peers = &[ - Keyring::Alice, Keyring::Bob, Keyring::Charlie, - Keyring::Dave, Keyring::Eve, Keyring::Ferdie, + AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie, + AuthorityKeyring::Dave, AuthorityKeyring::Eve, AuthorityKeyring::Ferdie, ]; let genesis_voters = make_ids(peers_a); @@ -883,7 +883,7 @@ fn finalizes_multiple_pending_changes_in_order() { #[test] fn doesnt_vote_on_the_tip_of_the_chain() { - let peers_a = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let voters = make_ids(peers_a); let api = TestApi::new(voters); let mut net = GrandpaTestNet::new(api, 3); @@ -907,8 +907,8 @@ fn doesnt_vote_on_the_tip_of_the_chain() { #[test] fn force_change_to_new_set() { // two of these guys are offline. - let genesis_authorities = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie, Keyring::One, Keyring::Two]; - let peers_a = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; + let genesis_authorities = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie, AuthorityKeyring::One, AuthorityKeyring::Two]; + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; let api = TestApi::new(make_ids(genesis_authorities)); let voters = make_ids(peers_a); @@ -960,8 +960,8 @@ fn force_change_to_new_set() { #[test] fn allows_reimporting_change_blocks() { - let peers_a = &[Keyring::Alice, Keyring::Bob, Keyring::Charlie]; - let peers_b = &[Keyring::Alice, Keyring::Bob]; + let peers_a = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob, AuthorityKeyring::Charlie]; + let peers_b = &[AuthorityKeyring::Alice, AuthorityKeyring::Bob]; let voters = make_ids(peers_a); let api = TestApi::new(voters); let net = GrandpaTestNet::new(api.clone(), 3); diff --git a/core/finality-grandpa/src/until_imported.rs b/core/finality-grandpa/src/until_imported.rs index ceeb819ed0881..4b867c18c8e2b 100644 --- a/core/finality-grandpa/src/until_imported.rs +++ b/core/finality-grandpa/src/until_imported.rs @@ -28,7 +28,7 @@ use futures::prelude::*; use futures::stream::Fuse; use parking_lot::Mutex; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor}; -use substrate_primitives::Ed25519AuthorityId; +use substrate_primitives::ed25519::Public as AuthorityId; use tokio::timer::Interval; use std::collections::{HashMap, VecDeque}; @@ -199,7 +199,7 @@ impl Stream for UntilImported } } -fn warn_authority_wrong_target(hash: H, id: Ed25519AuthorityId) { +fn warn_authority_wrong_target(hash: H, id: AuthorityId) { warn!( target: "afg", "Authority {:?} signed GRANDPA message with \ diff --git a/core/keyring/src/ed25519.rs b/core/keyring/src/ed25519.rs index 49a073c086d4e..188bf5352c9a4 100644 --- a/core/keyring/src/ed25519.rs +++ b/core/keyring/src/ed25519.rs @@ -19,10 +19,14 @@ use std::collections::HashMap; use std::ops::Deref; use lazy_static::lazy_static; -use hex_literal::{hex, hex_impl}; -use substrate_primitives::ed25519::{Pair, Public, Signature}; +use substrate_primitives::{ed25519::{Pair, Public, Signature}, Pair as _Pair, H256}; pub use substrate_primitives::ed25519; +/// The root phrase for our test keys. +/// +/// This is the same phrase that's in node::cli, but shouldn't need to be. +pub const DEV_PHRASE: &str = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; + /// Set of test accounts. #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub enum Keyring { @@ -37,7 +41,7 @@ pub enum Keyring { } impl Keyring { - pub fn from_public(who: Public) -> Option { + pub fn from_public(who: &Public) -> Option { [ Keyring::Alice, Keyring::Bob, @@ -49,17 +53,25 @@ impl Keyring { Keyring::Two, ].iter() .map(|i| *i) - .find(|&k| Public::from(k) == who) + .find(|&k| &Public::from(k) == who) } pub fn from_raw_public(who: [u8; 32]) -> Option { - Self::from_public(Public::from_raw(who)) + Self::from_public(&Public::from_raw(who)) } pub fn to_raw_public(self) -> [u8; 32] { *Public::from(self).as_array_ref() } + pub fn from_h256_public(who: H256) -> Option { + Self::from_public(&Public::from_raw(who.into())) + } + + pub fn to_h256_public(self) -> H256 { + Public::from(self).as_array_ref().into() + } + pub fn to_raw_public_vec(self) -> Vec { Public::from(self).to_raw_vec() } @@ -69,16 +81,8 @@ impl Keyring { } pub fn pair(self) -> Pair { - match self { - Keyring::Alice => Pair::from_seed(b"Alice "), - Keyring::Bob => Pair::from_seed(b"Bob "), - Keyring::Charlie => Pair::from_seed(b"Charlie "), - Keyring::Dave => Pair::from_seed(b"Dave "), - Keyring::Eve => Pair::from_seed(b"Eve "), - Keyring::Ferdie => Pair::from_seed(b"Ferdie "), - Keyring::One => Pair::from_seed(b"12345678901234567890123456789012"), - Keyring::Two => Pair::from_seed(&hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")), - } + Pair::from_string(&format!("{}//{}", DEV_PHRASE, <&'static str>::from(self)), None) + .expect("static values are known good; qed") } } @@ -91,8 +95,8 @@ impl From for &'static str { Keyring::Dave => "Dave", Keyring::Eve => "Eve", Keyring::Ferdie => "Ferdie", - Keyring::One => "one", - Keyring::Two => "two", + Keyring::One => "One", + Keyring::Two => "Two", } } } @@ -134,6 +138,12 @@ impl From for [u8; 32] { } } +impl From for H256 { + fn from(k: Keyring) -> Self { + (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref().into() + } +} + impl From for &'static [u8; 32] { fn from(k: Keyring) -> Self { (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref() @@ -162,12 +172,12 @@ impl Deref for Keyring { #[cfg(test)] mod tests { use super::*; - use ed25519::Verifiable; + use substrate_primitives::{ed25519::Pair, Pair as _Pair}; #[test] fn should_work() { - assert!(Keyring::Alice.sign(b"I am Alice!").verify(b"I am Alice!", Keyring::Alice)); - assert!(!Keyring::Alice.sign(b"I am Alice!").verify(b"I am Bob!", Keyring::Alice)); - assert!(!Keyring::Alice.sign(b"I am Alice!").verify(b"I am Alice!", Keyring::Bob)); + assert!(Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Alice!", Keyring::Alice)); + assert!(!Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Bob!", Keyring::Alice)); + assert!(!Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Alice!", Keyring::Bob)); } } diff --git a/core/keyring/src/lib.rs b/core/keyring/src/lib.rs index faed637e03da6..5cf38401d0823 100644 --- a/core/keyring/src/lib.rs +++ b/core/keyring/src/lib.rs @@ -22,7 +22,15 @@ pub mod sr25519; /// Test account crypto for ed25519. pub mod ed25519; -/// The Ed25519 keyring. -/// -/// This is deprecated: use `ed25519::Keyring` instead. -pub use ed25519::Keyring; +/// Convenience export: Sr25519's Keyring is exposed as `AccountKeyring`, +/// since it tends to be used for accounts. +pub use sr25519::Keyring as AccountKeyring; + +/// Convenience export: Ed25519's Keyring is exposed as `AuthorityKeyring`, +/// since it tends to be used for authorities (session keys &c.). +pub use ed25519::Keyring as AuthorityKeyring; + +pub mod test { + /// The keyring for use with accounts when using the test runtime. + pub use super::ed25519::Keyring as AccountKeyring; +} diff --git a/core/keyring/src/sr25519.rs b/core/keyring/src/sr25519.rs index e63830559353f..de2146020c638 100644 --- a/core/keyring/src/sr25519.rs +++ b/core/keyring/src/sr25519.rs @@ -19,10 +19,14 @@ use std::collections::HashMap; use std::ops::Deref; use lazy_static::lazy_static; -use hex_literal::{hex, hex_impl}; -use substrate_primitives::sr25519::{Pair, Public, Signature}; +use substrate_primitives::{sr25519::{Pair, Public, Signature}, Pair as _Pair, H256}; pub use substrate_primitives::sr25519; +/// The root phrase for our test keys. +/// +/// This is the same phrase that's in node::cli, but shouldn't need to be. +pub const DEV_PHRASE: &str = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; + /// Set of test accounts. #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub enum Keyring { @@ -37,7 +41,7 @@ pub enum Keyring { } impl Keyring { - pub fn from_public(who: Public) -> Option { + pub fn from_public(who: &Public) -> Option { [ Keyring::Alice, Keyring::Bob, @@ -49,17 +53,25 @@ impl Keyring { Keyring::Two, ].iter() .map(|i| *i) - .find(|&k| Public::from(k) == who) + .find(|&k| &Public::from(k) == who) } pub fn from_raw_public(who: [u8; 32]) -> Option { - Self::from_public(Public::from_raw(who)) + Self::from_public(&Public::from_raw(who)) } pub fn to_raw_public(self) -> [u8; 32] { *Public::from(self).as_array_ref() } + pub fn from_h256_public(who: H256) -> Option { + Self::from_public(&Public::from_raw(who.into())) + } + + pub fn to_h256_public(self) -> H256 { + Public::from(self).as_array_ref().into() + } + pub fn to_raw_public_vec(self) -> Vec { Public::from(self).to_raw_vec() } @@ -69,16 +81,8 @@ impl Keyring { } pub fn pair(self) -> Pair { - match self { - Keyring::Alice => Pair::from_seed(b"Alice "), - Keyring::Bob => Pair::from_seed(b"Bob "), - Keyring::Charlie => Pair::from_seed(b"Charlie "), - Keyring::Dave => Pair::from_seed(b"Dave "), - Keyring::Eve => Pair::from_seed(b"Eve "), - Keyring::Ferdie => Pair::from_seed(b"Ferdie "), - Keyring::One => Pair::from_seed(b"12345678901234567890123456789012"), - Keyring::Two => Pair::from_seed(&hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")), - } + Pair::from_string(&format!("{}//{}", DEV_PHRASE, <&'static str>::from(self)), None) + .expect("static values are known good; qed") } } @@ -91,8 +95,8 @@ impl From for &'static str { Keyring::Dave => "Dave", Keyring::Eve => "Eve", Keyring::Ferdie => "Ferdie", - Keyring::One => "one", - Keyring::Two => "two", + Keyring::One => "One", + Keyring::Two => "Two", } } } @@ -134,6 +138,12 @@ impl From for [u8; 32] { } } +impl From for H256 { + fn from(k: Keyring) -> Self { + (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref().into() + } +} + impl From for &'static [u8; 32] { fn from(k: Keyring) -> Self { (*PUBLIC_KEYS).get(&k).unwrap().as_array_ref() @@ -162,12 +172,12 @@ impl Deref for Keyring { #[cfg(test)] mod tests { use super::*; - use sr25519::Verifiable; + use substrate_primitives::{sr25519::Pair, Pair as _Pair}; #[test] fn should_work() { - assert!(Keyring::Alice.sign(b"I am Alice!").verify(b"I am Alice!", Keyring::Alice)); - assert!(!Keyring::Alice.sign(b"I am Alice!").verify(b"I am Bob!", Keyring::Alice)); - assert!(!Keyring::Alice.sign(b"I am Alice!").verify(b"I am Alice!", Keyring::Bob)); + assert!(Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Alice!", Keyring::Alice)); + assert!(!Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Bob!", Keyring::Alice)); + assert!(!Pair::verify(&Keyring::Alice.sign(b"I am Alice!"), b"I am Alice!", Keyring::Bob)); } } diff --git a/core/keystore/src/lib.rs b/core/keystore/src/lib.rs index 2b2380c7e27ae..f0ab573cd6dd6 100644 --- a/core/keystore/src/lib.rs +++ b/core/keystore/src/lib.rs @@ -24,13 +24,11 @@ use std::collections::HashMap; use std::path::PathBuf; use std::fs::{self, File}; use std::io::{self, Write}; -use std::num::NonZeroU32; -use serde_derive::{Serialize, Deserialize}; -use error_chain::{error_chain, error_chain_processing, impl_error_chain_processed, +use error_chain::{bail, error_chain, error_chain_processing, impl_error_chain_processed, impl_extract_backtrace, impl_error_chain_kind}; -use substrate_primitives::{hashing::blake2_256, ed25519::{Pair, Public, PKCS_LEN}}; +use substrate_primitives::{ed25519::{Pair, Public}, Pair as _Pair}; pub use crypto::KEY_ITERATIONS; @@ -45,99 +43,21 @@ error_chain! { description("Invalid password"), display("Invalid password"), } - InvalidPKCS8 { - description("Invalid PKCS#8 data"), - display("Invalid PKCS#8 data"), + InvalidPhrase { + description("Invalid recovery phrase (BIP39) data"), + display("Invalid recovery phrase (BIP39) data"), } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct InvalidPassword; - -#[derive(Serialize, Deserialize)] -struct EncryptedKey { - mac: [u8; 32], - salt: [u8; 32], - ciphertext: Vec, // FIXME: switch to fixed-size when serde supports - iv: [u8; 16], - iterations: NonZeroU32, -} - -impl EncryptedKey { - fn encrypt(plain: &[u8; PKCS_LEN], password: &str, iterations: NonZeroU32) -> Self { - use rand::{Rng, rngs::OsRng}; - - let mut rng = OsRng::new().expect("OS Randomness available on all supported platforms; qed"); - - let salt: [u8; 32] = rng.gen(); - let iv: [u8; 16] = rng.gen(); - - // two parts of derived key - // DK = [ DK[0..15] DK[16..31] ] = [derived_left_bits, derived_right_bits] - let (derived_left_bits, derived_right_bits) = crypto::derive_key_iterations(password.as_bytes(), &salt, iterations); - - // preallocated (on-stack in case of `Secret`) buffer to hold cipher - // length = length(plain) as we are using CTR-approach - let mut ciphertext = vec![0; PKCS_LEN]; - - // aes-128-ctr with initial vector of iv - crypto::aes::encrypt_128_ctr(&derived_left_bits, &iv, plain, &mut *ciphertext) - .expect("input lengths of key and iv are both 16; qed"); - - // Blake2_256(DK[16..31] ++ ), where DK[16..31] - derived_right_bits - let mac = blake2_256(&crypto::derive_mac(&derived_right_bits, &*ciphertext)); - - EncryptedKey { - salt, - iv, - mac, - iterations, - ciphertext, - } - } - - fn decrypt(&self, password: &str) -> Result<[u8; PKCS_LEN]> { - let (derived_left_bits, derived_right_bits) = - crypto::derive_key_iterations(password.as_bytes(), &self.salt, self.iterations); - - let mac = blake2_256(&crypto::derive_mac(&derived_right_bits, &self.ciphertext)); - - if subtle::ConstantTimeEq::ct_eq(&mac[..], &self.mac[..]).unwrap_u8() != 1 { - return Err(ErrorKind::InvalidPassword.into()); + InvalidSeed { + description("Invalid seed"), + display("Invalid seed"), } - - let mut plain = [0; PKCS_LEN]; - crypto::aes::decrypt_128_ctr(&derived_left_bits, &self.iv, &self.ciphertext, &mut plain[..]) - .expect("input lengths of key and iv are both 16; qed"); - Ok(plain) } } -type Seed = [u8; 32]; - /// Key store. pub struct Store { path: PathBuf, - additional: HashMap, -} - -pub fn pad_seed(seed: &str) -> Seed { - let mut s: [u8; 32] = [' ' as u8; 32]; - - let was_hex = if seed.len() == 66 && &seed[0..2] == "0x" { - if let Ok(d) = hex::decode(&seed[2..]) { - s.copy_from_slice(&d); - true - } else { false } - } else { false }; - - if !was_hex { - let len = ::std::cmp::min(32, seed.len()); - &mut s[..len].copy_from_slice(&seed.as_bytes()[..len]); - } - - s + additional: HashMap, } impl Store { @@ -149,44 +69,36 @@ impl Store { /// Generate a new key, placing it into the store. pub fn generate(&self, password: &str) -> Result { - let (pair, pkcs_bytes) = Pair::generate_with_pkcs8(); - let key_file = EncryptedKey::encrypt( - &pkcs_bytes, - password, - NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED") - ); - + let (pair, phrase) = Pair::generate_with_phrase(Some(password)); let mut file = File::create(self.key_file_path(&pair.public()))?; - ::serde_json::to_writer(&file, &key_file)?; - + ::serde_json::to_writer(&file, &phrase)?; file.flush()?; - Ok(pair) } /// Create a new key from seed. Do not place it into the store. - /// Only the first 32 bytes of the sead are used. This is meant to be used for testing only. - // FIXME: remove this - https://github.com/paritytech/substrate/issues/1063 pub fn generate_from_seed(&mut self, seed: &str) -> Result { - let padded_seed = pad_seed(seed); - let pair = Pair::from_seed(&padded_seed); - self.additional.insert(pair.public(), padded_seed); + let pair = Pair::from_string(seed, None) + .map_err(|_| Error::from(ErrorKind::InvalidSeed))?; + self.additional.insert(pair.public(), pair.clone()); Ok(pair) } /// Load a key file with given public key. pub fn load(&self, public: &Public, password: &str) -> Result { - if let Some(ref seed) = self.additional.get(public) { - let pair = Pair::from_seed(seed); - return Ok(pair); + if let Some(pair) = self.additional.get(public) { + return Ok(pair.clone()); } let path = self.key_file_path(public); let file = File::open(path)?; - let encrypted_key: EncryptedKey = ::serde_json::from_reader(&file)?; - let pkcs_bytes = encrypted_key.decrypt(password)?; - - Pair::from_pkcs8(&pkcs_bytes[..]).map_err(|_| ErrorKind::InvalidPKCS8.into()) + let phrase: String = ::serde_json::from_reader(&file)?; + let pair = Pair::from_phrase(&phrase, Some(password)) + .map_err(|_| Error::from(ErrorKind::InvalidPhrase))?; + if &pair.public() != public { + bail!(ErrorKind::InvalidPassword); + } + Ok(pair) } /// Get public keys of all stored keys. @@ -227,42 +139,6 @@ mod tests { use super::*; use tempdir::TempDir; - #[test] - fn encrypt_and_decrypt() { - let plain = [1; PKCS_LEN]; - let encrypted_key = EncryptedKey::encrypt(&plain, "thepassword", NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED")); - - let decrypted_key = encrypted_key.decrypt("thepassword").unwrap(); - - assert_eq!(&plain[..], &decrypted_key[..]); - } - - #[test] - fn decrypt_wrong_password_fails() { - let plain = [1; PKCS_LEN]; - let encrypted_key = EncryptedKey::encrypt( - &plain, - "thepassword", - NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED") - ); - - assert!(encrypted_key.decrypt("thepassword2").is_err()); - } - - #[test] - fn decrypt_wrong_iterations_fails() { - let plain = [1; PKCS_LEN]; - let mut encrypted_key = EncryptedKey::encrypt( - &plain, - "thepassword", - NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS is not zero; QED") - ); - - encrypted_key.iterations = NonZeroU32::new(encrypted_key.iterations.get() - 64).unwrap(); - - assert!(encrypted_key.decrypt("thepassword").is_err()); - } - #[test] fn basic_store() { let temp_dir = TempDir::new("keystore").unwrap(); @@ -285,16 +161,7 @@ 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("0x1").unwrap(); - assert_eq!("5GqhgbUd2S9uc5Tm7hWhw29Tw2jBnuHshmTV1fDF4V1w3G2z", pair.public().to_ss58check()); - let pair = store.generate_from_seed("0x3d97c819d68f9bafa7d6e79cb991eebcd77d966c5334c0b94d9e1fa7ad0869dc").unwrap(); assert_eq!("5DKUrgFqCPV8iAXx9sjy1nyBygQCeiUYRFWurZGhnrn3HBL8", pair.public().to_ss58check()); - - let pair = store.generate_from_seed("12345678901234567890123456789022").unwrap(); - assert_eq!("5DscZvfjnM5im7oKRXXP9xtCG1SEwfMb8J5eGLmw5EHhoHR3", pair.public().to_ss58check()); - - let pair = store.generate_from_seed("1").unwrap(); - assert_eq!("5DYnksEZFc7kgtfyNM1xK2eBtW142gZ3Ho3NQubrF2S6B2fq", pair.public().to_ss58check()); } } diff --git a/core/network/src/test/mod.rs b/core/network/src/test/mod.rs index e2cfe04e66814..24e05daec097e 100644 --- a/core/network/src/test/mod.rs +++ b/core/network/src/test/mod.rs @@ -39,19 +39,18 @@ use crate::consensus_gossip::ConsensusGossip; use crossbeam_channel::{self as channel, Sender, select}; use futures::Future; use futures::sync::{mpsc, oneshot}; -use keyring::Keyring; use crate::message::{Message, ConsensusEngineId}; use network_libp2p::{NodeIndex, ProtocolId, PeerId}; use parity_codec::Encode; use parking_lot::{Mutex, RwLock}; -use primitives::{H256, Ed25519AuthorityId}; +use primitives::{H256, ed25519::Public as AuthorityId}; use crate::protocol::{ConnectedPeer, Context, FromNetworkMsg, Protocol, ProtocolMsg}; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{AuthorityIdFor, Block as BlockT, Digest, DigestItem, Header, NumberFor}; use runtime_primitives::Justification; use crate::service::{network_channel, NetworkChan, NetworkLink, NetworkMsg, NetworkPort, TransactionPool}; use crate::specialization::NetworkSpecialization; -use test_client; +use test_client::{self, AccountKeyring}; pub use test_client::runtime::{Block, Extrinsic, Hash, Transfer}; pub use test_client::TestClient; @@ -458,12 +457,12 @@ impl + Clone> Peer { if with_tx { self.generate_blocks_at(at, count, BlockOrigin::File, |mut builder| { let transfer = Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Alice.into(), amount: 1, nonce, }; - let signature = Keyring::from_raw_public(transfer.from.to_fixed_bytes()).unwrap().sign(&transfer.encode()).into(); + let signature = AccountKeyring::from_public(&transfer.from).unwrap().sign(&transfer.encode()).into(); builder.push(Extrinsic::Transfer(transfer, signature)).unwrap(); nonce = nonce + 1; builder.bake().unwrap() @@ -473,7 +472,7 @@ impl + Clone> Peer { } } - pub fn push_authorities_change_block(&self, new_authorities: Vec) -> H256 { + pub fn push_authorities_change_block(&self, new_authorities: Vec) -> H256 { self.generate_blocks(1, BlockOrigin::File, |mut builder| { builder.push(Extrinsic::AuthoritiesChange(new_authorities.clone())).unwrap(); builder.bake().unwrap() diff --git a/core/primitives/Cargo.toml b/core/primitives/Cargo.toml index 7aeeaf1029b29..04094ff01e48a 100644 --- a/core/primitives/Cargo.toml +++ b/core/primitives/Cargo.toml @@ -27,6 +27,8 @@ rand = { version = "0.6", optional = true } sha2 = { version = "0.8", optional = true } substrate-bip39 = { git = "https://github.com/paritytech/substrate-bip39", optional = true } tiny-bip39 = { version = "0.6.0", optional = true } +hex = { version = "0.3", optional = true } +regex = {version = "1.1", optional = true } [dev-dependencies] substrate-serializer = { path = "../serializer" } @@ -55,6 +57,7 @@ std = [ "ring", "untrusted", "hex-literal", + "hex", "base58", "substrate-bip39", "tiny-bip39", @@ -63,4 +66,5 @@ std = [ "rand", "sha2", "schnorrkel", + "regex", ] diff --git a/core/primitives/src/authority_id.rs b/core/primitives/src/authority_id.rs deleted file mode 100644 index e1b97fbc5bcd2..0000000000000 --- a/core/primitives/src/authority_id.rs +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2017-2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate 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 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. If not, see . - -#[cfg(feature = "std")] -use serde::{Serialize, Serializer, Deserialize, Deserializer}; -use parity_codec::{Encode, Decode}; -use crate::H256; - -/// An identifier for an authority in the consensus algorithm. The same size as ed25519::Public. -#[derive(Clone, Copy, PartialEq, Eq, Default, Encode, Decode)] -pub struct Ed25519AuthorityId(pub [u8; 32]); - -#[cfg(feature = "std")] -impl ::std::fmt::Display for Ed25519AuthorityId { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{}", crate::ed25519::Public(self.0).to_ss58check()) - } -} - -#[cfg(feature = "std")] -impl ::std::fmt::Debug for Ed25519AuthorityId { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - let h = format!("{}", crate::hexdisplay::HexDisplay::from(&self.0)); - write!(f, "{} ({}…{})", crate::ed25519::Public(self.0).to_ss58check(), &h[0..8], &h[60..]) - } -} - -#[cfg(feature = "std")] -impl ::std::hash::Hash for Ed25519AuthorityId { - fn hash(&self, state: &mut H) { - self.0.hash(state); - } -} - -impl AsRef<[u8; 32]> for Ed25519AuthorityId { - fn as_ref(&self) -> &[u8; 32] { - &self.0 - } -} - -impl AsRef<[u8]> for Ed25519AuthorityId { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl Into<[u8; 32]> for Ed25519AuthorityId { - fn into(self) -> [u8; 32] { - self.0 - } -} - -impl From<[u8; 32]> for Ed25519AuthorityId { - fn from(a: [u8; 32]) -> Self { - Ed25519AuthorityId(a) - } -} - -impl AsRef for Ed25519AuthorityId { - fn as_ref(&self) -> &Ed25519AuthorityId { - &self - } -} - -impl Into for Ed25519AuthorityId { - fn into(self) -> H256 { - self.0.into() - } -} - -#[cfg(feature = "std")] -impl Serialize for Ed25519AuthorityId { - fn serialize(&self, serializer: S) -> Result where S: Serializer { - crate::ed25519::serialize(&self, serializer) - } -} - -#[cfg(feature = "std")] -impl<'de> Deserialize<'de> for Ed25519AuthorityId { - fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { - crate::ed25519::deserialize(deserializer) - } -} diff --git a/core/primitives/src/crypto.rs b/core/primitives/src/crypto.rs new file mode 100644 index 0000000000000..bf2ef3df46486 --- /dev/null +++ b/core/primitives/src/crypto.rs @@ -0,0 +1,486 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate 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 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. If not, see . + +// tag::description[] +//! Cryptographic utilities. +// end::description[] + +#[cfg(feature = "std")] +use parity_codec::{Encode, Decode}; +#[cfg(feature = "std")] +use regex::Regex; +#[cfg(feature = "std")] +use base58::{FromBase58, ToBase58}; + +/// The infallible type. +#[derive(Debug)] +pub enum Infallible {} + +/// The length of the junction identifier. Note that this is also referred to as the +/// `CHAIN_CODE_LENGTH` in the context of Schnorrkel. +#[cfg(feature = "std")] +pub const JUNCTION_ID_LEN: usize = 32; + +/// Similar to `From`, except that the onus is on the part of the caller to ensure +/// that data passed in makes sense. Basically, you're not guaranteed to get anything +/// sensible out. +pub trait UncheckedFrom { + /// Convert from an instance of `T` to Self. This is not guaranteed to be + /// whatever counts as a valid instance of `T` and it's up to the caller to + /// ensure that it makes sense. + fn unchecked_from(t: T) -> Self; +} + +/// The counterpart to `UncheckedFrom`. +pub trait UncheckedInto { + /// The counterpart to `unchecked_from`. + fn unchecked_into(self) -> T; +} + +impl> UncheckedInto for S { + fn unchecked_into(self) -> T { + T::unchecked_from(self) + } +} + +/// An error with the interpretation of a secret. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg(feature = "std")] +pub enum SecretStringError { + /// The overall format was invalid (e.g. the seed phrase contained symbols). + InvalidFormat, + /// The seed phrase provided is not a valid BIP39 phrase. + InvalidPhrase, + /// The supplied password was invalid. + InvalidPassword, + /// The seed is invalid (bad content). + InvalidSeed, + /// The seed has an invalid length. + InvalidSeedLength, + /// The derivation path was invalid (e.g. contains soft junctions when they are not supported). + InvalidPath, +} + +/// A since derivation junction description. It is the single parameter used when creating +/// a new secret key from an existing secret key and, in the case of `SoftRaw` and `SoftIndex` +/// a new public key from an existing public key. +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Encode, Decode)] +#[cfg(feature = "std")] +pub enum DeriveJunction { + /// Soft (vanilla) derivation. Public keys have a correspondent derivation. + Soft([u8; JUNCTION_ID_LEN]), + /// Hard ("hardened") derivation. Public keys do not have a correspondent derivation. + Hard([u8; JUNCTION_ID_LEN]), +} + +#[cfg(feature = "std")] +impl DeriveJunction { + /// Consume self to return a soft derive junction with the same chain code. + pub fn soften(self) -> Self { DeriveJunction::Soft(self.unwrap_inner()) } + + /// Consume self to return a hard derive junction with the same chain code. + pub fn harden(self) -> Self { DeriveJunction::Hard(self.unwrap_inner()) } + + /// Create a new soft (vanilla) DeriveJunction from a given, encodable, value. + /// + /// If you need a hard junction, use `hard()`. + pub fn soft(index: T) -> Self { + let mut cc: [u8; JUNCTION_ID_LEN] = Default::default(); + index.using_encoded(|data| if data.len() > JUNCTION_ID_LEN { + let hash_result = blake2_rfc::blake2b::blake2b(JUNCTION_ID_LEN, &[], data); + let hash = hash_result.as_bytes(); + cc.copy_from_slice(hash); + } else { + cc[0..data.len()].copy_from_slice(data); + }); + DeriveJunction::Soft(cc) + } + + /// Create a new hard (hardened) DeriveJunction from a given, encodable, value. + /// + /// If you need a soft junction, use `soft()`. + pub fn hard(index: T) -> Self { + Self::soft(index).harden() + } + + /// Consume self to return the chain code. + pub fn unwrap_inner(self) -> [u8; JUNCTION_ID_LEN] { + match self { + DeriveJunction::Hard(c) | DeriveJunction::Soft(c) => c, + } + } + + /// Get a reference to the inner junction id. + pub fn inner(&self) -> &[u8; JUNCTION_ID_LEN] { + match self { + DeriveJunction::Hard(ref c) | DeriveJunction::Soft(ref c) => c, + } + } + + /// Return `true` if the junction is soft. + pub fn is_soft(&self) -> bool { + match *self { + DeriveJunction::Soft(_) => true, + _ => false, + } + } + + /// Return `true` if the junction is hard. + pub fn is_hard(&self) -> bool { + match *self { + DeriveJunction::Hard(_) => true, + _ => false, + } + } +} + +#[cfg(feature = "std")] +impl> From for DeriveJunction { + fn from(j: T) -> DeriveJunction { + let j = j.as_ref(); + let (code, hard) = if j.starts_with("/") { + (&j[1..], true) + } else { + (j, false) + }; + + let res = if let Ok(n) = str::parse::(code) { + // number + DeriveJunction::soft(n) + } else { + // something else + DeriveJunction::soft(code) + }; + + if hard { + res.harden() + } else { + res + } + } +} + +/// An error type for SS58 decoding. +#[cfg(feature = "std")] +#[derive(Clone, Copy, Eq, PartialEq, Debug)] +pub enum PublicError { + /// Bad alphabet. + BadBase58, + /// Bad length. + BadLength, + /// Unknown version. + UnknownVersion, + /// Invalid checksum. + InvalidChecksum, + /// Invalid format. + InvalidFormat, + /// Invalid derivation path. + InvalidPath, +} + +/// Key that can be encoded to/from SS58. +#[cfg(feature = "std")] +pub trait Ss58Codec: Sized { + /// Some if the string is a properly encoded SS58Check address. + fn from_ss58check(s: &str) -> Result; + /// Some if the string is a properly encoded SS58Check address, optionally with + /// a derivation path following. + fn from_string(s: &str) -> Result { Self::from_ss58check(s) } + /// Return the ss58-check string for this key. + fn to_ss58check(&self) -> String; +} + +#[cfg(feature = "std")] +/// Derivable key trait. +pub trait Derive: Sized { + /// Derive a child key from a series of given junctions. + /// + /// Will be `None` for public keys if there are any hard junctions in there. + fn derive>(&self, _path: Iter) -> Option { None } +} + +#[cfg(feature = "std")] +impl + AsRef<[u8]> + Default + Derive> Ss58Codec for T { + fn from_ss58check(s: &str) -> Result { + let mut res = T::default(); + let len = res.as_mut().len(); + let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. + if d.len() != len + 3 { + // Invalid length. + return Err(PublicError::BadLength); + } + if d[0] != 42 { + // Invalid version. + return Err(PublicError::UnknownVersion); + } + if d[len+1..len+3] != blake2_rfc::blake2b::blake2b(64, &[], &d[0..len+1]).as_bytes()[0..2] { + // Invalid checksum. + return Err(PublicError::InvalidChecksum); + } + res.as_mut().copy_from_slice(&d[1..len+1]); + Ok(res) + } + + fn to_ss58check(&self) -> String { + let mut v = vec![42u8]; + v.extend(self.as_ref()); + let r = blake2_rfc::blake2b::blake2b(64, &[], &v); + v.extend(&r.as_bytes()[0..2]); + v.to_base58() + } + + fn from_string(s: &str) -> Result { + let re = Regex::new(r"^(?P[\w\d]+)(?P(//?[^/]+)*)$") + .expect("constructed from known-good static value; qed"); + let cap = re.captures(s).ok_or(PublicError::InvalidFormat)?; + let re_junction = Regex::new(r"/(/?[^/]+)") + .expect("constructed from known-good static value; qed"); + let path = re_junction.captures_iter(&cap["path"]) + .map(|f| DeriveJunction::from(&f[1])); + Self::from_ss58check(&cap["ss58"])?.derive(path).ok_or(PublicError::InvalidPath) + } +} + +/// 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 { + /// TThe type which is used to encode a public key. + type Public; + + /// The type used to (minimally) encode the data required to securely create + /// a new key pair. + type Seed; + + /// The type used to represent a signature. Can be created from a key pair and a message + /// and verified with the message and a public key. + type Signature; + + /// Error returned from the `derive` function. + type DeriveError; + + /// Generate new secure (random) key pair. + /// + /// This is only for ephemeral keys really, since you won't have access to the secret key + /// for storage. If you want a persistent key pair, use `generate_with_phrase` instead. + fn generate() -> Self; + + /// Generate new secure (random) key pair and provide the recovery phrase. + /// + /// You can recover the same key later with `from_phrase`. + /// + /// This is generally slower than `generate()`, so prefer that unless you need to persist + /// the key from the current session. + fn generate_with_phrase(password: Option<&str>) -> (Self, String); + + /// Returns the KeyPair from the English BIP39 seed `phrase`, or `None` if it's invalid. + fn from_phrase(phrase: &str, password: Option<&str>) -> Result; + + /// Derive a child key from a series of given junctions. + fn derive>(&self, path: Iter) -> Result; + + /// Generate new key pair from the provided `seed`. + /// + /// @WARNING: THIS WILL ONLY BE SECURE IF THE `seed` IS SECURE. If it can be guessed + /// by an attacker then they can also derive your key. + fn from_seed(seed: Self::Seed) -> Self; + + /// Make a new key pair from secret seed material. The slice must be the correct size or + /// it will return `None`. + /// + /// @WARNING: THIS WILL ONLY BE SECURE IF THE `seed` IS SECURE. If it can be guessed + /// by an attacker then they can also derive your key. + fn from_seed_slice(seed: &[u8]) -> Result; + + /// Construct a key from a phrase, password and path. + fn from_standard_components< + I: Iterator + >(phrase: &str, password: Option<&str>, path: I) -> Result; + + /// Sign a message. + fn sign(&self, message: &[u8]) -> Self::Signature; + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify, M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: P) -> bool; + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool; + + /// Get the public key. + fn public(&self) -> Self::Public; + + /// Interprets the string `s` in order to generate a key Pair. + /// + /// This takes a helper function to do the key generation from a phrase, password and + /// junction iterator. + /// + /// - If `s` is a possibly `0x` prefixed 64-digit hex string, then it will be interpreted + /// directly as a `MiniSecretKey` (aka "seed" in `subkey`). + /// - If `s` is a valid BIP-39 key phrase of 12, 15, 18, 21 or 24 words, then the key will + /// be derived from it. In this case: + /// - the phrase may be followed by one or more items delimited by `/` characters. + /// - the path may be followed by `///`, in which case everything after the `///` is treated + /// as a password. + /// In this case they are interpreted as HDKD junctions; purely numeric items are interpreted as + /// integers, non-numeric items as strings. Junctions prefixed with `/` are interpreted as soft + /// junctions, and with `//` as hard junctions. + /// + /// There is no correspondence mapping between SURI strings and the keys they represent. + /// Two different non-identical strings can actually lead to the same secret being derived. + /// Notably, integer junction indices may be legally prefixed with arbitrary number of zeros. + /// Similarly an empty password (ending the SURI with `///`) is perfectly valid and will generally + /// be equivalent to no password at all. + /// + /// `None` is returned if no matches are found. + fn from_string(s: &str, password_override: Option<&str>) -> Result { + let hex_seed = if s.starts_with("0x") { + &s[2..] + } else { + s + }; + + if let Ok(d) = hex::decode(hex_seed) { + if let Ok(r) = Self::from_seed_slice(&d) { + return Ok(r) + } + } + + let re = Regex::new(r"^(?P\w+( \w+)*)(?P(//?[^/]+)*)(///(?P.*))?$") + .expect("constructed from known-good static value; qed"); + let cap = re.captures(s).ok_or(SecretStringError::InvalidFormat)?; + let re_junction = Regex::new(r"/(/?[^/]+)") + .expect("constructed from known-good static value; qed"); + let path = re_junction.captures_iter(&cap["path"]) + .map(|f| DeriveJunction::from(&f[1])); + Self::from_standard_components( + &cap["phrase"], + password_override.or_else(|| cap.name("password").map(|m| m.as_str())), + path, + ) + } +} + +#[cfg(test)] +mod tests { + use crate::DeriveJunction; + use hex_literal::{hex, hex_impl}; + use super::*; + + #[derive(Eq, PartialEq, Debug)] + enum TestPair { + Generated, + GeneratedWithPhrase, + GeneratedFromPhrase{phrase: String, password: Option}, + Standard{phrase: String, password: Option, path: Vec}, + Seed(Vec), + } + + impl Pair for TestPair { + type Public = (); + type Seed = (); + type Signature = (); + type DeriveError = (); + + fn generate() -> Self { TestPair::Generated } + fn generate_with_phrase(_password: Option<&str>) -> (Self, String) { (TestPair::GeneratedWithPhrase, "".into()) } + fn from_phrase(phrase: &str, password: Option<&str>) -> Result { + Ok(TestPair::GeneratedFromPhrase{ phrase: phrase.to_owned(), password: password.map(Into::into) }) + } + fn derive>(&self, _path: Iter) -> Result { + Err(()) + } + fn from_seed(_seed: Self::Seed) -> Self { TestPair::Seed(vec![]) } + fn sign(&self, _message: &[u8]) -> Self::Signature { () } + fn verify, M: AsRef<[u8]>>(_sig: &Self::Signature, _message: M, _pubkey: P) -> bool { true } + fn verify_weak, M: AsRef<[u8]>>(_sig: &[u8], _message: M, _pubkey: P) -> bool { true } + fn public(&self) -> Self::Public { () } + fn from_standard_components>(phrase: &str, password: Option<&str>, path: I) -> Result { + Ok(TestPair::Standard { phrase: phrase.to_owned(), password: password.map(ToOwned::to_owned), path: path.collect() }) + } + fn from_seed_slice(seed: &[u8]) -> Result { + Ok(TestPair::Seed(seed.to_owned())) + } + } + + #[test] + fn interpret_std_seed_should_work() { + assert_eq!( + TestPair::from_string("0x0123456789abcdef", None), + Ok(TestPair::Seed(hex!["0123456789abcdef"][..].to_owned())) + ); + assert_eq!( + TestPair::from_string("0123456789abcdef", None), + Ok(TestPair::Seed(hex!["0123456789abcdef"][..].to_owned())) + ); + } + + #[test] + fn password_override_should_work() { + assert_eq!( + TestPair::from_string("hello world///password", None), + TestPair::from_string("hello world", Some("password")), + ); + assert_eq!( + TestPair::from_string("hello world///password", None), + TestPair::from_string("hello world///other password", Some("password")), + ); + } + + #[test] + fn interpret_std_secret_string_should_work() { + assert_eq!( + TestPair::from_string("hello world", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![]}) + ); + assert_eq!( + TestPair::from_string("hello world/1", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::soft(1)]}) + ); + assert_eq!( + TestPair::from_string("hello world/DOT", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::soft("DOT")]}) + ); + assert_eq!( + TestPair::from_string("hello world//1", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard(1)]}) + ); + assert_eq!( + TestPair::from_string("hello world//DOT", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard("DOT")]}) + ); + assert_eq!( + TestPair::from_string("hello world//1/DOT", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard(1), DeriveJunction::soft("DOT")]}) + ); + assert_eq!( + TestPair::from_string("hello world//DOT/1", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: None, path: vec![DeriveJunction::hard("DOT"), DeriveJunction::soft(1)]}) + ); + assert_eq!( + TestPair::from_string("hello world///password", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![]}) + ); + assert_eq!( + TestPair::from_string("hello world//1/DOT///password", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![DeriveJunction::hard(1), DeriveJunction::soft("DOT")]}) + ); + assert_eq!( + TestPair::from_string("hello world/1//DOT///password", None), + Ok(TestPair::Standard{phrase: "hello world".to_owned(), password: Some("password".to_owned()), path: vec![DeriveJunction::soft(1), DeriveJunction::hard("DOT")]}) + ); + } +} diff --git a/core/primitives/src/ed25519.rs b/core/primitives/src/ed25519.rs index 9b856009628ff..1d1a1bff4af92 100644 --- a/core/primitives/src/ed25519.rs +++ b/core/primitives/src/ed25519.rs @@ -18,58 +18,251 @@ //! Simple Ed25519 API. // end::description[] + +use crate::{hash::H256, hash::H512}; +use parity_codec::{Encode, Decode}; + +#[cfg(feature = "std")] use untrusted; +#[cfg(feature = "std")] use blake2_rfc; -use ring::{rand, signature, signature::KeyPair}; -use crate::{hash::H512, Ed25519AuthorityId}; +#[cfg(feature = "std")] +use ring::{signature, signature::KeyPair, rand::{SecureRandom, SystemRandom}}; +#[cfg(feature = "std")] use base58::{ToBase58, FromBase58}; -use parity_codec::{Encode, Decode}; +#[cfg(feature = "std")] +use substrate_bip39::seed_from_entropy; +#[cfg(feature = "std")] +use bip39::{Mnemonic, Language, MnemonicType}; +#[cfg(feature = "std")] +use crate::crypto::{Pair as TraitPair, DeriveJunction, SecretStringError, Derive}; +#[cfg(feature = "std")] +use serde::{de, Serializer, Serialize, Deserializer, Deserialize}; +use crate::crypto::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 +/// will need it later (such as for HDKD). #[cfg(feature = "std")] -use serde::{de, Serializer, Deserializer, Deserialize}; +type Seed = [u8; 32]; -/// Alias to 512-bit hash when used in the context of a signature on the relay chain. -pub type Signature = H512; +/// A public key. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] +pub struct Public(pub [u8; 32]); -/// Length of the PKCS#8 encoding of the key. -pub const PKCS_LEN: usize = 85; +/// A key pair. +#[cfg(feature = "std")] +pub struct Pair(signature::Ed25519KeyPair, Seed); -/// A localized signature also contains sender information. -#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] -pub struct LocalizedSignature { - /// The signer of the signature. - pub signer: Public, - /// The signature itself. - pub signature: Signature, +#[cfg(feature = "std")] +impl Clone for Pair { + fn clone(&self) -> Self { + Pair::from_seed(self.1.clone()) + } } -/// Verify a message without type checking the parameters' types for the right size. -/// Returns true if the signature is good. -pub fn verify>(sig: &[u8], message: &[u8], public: P) -> bool { - let public_key = untrusted::Input::from(public.as_ref()); - let msg = untrusted::Input::from(message); - let sig = untrusted::Input::from(sig); +impl AsRef<[u8; 32]> for Public { + fn as_ref(&self) -> &[u8; 32] { + &self.0 + } +} - match signature::verify(&signature::ED25519, public_key, msg, sig) { - Ok(_) => true, - _ => false, +impl AsRef<[u8]> for Public { + fn as_ref(&self) -> &[u8] { + &self.0[..] } } -/// A public key. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -pub struct Public(pub [u8; 32]); +impl AsMut<[u8]> for Public { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} -/// A key pair. -pub struct Pair(signature::Ed25519KeyPair); +impl From for [u8; 32] { + fn from(x: Public) -> Self { + x.0 + } +} + +#[cfg(feature = "std")] +impl From for Public { + fn from(x: Pair) -> Self { + x.public() + } +} + +impl AsRef for Public { + fn as_ref(&self) -> &Public { + &self + } +} + +impl From for H256 { + fn from(x: Public) -> Self { + x.0.into() + } +} + +impl UncheckedFrom<[u8; 32]> for Public { + fn unchecked_from(x: [u8; 32]) -> Self { + Public::from_raw(x) + } +} +impl UncheckedFrom for Public { + fn unchecked_from(x: H256) -> Self { + Public::from_h256(x) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Display for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + let s = self.to_ss58check(); + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) + } +} + +#[cfg(feature = "std")] +impl Serialize for Public { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for Public { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + Public::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +#[cfg(feature = "std")] impl ::std::hash::Hash for Public { fn hash(&self, state: &mut H) { self.0.hash(state); } } +/// A signature (a 512-bit value). +#[derive(Encode, Decode)] +pub struct Signature(pub [u8; 64]); + +impl Clone for Signature { + fn clone(&self) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(&self.0[..]); + Signature(r) + } +} + +impl Default for Signature { + fn default() -> Self { + Signature([0u8; 64]) + } +} + +impl PartialEq for Signature { + fn eq(&self, b: &Self) -> bool { + &self.0[..] == &b.0[..] + } +} + +impl Eq for Signature {} + +impl From for H512 { + fn from(v: Signature) -> H512 { + H512::from(v.0) + } +} + +impl From for [u8; 64] { + fn from(v: Signature) -> [u8; 64] { + v.0 + } +} + +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 AsMut<[u8]> for Signature { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for Signature { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) + } +} + +#[cfg(feature = "std")] +impl ::std::hash::Hash for Signature { + fn hash(&self, state: &mut H) { + ::std::hash::Hash::hash(&self.0[..], state); + } +} + +impl Signature { + /// A new instance from the given 64-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_raw(data: [u8; 64]) -> Signature { + Signature(data) + } + + /// A new instance from the given slice that should be 64 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(data); + Signature(r) + } + + /// A new instance from an H512. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_h512(v: H512) -> Signature { + Signature(v.into()) + } +} + +/// A localized signature also contains sender information. +#[cfg(feature = "std")] +#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] +pub struct LocalizedSignature { + /// The signer of the signature. + pub signer: Public, + /// The signature itself. + pub signature: Signature, +} + /// An error type for SS58 decoding. +#[cfg(feature = "std")] #[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum PublicError { /// Bad alphabet. @@ -84,36 +277,33 @@ pub enum PublicError { impl Public { /// A new instance from the given 32-byte `data`. + /// + /// 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_raw(data: [u8; 32]) -> Self { 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) } - /// Some if the string is a properly encoded SS58Check address. - pub fn from_ss58check(s: &str) -> Result { - let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. - if d.len() != 35 { - // Invalid length. - return Err(PublicError::BadLength); - } - if d[0] != 42 { - // Invalid version. - return Err(PublicError::UnknownVersion); - } - if d[33..35] != blake2_rfc::blake2b::blake2b(64, &[], &d[0..33]).as_bytes()[0..2] { - // Invalid checksum. - return Err(PublicError::InvalidChecksum); - } - Ok(Self::from_slice(&d[1..33])) + /// A new instance from an H256. + /// + /// 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_h256(x: H256) -> Self { + Public(x.into()) } /// Return a `Vec` filled with raw data. + #[cfg(feature = "std")] pub fn to_raw_vec(self) -> Vec { let r: &[u8; 32] = self.as_ref(); r.to_vec() @@ -129,6 +319,30 @@ impl Public { pub fn as_array_ref(&self) -> &[u8; 32] { self.as_ref() } +} + +#[cfg(feature = "std")] +impl Derive for Public {} + +#[cfg(feature = "std")] +impl Public { + /// Some if the string is a properly encoded SS58Check address. + pub fn from_ss58check(s: &str) -> Result { + let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. + if d.len() != 35 { + // Invalid length. + return Err(PublicError::BadLength); + } + if d[0] != 42 { + // Invalid version. + return Err(PublicError::UnknownVersion); + } + if d[33..35] != blake2_rfc::blake2b::blake2b(64, &[], &d[0..33]).as_bytes()[0..2] { + // Invalid checksum. + return Err(PublicError::InvalidChecksum); + } + Ok(Self::from_slice(&d[1..33])) + } /// Return the ss58-check string for this key. pub fn to_ss58check(&self) -> String { @@ -140,178 +354,197 @@ impl Public { } } -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 Into<[u8; 32]> for Public { - fn into(self) -> [u8; 32] { - self.0 - } -} - -impl AsRef for Public { - fn as_ref(&self) -> &Public { - &self - } -} - +#[cfg(feature = "std")] impl AsRef for Pair { fn as_ref(&self) -> &Pair { &self } } -impl Into for Public { - fn into(self) -> Ed25519AuthorityId { - Ed25519AuthorityId(self.0) - } -} - -impl From for Public { - fn from(id: Ed25519AuthorityId) -> Self { - Public(id.0) - } -} - -impl ::std::fmt::Display for Public { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{}", self.to_ss58check()) - } +/// Derive a single hard junction. +#[cfg(feature = "std")] +fn derive_hard_junction(secret_seed: &Seed, cc: &[u8; 32]) -> Seed { + ("Ed25519HDKD", secret_seed, cc).using_encoded(|data| { + let mut res = [0u8; 32]; + res.copy_from_slice(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()); + res + }) } -impl ::std::fmt::Debug for Public { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) - } +/// An error when deriving a key. +#[cfg(feature = "std")] +pub enum DeriveError { + /// A soft key was found in the path (and is unsupported). + SoftKeyInPath, } -impl Pair { - /// Generate new secure (random) key pair, yielding it and the corresponding pkcs#8 bytes. - pub fn generate_with_pkcs8() -> (Self, [u8; PKCS_LEN]) { - let rng = rand::SystemRandom::new(); - let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(&rng).expect("system randomness is available; qed"); - let pair = Self::from_pkcs8(&pkcs8_bytes.as_ref()).expect("just-generated pkcs#8 data is valid; qed"); - - let mut out = [0; PKCS_LEN]; - out.copy_from_slice(pkcs8_bytes.as_ref()); - (pair, out) - } +#[cfg(feature = "std")] +impl TraitPair for Pair { + type Public = Public; + type Seed = Seed; + type Signature = Signature; + type DeriveError = DeriveError; /// Generate new secure (random) key pair. - pub fn generate() -> Pair { - let (pair, _) = Self::generate_with_pkcs8(); - pair - } - - /// Generate from pkcs#8 bytes. - pub fn from_pkcs8(pkcs8_bytes: &[u8]) -> Result { - signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&pkcs8_bytes)).map(Pair) - } - - /// Make a new key pair from a seed phrase. - /// NOTE: prefer pkcs#8 unless security doesn't matter -- this is used primarily for tests. - pub fn from_seed(seed: &[u8; 32]) -> Pair { + /// + /// This is only for ephemeral keys really, since you won't have access to the secret key + /// for storage. If you want a persistent key pair, use `generate_with_phrase` instead. + fn generate() -> Pair { + let mut seed: Seed = Default::default(); + SystemRandom::new().fill(seed.as_mut()).expect("system random source should always work! qed"); + Self::from_seed(seed) + } + + /// Generate new secure (random) key pair and provide the recovery phrase. + /// + /// You can recover the same key later with `from_phrase`. + fn generate_with_phrase(password: Option<&str>) -> (Pair, String) { + let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); + let phrase = mnemonic.phrase(); + ( + Self::from_phrase(phrase, password).expect("All phrases generated by Mnemonic are valid; qed"), + phrase.to_owned(), + ) + } + + /// Generate key pair from given recovery phrase and password. + fn from_phrase(phrase: &str, password: Option<&str>) -> Result { + let big_seed = seed_from_entropy( + Mnemonic::from_phrase(phrase, Language::English) + .map_err(|_| SecretStringError::InvalidPhrase)?.entropy(), + password.unwrap_or(""), + ).map_err(|_| SecretStringError::InvalidSeed)?; + Self::from_seed_slice(&big_seed[0..32]) + } + + /// Make a new key pair from secret seed material. + /// + /// You should never need to use this; generate(), generate_with_phrasee + fn from_seed(seed: Seed) -> Pair { let key = signature::Ed25519KeyPair::from_seed_unchecked(untrusted::Input::from(&seed[..])) .expect("seed has valid length; qed"); + Pair(key, seed) + } + + /// Make a new key pair from secret seed material. The slice must be 32 bytes long or it + /// will return `None`. + /// + /// You should never need to use this; generate(), generate_with_phrase + fn from_seed_slice(seed_slice: &[u8]) -> Result { + if seed_slice.len() != 32 { + Err(SecretStringError::InvalidSeedLength) + } else { + let mut seed = [0u8; 32]; + seed.copy_from_slice(&seed_slice); + Ok(Self::from_seed(seed)) + } + } - Pair(key) + /// Derive a child key from a series of given junctions. + fn derive>(&self, path: Iter) -> Result { + let mut acc = self.1.clone(); + for j in path { + match j { + DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath), + DeriveJunction::Hard(cc) => acc = derive_hard_junction(&acc, &cc), + } + } + Ok(Self::from_seed(acc)) } - /// 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) + /// Generate a key from the phrase, password and derivation path. + fn from_standard_components>(phrase: &str, password: Option<&str>, path: I) -> Result { + Self::from_phrase(phrase, password)?.derive(path).map_err(|_| SecretStringError::InvalidPath) } /// Get the public key. - pub fn public(&self) -> Public { + fn public(&self) -> Public { let mut r = [0u8; 32]; let pk = self.0.public_key().as_ref(); r.copy_from_slice(pk); Public(r) } -} - -/// Verify a signature on a message. Returns true if the signature is good. -pub fn verify_strong>(sig: &Signature, message: &[u8], pubkey: P) -> bool { - let public_key = untrusted::Input::from(&pubkey.as_ref().0[..]); - let msg = untrusted::Input::from(message); - let sig = untrusted::Input::from(&sig.as_bytes()); - match signature::verify(&signature::ED25519, public_key, msg, sig) { - Ok(_) => true, - _ => false, + /// Sign a message. + fn sign(&self, message: &[u8]) -> Signature { + let mut r = [0u8; 64]; + r.copy_from_slice(self.0.sign(message).as_ref()); + Signature::from_raw(r) } -} -/// Something that acts as a signature allowing a message to be verified. -pub trait Verifiable { - /// Verify something that acts like a signature. - fn verify>(&self, message: &[u8], pubkey: P) -> bool; -} + /// Verify a signature on a message. Returns true if the signature is good. + fn verify, M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: P) -> bool { + let public_key = untrusted::Input::from(&pubkey.as_ref().0[..]); + let msg = untrusted::Input::from(message.as_ref()); + let sig = untrusted::Input::from(&sig.0[..]); -impl Verifiable for Signature { - /// Verify something that acts like a signature. - fn verify>(&self, message: &[u8], pubkey: P) -> bool { - verify_strong(&self, message, pubkey) + match signature::verify(&signature::ED25519, public_key, msg, sig) { + Ok(_) => true, + _ => false, + } } -} -impl Verifiable for LocalizedSignature { - fn verify>(&self, message: &[u8], pubkey: P) -> bool { - pubkey.as_ref() == &self.signer && self.signature.verify(message, pubkey) + /// Verify a signature on a message. Returns true if the signature is good. + /// + /// This doesn't use the type system to ensure that `sig` and `pubkey` are the correct + /// size. Use it only if you're coming from byte buffers and need the speed. + fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool { + let public_key = untrusted::Input::from(pubkey.as_ref()); + let msg = untrusted::Input::from(message.as_ref()); + let sig = untrusted::Input::from(sig); + + match signature::verify(&signature::ED25519, public_key, msg, sig) { + Ok(_) => true, + _ => false, + } } } -/// Deserialize from `ss58` into something that can be constructed from `[u8; 32]`. #[cfg(feature = "std")] -pub fn deserialize<'de, D, T: From<[u8; 32]>>(deserializer: D) -> Result where - D: Deserializer<'de>, -{ - let ss58 = String::deserialize(deserializer)?; - Public::from_ss58check(&ss58) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - .map(|v| v.0.into()) -} +impl Pair { + /// Get the seed for this key. + pub fn seed(&self) -> &Seed { + &self.1 + } -/// Serializes something that implements `AsRef<[u8; 32]>` into `ss58`. -#[cfg(feature = "std")] -pub fn serialize>(data: &T, serializer: S) -> Result where - S: Serializer, -{ - serializer.serialize_str(&Public(*data.as_ref()).to_ss58check()) + /// Exactly as `from_string` except that if no matches are found then, the the first 32 + /// characters are taken (padded with spaces as necessary) and used as the MiniSecretKey. + pub fn from_legacy_string(s: &str, password_override: Option<&str>) -> Pair { + Self::from_string(s, password_override).unwrap_or_else(|_| { + let mut padded_seed: Seed = [' ' as u8; 32]; + let len = s.len().min(32); + padded_seed[..len].copy_from_slice(&s.as_bytes()[..len]); + Self::from_seed(padded_seed) + }) + } } #[cfg(test)] mod test { use super::*; use hex_literal::{hex, hex_impl}; + use crate::Pair as _Pair; - fn _test_primitives_signature_and_local_the_same() { - fn takes_two(_: T, _: T) { } - takes_two(Signature::default(), crate::Signature::default()) + #[test] + fn test_vector_should_work() { + let pair: Pair = Pair::from_seed(hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")); + let public = pair.public(); + assert_eq!(public, Public::from_raw(hex!("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"))); + let message = b""; + let signature = Signature::from_raw(hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b")); + assert!(&pair.sign(&message[..]) == &signature); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] - fn test_vector_should_work() { - let pair: Pair = Pair::from_seed(&hex!("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")); + fn test_vector_by_string_should_work() { + let pair: Pair = Pair::from_string("0x9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", None).unwrap(); let public = pair.public(); assert_eq!(public, Public::from_raw(hex!("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a"))); let message = b""; - let signature: Signature = hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b").into(); + let signature = Signature::from_raw(hex!("e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b")); assert!(&pair.sign(&message[..]) == &signature); - assert!(verify_strong(&signature, &message[..], &public)); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] @@ -320,33 +553,47 @@ mod test { let public = pair.public(); let message = b"Something important"; let signature = pair.sign(&message[..]); - assert!(verify_strong(&signature, &message[..], &public)); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] fn seeded_pair_should_work() { - use crate::hexdisplay::HexDisplay; - - let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let pair = Pair::from_seed(*b"12345678901234567890123456789012"); let public = pair.public(); assert_eq!(public, Public::from_raw(hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee"))); let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"); let signature = pair.sign(&message[..]); - println!("Correct signature: {}", HexDisplay::from(&signature.as_bytes())); - assert!(verify_strong(&signature, &message[..], &public)); + println!("Correct signature: {:?}", signature); + assert!(Pair::verify(&signature, &message[..], &public)); + } + + #[test] + fn generate_with_phrase_recovery_possible() { + let (pair1, phrase) = Pair::generate_with_phrase(None); + let pair2 = Pair::from_phrase(&phrase, None).unwrap(); + + assert_eq!(pair1.public(), pair2.public()); } #[test] - fn generate_with_pkcs8_recovery_possible() { - let (pair1, pkcs8) = Pair::generate_with_pkcs8(); - let pair2 = Pair::from_pkcs8(&pkcs8).unwrap(); + fn generate_with_password_phrase_recovery_possible() { + let (pair1, phrase) = Pair::generate_with_phrase(Some("password")); + let pair2 = Pair::from_phrase(&phrase, Some("password")).unwrap(); assert_eq!(pair1.public(), pair2.public()); } + #[test] + fn password_does_something() { + let (pair1, phrase) = Pair::generate_with_phrase(Some("password")); + let pair2 = Pair::from_phrase(&phrase, None).unwrap(); + + assert_ne!(pair1.public(), pair2.public()); + } + #[test] fn ss58check_roundtrip_works() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let pair = Pair::from_seed(*b"12345678901234567890123456789012"); let public = pair.public(); let s = public.to_ss58check(); println!("Correct: {}", s); diff --git a/core/primitives/src/lib.rs b/core/primitives/src/lib.rs index fc3867a7880c0..67b99f7ebc81b 100644 --- a/core/primitives/src/lib.rs +++ b/core/primitives/src/lib.rs @@ -49,19 +49,17 @@ pub mod hashing; pub use hashing::{blake2_256, twox_128, twox_256}; #[cfg(feature = "std")] pub mod hexdisplay; -#[cfg(feature = "std")] -pub mod ed25519; -#[cfg(feature = "std")] -pub mod sr25519; +pub mod crypto; pub mod u32_trait; +pub mod ed25519; +pub mod sr25519; pub mod hash; mod hasher; pub mod sandbox; pub mod storage; pub mod uint; -mod authority_id; mod changes_trie; #[cfg(test)] @@ -69,17 +67,15 @@ mod tests; pub use self::hash::{H160, H256, H512, convert_hash}; pub use self::uint::U256; -pub use authority_id::Ed25519AuthorityId; pub use changes_trie::ChangesTrieConfiguration; +#[cfg(feature = "std")] +pub use crypto::{DeriveJunction, Pair}; pub use hash_db::Hasher; // Switch back to Blake after PoC-3 is out // pub use self::hasher::blake::BlakeHasher; pub use self::hasher::blake2::Blake2Hasher; -/// A 512-bit value interpreted as a signature. -pub type Signature = hash::H512; - /// Hex-serialised shim for `Vec`. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Hash, PartialOrd, Ord))] diff --git a/core/primitives/src/sr25519.rs b/core/primitives/src/sr25519.rs index a6e7db8078cdf..4c2b97c5f68a2 100644 --- a/core/primitives/src/sr25519.rs +++ b/core/primitives/src/sr25519.rs @@ -16,33 +16,212 @@ // tag::description[] //! Simple sr25519 (Schnorr-Ristretto) API. +//! +//! Note: `CHAIN_CODE_LENGTH` must be equal to `crate::crypto::JUNCTION_ID_LEN` +//! for this to work. // end::description[] -use base58::{FromBase58, ToBase58}; +#[cfg(feature = "std")] use blake2_rfc; +#[cfg(feature = "std")] use rand::rngs::OsRng; +#[cfg(feature = "std")] use schnorrkel::{signing_context, Keypair, SecretKey, MiniSecretKey, PublicKey, derive::{Derivation, ChainCode, CHAIN_CODE_LENGTH} }; +#[cfg(feature = "std")] use substrate_bip39::mini_secret_from_entropy; -//use sha2::Sha512; +#[cfg(feature = "std")] +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 parity_codec::{Encode, Decode}; -use crate::hash::H512; -use bip39::{Mnemonic, Language}; #[cfg(feature = "std")] -use serde::{de, Deserialize, Deserializer, Serializer}; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +#[cfg(feature = "std")] +use schnorrkel::keys::MINI_SECRET_KEY_LENGTH; // signing context -const SIGNING_CTX: &'static [u8] = b"substrate transaction"; +#[cfg(feature = "std")] +const SIGNING_CTX: &[u8] = b"substrate"; + +/// An Schnorrkel/Ristretto x25519 ("sr25519") public key. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] +pub struct Public(pub [u8; 32]); + +/// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. +#[cfg(feature = "std")] +pub struct Pair(Keypair); + +impl AsRef for Public { + fn as_ref(&self) -> &Public { + &self + } +} + +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 AsMut<[u8]> for Public { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +impl From for [u8; 32] { + fn from(x: Public) -> [u8; 32] { + x.0 + } +} + +impl From for H256 { + fn from(x: Public) -> H256 { + x.0.into() + } +} + +impl UncheckedFrom<[u8; 32]> for Public { + fn unchecked_from(x: [u8; 32]) -> Self { + Public::from_raw(x) + } +} + +impl UncheckedFrom for Public { + fn unchecked_from(x: H256) -> Self { + Public::from_h256(x) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Display for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for Public { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + let s = self.to_ss58check(); + write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) + } +} + +#[cfg(feature = "std")] +impl Serialize for Public { + fn serialize(&self, serializer: S) -> Result where S: Serializer { + serializer.serialize_str(&self.to_ss58check()) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for Public { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + Public::from_ss58check(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +#[cfg(feature = "std")] +impl ::std::hash::Hash for Public { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} /// An Schnorrkel/Ristretto x25519 ("sr25519") signature. /// /// Instead of importing it for the local module, alias it to be available as a public type -pub type Signature = H512; +#[derive(Encode, Decode)] +pub struct Signature(pub [u8; 64]); + +impl Clone for Signature { + fn clone(&self) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(&self.0[..]); + Signature(r) + } +} + +impl Default for Signature { + fn default() -> Self { + Signature([0u8; 64]) + } +} + +impl PartialEq for Signature { + fn eq(&self, b: &Self) -> bool { + &self.0[..] == &b.0[..] + } +} + +impl Eq for Signature {} + +impl From for [u8; 64] { + fn from(v: Signature) -> [u8; 64] { + v.0 + } +} + +impl From for H512 { + fn from(v: Signature) -> H512 { + H512::from(v.0) + } +} + +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 AsMut<[u8]> for Signature { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0[..] + } +} + +#[cfg(feature = "std")] +impl From for Signature { + fn from(s: schnorrkel::Signature) -> Signature { + Signature(s.to_bytes()) + } +} + +#[cfg(feature = "std")] +impl ::std::fmt::Debug for Signature { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", crate::hexdisplay::HexDisplay::from(&self.0)) + } +} + +#[cfg(feature = "std")] +impl ::std::hash::Hash for Signature { + fn hash(&self, state: &mut H) { + ::std::hash::Hash::hash(&self.0[..], state); + } +} /// A localized signature also contains sender information. /// NOTE: Encode and Decode traits are supported in ed25519 but not possible for now here. +#[cfg(feature = "std")] #[derive(PartialEq, Eq, Clone, Debug)] pub struct LocalizedSignature { /// The signer of the signature. @@ -51,64 +230,80 @@ pub struct LocalizedSignature { pub signature: Signature, } -/// An Schnorrkel/Ristretto x25519 ("sr25519") public key. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -pub struct Public(pub [u8; 32]); +impl Signature { + /// A new instance from the given 64-byte `data`. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_raw(data: [u8; 64]) -> Signature { + Signature(data) + } -/// An Schnorrkel/Ristretto x25519 ("sr25519") key pair. -pub struct Pair(Keypair); + /// A new instance from the given slice that should be 64 bytes long. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_slice(data: &[u8]) -> Self { + let mut r = [0u8; 64]; + r.copy_from_slice(data); + Signature(r) + } -impl ::std::hash::Hash for Public { - fn hash(&self, state: &mut H) { - self.0.hash(state); + /// A new instance from an H512. + /// + /// NOTE: No checking goes on to ensure this is a real signature. Only use it if + /// you are certain that the array actually is a signature. GIGO! + pub fn from_h512(v: H512) -> Signature { + Signature(v.into()) } } -/// An error type for SS58 decoding. -#[derive(Clone, Copy, Eq, PartialEq, Debug)] -pub enum PublicError { - /// Bad alphabet. - BadBase58, - /// Bad length. - BadLength, - /// Unknown version. - UnknownVersion, - /// Invalid checksum. - InvalidChecksum, +#[cfg(feature = "std")] +impl Derive for Public { + /// Derive a child key from a series of given junctions. + /// + /// `None` if there are any hard junctions in there. + fn derive>(&self, path: Iter) -> Option { + let mut acc = PublicKey::from_bytes(self.as_ref()).ok()?; + for j in path { + match j { + DeriveJunction::Soft(cc) => acc = acc.derived_key_simple(ChainCode(cc), &[]).0, + DeriveJunction::Hard(_cc) => return None, + } + } + Some(Self(acc.to_bytes())) + } } impl Public { /// A new instance from the given 32-byte `data`. + /// + /// 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_raw(data: [u8; 32]) -> Self { 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) } - /// Some if the string is a properly encoded SS58Check address. - pub fn from_ss58check(s: &str) -> Result { - let d = s.from_base58().map_err(|_| PublicError::BadBase58)?; // failure here would be invalid encoding. - if d.len() != 35 { - // Invalid length. - return Err(PublicError::BadLength); - } - if d[0] != 42 { - // Invalid version. - return Err(PublicError::UnknownVersion); - } - if d[33..35] != blake2_rfc::blake2b::blake2b(64, &[], &d[0..33]).as_bytes()[0..2] { - // Invalid checksum. - return Err(PublicError::InvalidChecksum); - } - Ok(Self::from_slice(&d[1..33])) + /// A new instance from an H256. + /// + /// 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_h256(x: H256) -> Self { + Public(x.into()) } /// Return a `Vec` filled with raw data. + #[cfg(feature = "std")] pub fn to_raw_vec(self) -> Vec { let r: &[u8; 32] = self.as_ref(); r.to_vec() @@ -124,179 +319,52 @@ impl Public { pub fn as_array_ref(&self) -> &[u8; 32] { self.as_ref() } - - /// Return the ss58-check string for this key. - pub fn to_ss58check(&self) -> String { - let mut v = vec![42u8]; - v.extend(self.as_slice()); - let r = blake2_rfc::blake2b::blake2b(64, &[], &v); - v.extend(&r.as_bytes()[0..2]); - v.to_base58() - } - - /// Derive a child key from a series of given junctions. - /// - /// `None` if there are any hard junctions in there. - pub fn derive>(&self, mut path: Iter) -> Option { - let mut acc = PublicKey::from_bytes(self.as_ref()).ok()?; - for j in path { - match j { - DeriveJunction::Soft(cc) => acc = acc.derived_key_simple(ChainCode(cc), &[]).0, - DeriveJunction::Hard(cc) => return None, - } - } - Some(Self(acc.to_bytes())) - } -} - -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 Into<[u8; 32]> for Public { - fn into(self) -> [u8; 32] { - self.0 - } -} - -impl AsRef for Public { - fn as_ref(&self) -> &Public { - &self - } } +#[cfg(feature = "std")] impl AsRef for Pair { fn as_ref(&self) -> &Pair { &self } } +#[cfg(feature = "std")] impl From for Pair { fn from(sec: MiniSecretKey) -> Pair { Pair(sec.expand_to_keypair()) } } +#[cfg(feature = "std")] impl From for Pair { fn from(sec: SecretKey) -> Pair { Pair(Keypair::from(sec)) } } +#[cfg(feature = "std")] impl From for Pair { fn from(p: schnorrkel::Keypair) -> Pair { Pair(p) } } +#[cfg(feature = "std")] impl From for schnorrkel::Keypair { fn from(p: Pair) -> schnorrkel::Keypair { p.0 } } +#[cfg(feature = "std")] impl AsRef for Pair { fn as_ref(&self) -> &schnorrkel::Keypair { &self.0 } } -impl ::std::fmt::Display for Public { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - write!(f, "{}", self.to_ss58check()) - } -} - -impl ::std::fmt::Debug for Public { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - let s = self.to_ss58check(); - write!(f, "{} ({}...)", crate::hexdisplay::HexDisplay::from(&self.0), &s[0..8]) - } -} - -/// A since derivation junction description. It is the single parameter used when creating -/// a new secret key from an existing secret key and, in the case of `SoftRaw` and `SoftIndex` -/// a new public key from an existing public key. -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Encode, Decode)] -pub enum DeriveJunction { - /// Soft (vanilla) derivation. Public keys have a correspondent derivation. - Soft([u8; CHAIN_CODE_LENGTH]), - /// Hard ("hardened") derivation. Public keys do not have a correspondent derivation. - Hard([u8; CHAIN_CODE_LENGTH]), -} - -impl DeriveJunction { - /// Consume self to return a soft derive junction with the same chain code. - pub fn soften(self) -> Self { DeriveJunction::Soft(self.unwrap_inner()) } - - /// Consume self to return a hard derive junction with the same chain code. - pub fn harden(self) -> Self { DeriveJunction::Hard(self.unwrap_inner()) } - - /// Create a new soft (vanilla) DeriveJunction from a given, encodable, value. - /// - /// If you need a hard junction, use `hard()`. - pub fn soft(index: T) -> Self { - let mut cc: [u8; CHAIN_CODE_LENGTH] = Default::default(); - index.using_encoded(|data| if data.len() > CHAIN_CODE_LENGTH { - let hash_result = blake2_rfc::blake2b::blake2b(CHAIN_CODE_LENGTH, &[], data); - let hash = hash_result.as_bytes(); - cc.copy_from_slice(hash); - } else { - cc[0..data.len()].copy_from_slice(data); - }); - DeriveJunction::Soft(cc) - } - - /// Create a new hard (hardened) DeriveJunction from a given, encodable, value. - /// - /// If you need a soft junction, use `soft()`. - pub fn hard(index: T) -> Self { - Self::soft(index).harden() - } - - /// Consume self to return the chain code. - pub fn unwrap_inner(self) -> [u8; CHAIN_CODE_LENGTH] { - match self { - DeriveJunction::Hard(c) | DeriveJunction::Soft(c) => c, - } - } - - /// Consume self to return the chain code. - pub fn unwrap_chain_code(self) -> ChainCode { - ChainCode(self.unwrap_inner()) - } - - /// Return a reference to the chain code. - pub fn chain_code(&self) -> ChainCode { - self.clone().unwrap_chain_code() - } - - /// Return `true` if the junction is soft. - pub fn is_soft(&self) -> bool { - match *self { - DeriveJunction::Soft(_) => true, - _ => false, - } - } - - /// Return `true` if the junction is hard. - pub fn is_hard(&self) -> bool { - match *self { - DeriveJunction::Hard(_) => true, - _ => false, - } - } -} - /// Derive a single hard junction. +#[cfg(feature = "std")] fn derive_hard_junction(secret: &SecretKey, cc: &[u8; CHAIN_CODE_LENGTH]) -> SecretKey { ("SchnorrRistrettoHDKD", &secret.to_bytes()[..], cc).using_encoded(|data| MiniSecretKey::from_bytes(blake2_rfc::blake2b::blake2b(32, &[], data).as_bytes()) @@ -305,173 +373,181 @@ fn derive_hard_junction(secret: &SecretKey, cc: &[u8; CHAIN_CODE_LENGTH]) -> Sec ) } -impl Pair { +#[cfg(feature = "std")] +type Seed = [u8; MINI_SECRET_KEY_LENGTH]; + +#[cfg(feature = "std")] +impl TraitPair for Pair { + type Public = Public; + type Seed = Seed; + type Signature = Signature; + type DeriveError = Infallible; + /// Generate new secure (random) key pair. - pub fn generate() -> Pair { + fn generate() -> Pair { let mut csprng: OsRng = OsRng::new().expect("os random generator works; qed"); let key_pair: Keypair = Keypair::generate(&mut csprng); Pair(key_pair) } - /// Make a new key pair from a seed phrase. + /// Make a new key pair from raw secret seed material. + /// /// This is generated using schnorrkel's Mini-Secret-Keys. + /// /// A MiniSecretKey is literally what Ed25519 calls a SecretKey, which is just 32 random bytes. - pub fn from_seed(seed: &[u8; 32]) -> Pair { - let mini_key: MiniSecretKey = MiniSecretKey::from_bytes(seed) + fn from_seed(seed: Seed) -> Pair { + let mini_key: MiniSecretKey = MiniSecretKey::from_bytes(&seed[..]) .expect("32 bytes can always build a key; qed"); let kp = mini_key.expand_to_keypair(); Pair(kp) } - /// Make a new key pair from a seed phrase. - /// This is generated using schnorrkel's Mini-Secret-Keys. - /// A MiniSecretKey is literally what Ed25519 calls a SecretKey, which is just 32 random bytes. - pub fn from_entropy(entropy: &[u8], password: Option<&str>) -> Pair { - let mini_key: MiniSecretKey = mini_secret_from_entropy(entropy, password.unwrap_or("")) - .expect("32 bytes can always build a key; qed"); - let kp = mini_key.expand_to_keypair(); - Pair(kp) + /// Get the public key. + fn public(&self) -> Public { + let mut pk = [0u8; 32]; + pk.copy_from_slice(&self.0.public.to_bytes()); + Public(pk) + } + + /// Make a new key pair from secret seed material. The slice must be 32 bytes long or it + /// will return `None`. + /// + /// 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() + )) + } + } + + /// Generate a key from the phrase, password and derivation path. + fn from_standard_components>(phrase: &str, password: Option<&str>, path: I) -> Result { + Self::from_phrase(phrase, password)? + .derive(path) + .map_err(|_| SecretStringError::InvalidPath) + } + + fn generate_with_phrase(password: Option<&str>) -> (Pair, String) { + let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); + let phrase = mnemonic.phrase(); + ( + Self::from_phrase(phrase, password).expect("All phrases generated by Mnemonic are valid; qed"), + phrase.to_owned(), + ) } - /// Returns the KeyPair from the English BIP39 seed `phrase`, or `None` if it's invalid. - pub fn from_phrase(phrase: &str, password: Option<&str>) -> Option { + fn from_phrase(phrase: &str, password: Option<&str>) -> Result { Mnemonic::from_phrase(phrase, Language::English) - .ok() + .map_err(|_| SecretStringError::InvalidPhrase) .map(|m| Self::from_entropy(m.entropy(), password)) } - /// Derive a child key from a series of given junctions. - pub fn derive>(&self, mut path: Iter) -> Pair { + fn derive>(&self, path: Iter) -> Result { let init = self.0.secret.clone(); let result = path.fold(init, |acc, j| match j { DeriveJunction::Soft(cc) => acc.derived_key_simple(ChainCode(cc), &[]).0, DeriveJunction::Hard(cc) => derive_hard_junction(&acc, &cc), }); - Self(result.into()) + Ok(Self(result.into())) } - /// Sign a message. - pub fn sign(&self, message: &[u8]) -> Signature { + fn sign(&self, message: &[u8]) -> Signature { let context = signing_context(SIGNING_CTX); - Signature::from(self.0.sign(context.bytes(message)).to_bytes()) - } - - /// Get the public key. - pub fn public(&self) -> Public { - let mut pk = [0u8; 32]; - pk.copy_from_slice(&self.0.public.to_bytes()); - Public(pk) - } -} - -/// Verify a signature on a message. Returns true if the signature is good. -pub fn verify_strong>(sig: &Signature, message: &[u8], pubkey: P) -> bool { - let signature: schnorrkel::Signature = match schnorrkel::Signature::from_bytes(&sig[..]) { - Ok(some_signature) => some_signature, - Err(_) => return false - }; - match PublicKey::from_bytes(pubkey.as_ref().as_slice()) { - Ok(pk) => pk.verify(signing_context(SIGNING_CTX).bytes(message), &signature), - Err(_) => false, - } -} - -/// Verify a message without type checking the parameters' types for the right size. -/// Returns true if both the pubkey and the signature is good. -pub fn verify>(sig: &[u8], message: &[u8], pubkey: P) -> bool { - let signature = match schnorrkel::Signature::from_bytes(&sig[..]) { - Ok(sig) => sig, - Err(_) => return false, - }; - match PublicKey::from_bytes(pubkey.as_ref()) { - Ok(pk) => pk.verify_simple(SIGNING_CTX, message, &signature), - Err(_) => false, - } -} - -/// Something that acts as a signature allowing a message to be verified. -pub trait Verifiable { - /// Verify something that acts like a signature. - fn verify>(&self, message: &[u8], pubkey: P) -> bool; -} - -impl Verifiable for Signature { - /// Verify something that acts like a signature. - fn verify>(&self, message: &[u8], pubkey: P) -> bool { - verify_strong(&self, message, pubkey) + self.0.sign(context.bytes(message)).into() + } + + /// Verify a signature on a message. Returns true if the signature is good. + fn verify, M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: P) -> bool { + let signature: schnorrkel::Signature = match schnorrkel::Signature::from_bytes(&sig.as_ref()) { + Ok(some_signature) => some_signature, + Err(_) => return false + }; + match PublicKey::from_bytes(pubkey.as_ref().as_slice()) { + Ok(pk) => pk.verify( + signing_context(SIGNING_CTX).bytes(message.as_ref()), &signature + ), + Err(_) => false, + } } -} -impl Verifiable for LocalizedSignature { - fn verify>(&self, message: &[u8], pubkey: P) -> bool { - pubkey.as_ref() == &self.signer && self.signature.verify(message, pubkey) + /// Verify a signature on a message. Returns true if the signature is good. + fn verify_weak, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool { + let signature: schnorrkel::Signature = match schnorrkel::Signature::from_bytes(sig) { + Ok(some_signature) => some_signature, + Err(_) => return false + }; + match PublicKey::from_bytes(pubkey.as_ref()) { + Ok(pk) => pk.verify( + signing_context(SIGNING_CTX).bytes(message.as_ref()), &signature + ), + Err(_) => false, + } } } -/// Deserialize from `ss58` into something that can be constructed from `[u8; 32]`. #[cfg(feature = "std")] -pub fn deserialize<'de, D, T: From<[u8; 32]>>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let ss58 = String::deserialize(deserializer)?; - Public::from_ss58check(&ss58) - .map_err(|e| de::Error::custom(format!("{:?}", e))) - .map(|v| v.0.into()) -} - -/// Serializes something that implements `AsRef<[u8; 32]>` into `ss58`. -#[cfg(feature = "std")] -pub fn serialize>(data: &T, serializer: S) -> Result -where - S: Serializer, -{ - serializer.serialize_str(&Public(*data.as_ref()).to_ss58check()) +impl Pair { + /// Make a new key pair from binary data derived from a valid seed phrase. + /// + /// This uses a key derivation function to convert the entropy into a seed, then returns + /// the pair generated from it. + pub fn from_entropy(entropy: &[u8], password: Option<&str>) -> Pair { + let mini_key: MiniSecretKey = mini_secret_from_entropy(entropy, password.unwrap_or("")) + .expect("32 bytes can always build a key; qed"); + let kp = mini_key.expand_to_keypair(); + Pair(kp) + } } #[cfg(test)] mod test { use super::*; + use crate::Pair as _Pair; use hex_literal::{hex, hex_impl}; - + #[test] fn derive_soft_should_work() { - let pair: Pair = Pair::from_seed(&hex!( + let pair: Pair = Pair::from_seed(hex!( "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" )); - let derive_1 = pair.derive(Some(DeriveJunction::soft(1)).into_iter()); - let derive_1b = pair.derive(Some(DeriveJunction::soft(1)).into_iter()); - let derive_2 = pair.derive(Some(DeriveJunction::soft(2)).into_iter()); + let derive_1 = pair.derive(Some(DeriveJunction::soft(1)).into_iter()).unwrap(); + let derive_1b = pair.derive(Some(DeriveJunction::soft(1)).into_iter()).unwrap(); + let derive_2 = pair.derive(Some(DeriveJunction::soft(2)).into_iter()).unwrap(); assert_eq!(derive_1.public(), derive_1b.public()); assert_ne!(derive_1.public(), derive_2.public()); } #[test] fn derive_hard_should_work() { - let pair: Pair = Pair::from_seed(&hex!( + let pair: Pair = Pair::from_seed(hex!( "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" )); - let derive_1 = pair.derive(Some(DeriveJunction::hard(1)).into_iter()); - let derive_1b = pair.derive(Some(DeriveJunction::hard(1)).into_iter()); - let derive_2 = pair.derive(Some(DeriveJunction::hard(2)).into_iter()); + let derive_1 = pair.derive(Some(DeriveJunction::hard(1)).into_iter()).unwrap(); + let derive_1b = pair.derive(Some(DeriveJunction::hard(1)).into_iter()).unwrap(); + let derive_2 = pair.derive(Some(DeriveJunction::hard(2)).into_iter()).unwrap(); assert_eq!(derive_1.public(), derive_1b.public()); assert_ne!(derive_1.public(), derive_2.public()); } #[test] fn derive_soft_public_should_work() { - let pair: Pair = Pair::from_seed(&hex!( + let pair: Pair = Pair::from_seed(hex!( "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" )); let path = Some(DeriveJunction::soft(1)); - let pair_1 = pair.derive(path.clone().into_iter()); + let pair_1 = pair.derive(path.clone().into_iter()).unwrap(); let public_1 = pair.public().derive(path.into_iter()).unwrap(); assert_eq!(pair_1.public(), public_1); } #[test] fn derive_hard_public_should_fail() { - let pair: Pair = Pair::from_seed(&hex!( + let pair: Pair = Pair::from_seed(hex!( "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" )); let path = Some(DeriveJunction::hard(1)); @@ -480,7 +556,7 @@ mod test { #[test] fn sr_test_vector_should_work() { - let pair: Pair = Pair::from_seed(&hex!( + let pair: Pair = Pair::from_seed(hex!( "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60" )); let public = pair.public(); @@ -492,8 +568,7 @@ mod test { ); let message = b""; let signature = pair.sign(message); - assert!(verify(&signature[..], message, &public.0)); - assert!(verify_strong(&signature, &message[..], &public)); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] @@ -502,13 +577,13 @@ mod test { let public = pair.public(); let message = b"Something important"; let signature = pair.sign(&message[..]); - assert!(verify_strong(&signature, &message[..], &public)); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] fn seeded_pair_should_work() { - let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let pair = Pair::from_seed(*b"12345678901234567890123456789012"); let public = pair.public(); assert_eq!( public, @@ -518,7 +593,7 @@ mod test { ); let message = hex!("2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000"); let signature = pair.sign(&message[..]); - assert!(verify_strong(&signature, &message[..], &public)); + assert!(Pair::verify(&signature, &message[..], &public)); } #[test] @@ -537,4 +612,15 @@ mod test { let enc = hex!["090fa15cb5b1666222fff584b4cc2b1761fe1e238346b340491b37e25ea183ff"]; assert_eq!(Public::from_ss58check(k).unwrap(), Public::from_raw(enc)); } + + #[test] + fn verify_from_wasm_works() { + // The values in this test case are compared to the output of `node-test.js` in schnorrkel-js. + // + // This is to make sure that the wasm library is compatible. + let pk = Pair::from_seed(hex!("0000000000000000000000000000000000000000000000000000000000000000")); + let public = pk.public(); + let js_signature = Signature::from_raw(hex!("28a854d54903e056f89581c691c1f7d2ff39f8f896c9e9c22475e60902cc2b3547199e0e91fa32902028f2ca2355e8cdd16cfe19ba5e8b658c94aa80f3b81a00")); + assert!(Pair::verify(&js_signature, b"SUBSTRATE", public)); + } } diff --git a/core/rpc/Cargo.toml b/core/rpc/Cargo.toml index 47edca65dc439..762453f2b77cc 100644 --- a/core/rpc/Cargo.toml +++ b/core/rpc/Cargo.toml @@ -28,7 +28,9 @@ tokio = "0.1.7" [dev-dependencies] assert_matches = "1.1" futures = "0.1.17" +sr-io = { path = "../sr-io" } test_client = { package = "substrate-test-client", path = "../test-client" } +test_runtime = { package = "substrate-test-runtime", path = "../test-runtime" } consensus = { package = "substrate-consensus-common", path = "../consensus/common" } rustc-hex = "2.0" hex-literal = "0.1" diff --git a/core/rpc/src/author/tests.rs b/core/rpc/src/author/tests.rs index dfdae48311106..53166e76f82ea 100644 --- a/core/rpc/src/author/tests.rs +++ b/core/rpc/src/author/tests.rs @@ -17,27 +17,24 @@ use super::*; use std::sync::Arc; -use hex_literal::{hex, hex_impl}; use assert_matches::assert_matches; use parity_codec::Encode; use transaction_pool::{ txpool::Pool, ChainApi, }; -use primitives::H256; -use test_client::keyring::Keyring; -use test_client::runtime::{Extrinsic, Transfer}; -use test_client; +use primitives::{H256, blake2_256, hexdisplay::HexDisplay}; +use test_client::{self, AccountKeyring, runtime::{Extrinsic, Transfer}}; use tokio::runtime; -fn uxt(sender: Keyring, nonce: u64) -> Extrinsic { +fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic { let tx = Transfer { amount: Default::default(), nonce, - from: sender.to_raw_public().into(), + from: sender.into(), to: Default::default(), }; - let signature = Keyring::from_raw_public(tx.from.to_fixed_bytes()).unwrap().sign(&tx.encode()).into(); + let signature = AccountKeyring::from_public(&tx.from).unwrap().sign(&tx.encode()).into(); Extrinsic::Transfer(tx, signature) } @@ -50,14 +47,15 @@ fn submit_transaction_should_not_cause_error() { pool: Arc::new(Pool::new(Default::default(), ChainApi::new(client))), subscriptions: Subscriptions::new(runtime.executor()), }; - let h: H256 = hex!("81897a4890fb7554e7f77c533a865846a11583a56a8ad5e307543188d55e64f1").into(); + let xt = uxt(AccountKeyring::Alice, 1).encode(); + let h: H256 = blake2_256(&xt).into(); assert_matches!( - AuthorApi::submit_extrinsic(&p, uxt(Keyring::Alice, 1).encode().into()), + AuthorApi::submit_extrinsic(&p, xt.clone().into()), Ok(h2) if h == h2 ); assert!( - AuthorApi::submit_extrinsic(&p, uxt(Keyring::Alice, 1).encode().into()).is_err() + AuthorApi::submit_extrinsic(&p, xt.into()).is_err() ); } @@ -70,14 +68,15 @@ fn submit_rich_transaction_should_not_cause_error() { pool: Arc::new(Pool::new(Default::default(), ChainApi::new(client.clone()))), subscriptions: Subscriptions::new(runtime.executor()), }; - let h: H256 = hex!("9ec8469b5dcfe29cc274ac1d07ad73d80be57566ace0fcdbe51ebcf4b51e925b").into(); + let xt = uxt(AccountKeyring::Alice, 0).encode(); + let h: H256 = blake2_256(&xt).into(); assert_matches!( - AuthorApi::submit_extrinsic(&p, uxt(Keyring::Alice, 0).encode().into()), + AuthorApi::submit_extrinsic(&p, xt.clone().into()), Ok(h2) if h == h2 ); assert!( - AuthorApi::submit_extrinsic(&p, uxt(Keyring::Alice, 0).encode().into()).is_err() + AuthorApi::submit_extrinsic(&p, xt.into()).is_err() ); } @@ -95,7 +94,7 @@ fn should_watch_extrinsic() { let (subscriber, id_rx, data) = ::jsonrpc_pubsub::typed::Subscriber::new_test("test"); // when - p.watch_extrinsic(Default::default(), subscriber, uxt(Keyring::Alice, 0).encode().into()); + p.watch_extrinsic(Default::default(), subscriber, uxt(AccountKeyring::Alice, 0).encode().into()); // then assert_eq!(runtime.block_on(id_rx), Ok(Ok(1.into()))); @@ -104,10 +103,10 @@ fn should_watch_extrinsic() { let tx = Transfer { amount: 5, nonce: 0, - from: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Alice.into(), to: Default::default(), }; - let signature = Keyring::from_raw_public(tx.from.to_fixed_bytes()).unwrap().sign(&tx.encode()).into(); + let signature = AccountKeyring::from_public(&tx.from).unwrap().sign(&tx.encode()).into(); Extrinsic::Transfer(tx, signature) }; AuthorApi::submit_extrinsic(&p, replacement.encode().into()).unwrap(); @@ -116,9 +115,10 @@ fn should_watch_extrinsic() { res, Some(r#"{"jsonrpc":"2.0","method":"test","params":{"result":"ready","subscription":1}}"#.into()) ); + let h = blake2_256(&replacement.encode()); assert_eq!( runtime.block_on(data.into_future()).unwrap().0, - Some(r#"{"jsonrpc":"2.0","method":"test","params":{"result":{"usurped":"0x53daed816610aa6b22dedbcee43aba44a7ca7155cc71f2919c5e79ebbc7de58c"},"subscription":1}}"#.into()) + Some(format!(r#"{{"jsonrpc":"2.0","method":"test","params":{{"result":{{"usurped":"0x{}"}},"subscription":1}}}}"#, HexDisplay::from(&h))) ); } @@ -132,7 +132,7 @@ fn should_return_pending_extrinsics() { pool: pool.clone(), subscriptions: Subscriptions::new(runtime.executor()), }; - let ex = uxt(Keyring::Alice, 0); + let ex = uxt(AccountKeyring::Alice, 0); AuthorApi::submit_extrinsic(&p, ex.encode().into()).unwrap(); assert_matches!( p.pending_extrinsics(), diff --git a/core/rpc/src/state/tests.rs b/core/rpc/src/state/tests.rs index 510f4235a7866..436d413b1a7be 100644 --- a/core/rpc/src/state/tests.rs +++ b/core/rpc/src/state/tests.rs @@ -17,10 +17,10 @@ use super::*; use self::error::{Error, ErrorKind}; +use sr_io::twox_128; use assert_matches::assert_matches; use consensus::BlockOrigin; -use rustc_hex::FromHex; -use test_client::{self, runtime, keyring::Keyring, TestClient, BlockBuilderExt}; +use test_client::{self, runtime, AccountKeyring, TestClient, BlockBuilderExt}; #[test] fn should_return_storage() { @@ -64,8 +64,8 @@ fn should_notify_about_storage_changes() { let mut builder = api.client.new_block().unwrap(); builder.push_transfer(runtime::Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); @@ -88,8 +88,10 @@ fn should_send_initial_storage_changes_and_notifications() { { let api = State::new(Arc::new(test_client::new()), Subscriptions::new(remote)); + let alice_balance_key = twox_128(&test_runtime::system::balance_of_key(AccountKeyring::Alice.into())); + api.subscribe_storage(Default::default(), subscriber, Some(vec![ - StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap()), + StorageKey(alice_balance_key.to_vec()), ]).into()); // assert id assigned @@ -97,8 +99,8 @@ fn should_send_initial_storage_changes_and_notifications() { let mut builder = api.client.new_block().unwrap(); builder.push_transfer(runtime::Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce: 0, }).unwrap(); @@ -131,8 +133,8 @@ fn should_query_storage() { let add_block = |nonce| { let mut builder = client.new_block().unwrap(); builder.push_transfer(runtime::Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 42, nonce, }).unwrap(); @@ -145,13 +147,14 @@ fn should_query_storage() { let block2_hash = add_block(1); let genesis_hash = client.genesis_hash(); + let alice_balance_key = twox_128(&test_runtime::system::balance_of_key(AccountKeyring::Alice.into())); let mut expected = vec![ StorageChangeSet { block: genesis_hash, changes: vec![ ( - StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap()), + StorageKey(alice_balance_key.to_vec()), Some(StorageData(vec![232, 3, 0, 0, 0, 0, 0, 0])) ), ], @@ -160,7 +163,7 @@ fn should_query_storage() { block: block1_hash, changes: vec![ ( - StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap()), + StorageKey(alice_balance_key.to_vec()), Some(StorageData(vec![190, 3, 0, 0, 0, 0, 0, 0])) ), ], @@ -169,7 +172,7 @@ fn should_query_storage() { // Query changes only up to block1 let result = api.query_storage( - vec![StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap())], + vec![StorageKey(alice_balance_key.to_vec())], genesis_hash, Some(block1_hash).into(), ); @@ -178,7 +181,7 @@ fn should_query_storage() { // Query all changes let result = api.query_storage( - vec![StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap())], + vec![StorageKey(alice_balance_key.to_vec())], genesis_hash, None.into(), ); @@ -187,7 +190,7 @@ fn should_query_storage() { block: block2_hash, changes: vec![ ( - StorageKey("a52da2b7c269da1366b3ed1cdb7299ce".from_hex().unwrap()), + StorageKey(alice_balance_key.to_vec()), Some(StorageData(vec![148, 3, 0, 0, 0, 0, 0, 0])) ), ], diff --git a/core/service/src/components.rs b/core/service/src/components.rs index 8786306fa2545..94f5e69c8f395 100644 --- a/core/service/src/components.rs +++ b/core/service/src/components.rs @@ -536,12 +536,7 @@ mod tests { use super::*; use parity_codec::Encode; use consensus_common::BlockOrigin; - use substrate_test_client::{ - self, - TestClient, - keyring::Keyring, - runtime::{Extrinsic, Transfer}, - }; + use substrate_test_client::{self, TestClient, AccountKeyring, runtime::{Extrinsic, Transfer}}; #[test] fn should_remove_transactions_from_the_pool() { @@ -551,10 +546,10 @@ mod tests { let transfer = Transfer { amount: 5, nonce: 0, - from: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Alice.into(), to: Default::default(), }; - let signature = Keyring::from_raw_public(transfer.from.to_fixed_bytes()).unwrap().sign(&transfer.encode()).into(); + let signature = AccountKeyring::from_public(&transfer.from).unwrap().sign(&transfer.encode()).into(); Extrinsic::Transfer(transfer, signature) }; // store the transaction in the pool diff --git a/core/service/src/lib.rs b/core/service/src/lib.rs index 45127cd43677b..6ec7195d5d8cd 100644 --- a/core/service/src/lib.rs +++ b/core/service/src/lib.rs @@ -34,6 +34,7 @@ use log::{info, warn, debug}; use futures::prelude::*; use keystore::Store as Keystore; use client::BlockchainEvents; +use primitives::Pair; use runtime_primitives::generic::BlockId; use runtime_primitives::traits::{Header, As}; use exit_future::Signal; @@ -62,7 +63,7 @@ use components::{StartRPC, MaintainTransactionPool}; #[doc(hidden)] pub use network::OnDemand; -const DEFAULT_PROTOCOL_ID: &'static str = "sup"; +const DEFAULT_PROTOCOL_ID: &str = "sup"; /// Substrate service. pub struct Service { diff --git a/core/sr-io/with_std.rs b/core/sr-io/with_std.rs index 3667866398870..d67d4ec53c50f 100644 --- a/core/sr-io/with_std.rs +++ b/core/sr-io/with_std.rs @@ -18,7 +18,8 @@ pub use parity_codec as codec; // re-export hashing functions. pub use primitives::{ - blake2_256, twox_128, twox_256, ed25519, Blake2Hasher, sr25519 + blake2_256, twox_128, twox_256, ed25519, Blake2Hasher, sr25519, + Pair }; pub use tiny_keccak::keccak256 as keccak_256; // Switch to this after PoC-3 @@ -163,6 +164,7 @@ pub fn storage_changes_root(parent_hash: [u8; 32], parent_num: u64) -> Option

(input: &[&[u8]]) -> H::Out where H: Hasher, @@ -196,12 +198,12 @@ where /// Verify a ed25519 signature. pub fn ed25519_verify>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool { - ed25519::verify(sig, msg, pubkey) + ed25519::Pair::verify_weak(sig, msg, pubkey) } /// Verify an sr25519 signature. pub fn sr25519_verify>(sig: &[u8; 64], msg: &[u8], pubkey: P) -> bool { - sr25519::verify(sig, msg, pubkey) + sr25519::Pair::verify_weak(sig, msg, pubkey) } /// Verify and recover a SECP256k1 ECDSA signature. diff --git a/core/sr-primitives/src/generic/digest.rs b/core/sr-primitives/src/generic/digest.rs index 95d243b97df74..710bcc77457ce 100644 --- a/core/sr-primitives/src/generic/digest.rs +++ b/core/sr-primitives/src/generic/digest.rs @@ -24,8 +24,6 @@ use rstd::prelude::*; use crate::codec::{Decode, Encode, Codec, Input}; use crate::traits::{self, Member, DigestItem as DigestItemT, MaybeHash}; -use substrate_primitives::hash::H512 as Signature; - /// Generic header digest. #[derive(PartialEq, Eq, Clone, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize))] @@ -63,7 +61,7 @@ impl traits::Digest for Digest where /// provide opaque access to other items. #[derive(PartialEq, Eq, Clone)] #[cfg_attr(feature = "std", derive(Debug))] -pub enum DigestItem { +pub enum DigestItem { /// System digest item announcing that authorities set has been changed /// in the block. Contains the new set of authorities. AuthoritiesChange(Vec), @@ -72,13 +70,13 @@ pub enum DigestItem { /// trie creation. ChangesTrieRoot(Hash), /// Put a Seal on it - Seal(u64, Signature), + Seal(u64, SealSignature), /// Any 'non-system' digest item, opaque to the native code. Other(Vec), } #[cfg(feature = "std")] -impl ::serde::Serialize for DigestItem { +impl ::serde::Serialize for DigestItem { fn serialize(&self, seq: S) -> Result where S: ::serde::Serializer { self.using_encoded(|bytes| { ::substrate_primitives::bytes::serialize(bytes, seq) @@ -91,13 +89,13 @@ impl ::serde::Serialize for DigestItem { +pub enum DigestItemRef<'a, Hash: 'a, AuthorityId: 'a, SealSignature: 'a> { /// Reference to `DigestItem::AuthoritiesChange`. AuthoritiesChange(&'a [AuthorityId]), /// Reference to `DigestItem::ChangesTrieRoot`. ChangesTrieRoot(&'a Hash), /// A sealed signature for testing - Seal(&'a u64, &'a Signature), + Seal(&'a u64, &'a SealSignature), /// Any 'non-system' digest item, opaque to the native code. /// Reference to `DigestItem::Other`. Other(&'a Vec), @@ -116,7 +114,7 @@ enum DigestItemType { Seal, } -impl DigestItem { +impl DigestItem { /// Returns Some if `self` is a `DigestItem::Other`. pub fn as_other(&self) -> Option<&Vec> { match *self { @@ -126,7 +124,7 @@ impl DigestItem { } /// Returns a 'referencing view' for this digest item. - fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash, AuthorityId> { + fn dref<'a>(&'a self) -> DigestItemRef<'a, Hash, AuthorityId, SealSignature> { match *self { DigestItem::AuthoritiesChange(ref v) => DigestItemRef::AuthoritiesChange(v), DigestItem::ChangesTrieRoot(ref v) => DigestItemRef::ChangesTrieRoot(v), @@ -139,7 +137,8 @@ impl DigestItem { impl< Hash: Codec + Member, AuthorityId: Codec + Member + MaybeHash, -> traits::DigestItem for DigestItem { + SealSignature: Codec + Member, +> traits::DigestItem for DigestItem { type Hash = Hash; type AuthorityId = AuthorityId; @@ -152,13 +151,13 @@ impl< } } -impl Encode for DigestItem { +impl Encode for DigestItem { fn encode(&self) -> Vec { self.dref().encode() } } -impl Decode for DigestItem { +impl Decode for DigestItem { fn decode(input: &mut I) -> Option { let item_type: DigestItemType = Decode::decode(input)?; match item_type { @@ -169,7 +168,7 @@ impl Decode for DigestItem Decode::decode(input)?, )), DigestItemType::Seal => { - let vals: (u64, Signature) = Decode::decode(input)?; + let vals: (u64, SealSignature) = Decode::decode(input)?; Some(DigestItem::Seal(vals.0, vals.1)) }, DigestItemType::Other => Some(DigestItem::Other( @@ -179,7 +178,7 @@ impl Decode for DigestItem } } -impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member> DigestItemRef<'a, Hash, AuthorityId> { +impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member, SealSignature: Codec + Member> DigestItemRef<'a, Hash, AuthorityId, SealSignature> { /// Cast this digest item into `AuthoritiesChange`. pub fn as_authorities_change(&self) -> Option<&'a [AuthorityId]> { match *self { @@ -197,7 +196,7 @@ impl<'a, Hash: Codec + Member, AuthorityId: Codec + Member> DigestItemRef<'a, Ha } } -impl<'a, Hash: Encode, AuthorityId: Encode> Encode for DigestItemRef<'a, Hash, AuthorityId> { +impl<'a, Hash: Encode, AuthorityId: Encode, SealSignature: Encode> Encode for DigestItemRef<'a, Hash, AuthorityId, SealSignature> { fn encode(&self) -> Vec { let mut v = Vec::new(); @@ -227,6 +226,7 @@ impl<'a, Hash: Encode, AuthorityId: Encode> Encode for DigestItemRef<'a, Hash, A #[cfg(test)] mod tests { use super::*; + use substrate_primitives::hash::H512 as Signature; #[test] fn should_serialize_digest() { diff --git a/core/sr-primitives/src/generic/tests.rs b/core/sr-primitives/src/generic/tests.rs index 5d58bd6c33bb9..91fc8f3faf904 100644 --- a/core/sr-primitives/src/generic/tests.rs +++ b/core/sr-primitives/src/generic/tests.rs @@ -17,12 +17,12 @@ //! Tests for the generic implementations of Extrinsic/Header/Block. use crate::codec::{Decode, Encode}; -use substrate_primitives::H256; +use substrate_primitives::{H256, H512}; use super::DigestItem; #[test] fn system_digest_item_encoding() { - let item = DigestItem::AuthoritiesChange::(vec![10, 20, 30]); + let item = DigestItem::AuthoritiesChange::(vec![10, 20, 30]); let encoded = item.encode(); assert_eq!(encoded, vec![ // type = DigestItemType::AuthoritiesChange @@ -35,13 +35,13 @@ fn system_digest_item_encoding() { 30, 0, 0, 0, ]); - let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); + let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); assert_eq!(item, decoded); } #[test] fn non_system_digest_item_encoding() { - let item = DigestItem::Other::(vec![10, 20, 30]); + let item = DigestItem::Other::(vec![10, 20, 30]); let encoded = item.encode(); assert_eq!(encoded, vec![ // type = DigestItemType::Other @@ -52,6 +52,6 @@ fn non_system_digest_item_encoding() { 10, 20, 30, ]); - let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); + let decoded: DigestItem = Decode::decode(&mut &encoded[..]).unwrap(); assert_eq!(item, decoded); } diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index a06f3fc1b0017..953568e57bc7a 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -30,7 +30,7 @@ pub use serde_derive; pub use runtime_io::{StorageOverlay, ChildrenStorageOverlay}; use rstd::prelude::*; -use substrate_primitives::hash::{H256, H512}; +use substrate_primitives::{ed25519, sr25519, hash::{H256, H512}}; use codec::{Encode, Decode}; #[cfg(feature = "std")] @@ -251,39 +251,64 @@ impl From> for Perbill { } } -/// Ed25519 signature verify. -#[derive(Eq, PartialEq, Clone, Default, Encode, Decode)] +/// Signature verify that can work with any known signature types.. +#[derive(Eq, PartialEq, Clone, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug))] +pub enum MultiSignature { + /// An Ed25519 signature. + Ed25519(ed25519::Signature), + /// An Sr25519 signature. + Sr25519(sr25519::Signature), +} + +impl Default for MultiSignature { + fn default() -> Self { + MultiSignature::Ed25519(Default::default()) + } +} + +/// Public key for any known crypto algorithm. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -pub struct Ed25519Signature(pub H512); +pub enum MultiSigner { + /// An Ed25519 identity. + Ed25519(ed25519::Public), + /// An Sr25519 identity. + Sr25519(sr25519::Public), +} -impl Verify for Ed25519Signature { - type Signer = H256; - fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { - runtime_io::ed25519_verify((self.0).as_fixed_bytes(), msg.get(), &signer.as_bytes()) +impl Default for MultiSigner { + fn default() -> Self { + MultiSigner::Ed25519(Default::default()) } } -impl From for Ed25519Signature { - fn from(h: H512) -> Ed25519Signature { - Ed25519Signature(h) +impl Verify for MultiSignature { + type Signer = MultiSigner; + fn verify>(&self, msg: L, signer: &Self::Signer) -> bool { + match (self, signer) { + (MultiSignature::Ed25519(ref sig), &MultiSigner::Ed25519(ref who)) => sig.verify(msg, who), + (MultiSignature::Sr25519(ref sig), &MultiSigner::Sr25519(ref who)) => sig.verify(msg, who), + _ => false, + } } } -/// Sr25519 signature verify. +/// Signature verify that can work with any known signature types.. #[derive(Eq, PartialEq, Clone, Default, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] -pub struct Sr25519Signature(pub H512); +pub struct AnySignature(H512); -impl Verify for Sr25519Signature { - type Signer = H256; - fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { - runtime_io::sr25519_verify((self.0).as_fixed_bytes(), msg.get(), &signer.as_bytes()) - } -} +/// Public key for any known crypto algorithm. +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Default, Encode, Decode)] +#[cfg_attr(feature = "std", derive(Debug, Serialize, Deserialize))] +pub struct AnySigner(H256); -impl From for Sr25519Signature { - fn from(h: H512) -> Sr25519Signature { - Sr25519Signature(h) +impl Verify for AnySignature { + type Signer = AnySigner; + fn verify>(&self, mut msg: L, signer: &AnySigner) -> bool { + runtime_io::sr25519_verify(self.0.as_fixed_bytes(), msg.get(), &signer.0.as_bytes()) || + runtime_io::ed25519_verify(self.0.as_fixed_bytes(), msg.get(), &signer.0.as_bytes()) } } @@ -581,7 +606,7 @@ impl traits::Extrinsic for OpaqueExtrinsic { #[cfg(test)] mod tests { - use substrate_primitives::hash::H256; + use substrate_primitives::hash::{H256, H512}; use crate::codec::{Encode, Decode}; use crate::traits::DigestItem; @@ -616,7 +641,7 @@ mod tests { } impl_outer_log! { - pub enum Log(InternalLog: DigestItem) for Runtime { + pub enum Log(InternalLog: DigestItem) for Runtime { a(AuthoritiesChange), b() } } @@ -636,16 +661,16 @@ mod tests { assert_eq!(auth_change, decoded_auth_change); // interpret regular item using `generic::DigestItem` - let generic_b1: super::generic::DigestItem = Decode::decode(&mut &encoded_b1[..]).unwrap(); + let generic_b1: super::generic::DigestItem = Decode::decode(&mut &encoded_b1[..]).unwrap(); match generic_b1 { super::generic::DigestItem::Other(_) => (), _ => panic!("unexpected generic_b1: {:?}", generic_b1), } // interpret system item using `generic::DigestItem` - let generic_auth_change: super::generic::DigestItem = Decode::decode(&mut &encoded_auth_change[..]).unwrap(); + let generic_auth_change: super::generic::DigestItem = Decode::decode(&mut &encoded_auth_change[..]).unwrap(); match generic_auth_change { - super::generic::DigestItem::AuthoritiesChange::(authorities) => assert_eq!(authorities, vec![100, 200, 300]), + super::generic::DigestItem::AuthoritiesChange::(authorities) => assert_eq!(authorities, vec![100, 200, 300]), _ => panic!("unexpected generic_auth_change: {:?}", generic_auth_change), } diff --git a/core/sr-primitives/src/testing.rs b/core/sr-primitives/src/testing.rs index 96a10363aacd0..2711c0e623d62 100644 --- a/core/sr-primitives/src/testing.rs +++ b/core/sr-primitives/src/testing.rs @@ -24,30 +24,30 @@ use std::{fmt::Debug, ops::Deref, fmt}; use crate::codec::{Codec, Encode, Decode}; use crate::traits::{self, Checkable, Applyable, BlakeTwo256, Convert}; use crate::generic::DigestItem as GenDigestItem; - -pub use substrate_primitives::{H256, Ed25519AuthorityId}; +pub use substrate_primitives::H256; use substrate_primitives::U256; +use substrate_primitives::ed25519::{Public as AuthorityId, Signature as AuthoritySignature}; /// Authority Id #[derive(Default, PartialEq, Eq, Clone, Encode, Decode, Debug)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct UintAuthorityId(pub u64); -impl Into for UintAuthorityId { - fn into(self) -> Ed25519AuthorityId { +impl Into for UintAuthorityId { + fn into(self) -> AuthorityId { let bytes: [u8; 32] = U256::from(self.0).into(); - Ed25519AuthorityId(bytes) + AuthorityId(bytes) } } /// Converter between u64 and the AuthorityId wrapper type. pub struct ConvertUintAuthorityId; -impl Convert for ConvertUintAuthorityId { - fn convert(a: u64) -> UintAuthorityId { - UintAuthorityId(a) +impl Convert> for ConvertUintAuthorityId { + fn convert(a: u64) -> Option { + Some(UintAuthorityId(a)) } } /// Digest item -pub type DigestItem = GenDigestItem; +pub type DigestItem = GenDigestItem; /// Header Digest #[derive(Default, PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)] diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index b05f1a38da264..e5a58850e747c 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -55,6 +55,20 @@ pub trait Verify { fn verify>(&self, msg: L, signer: &Self::Signer) -> bool; } +impl Verify for substrate_primitives::ed25519::Signature { + type Signer = substrate_primitives::ed25519::Public; + fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { + runtime_io::ed25519_verify(self.as_ref(), msg.get(), signer) + } +} + +impl Verify for substrate_primitives::sr25519::Signature { + type Signer = substrate_primitives::sr25519::Public; + fn verify>(&self, mut msg: L, signer: &Self::Signer) -> bool { + runtime_io::sr25519_verify(self.as_ref(), msg.get(), signer) + } +} + /// Some sort of check on the origin is performed by this object. pub trait EnsureOrigin { /// A return type. @@ -134,6 +148,16 @@ pub trait Convert { fn convert(a: A) -> B; } +impl Convert for () { + fn convert(_: A) -> B { Default::default() } +} + +/// A structure that performs identity conversion. +pub struct Identity; +impl Convert for Identity { + fn convert(a: T) -> T { a } +} + /// Simple trait similar to `Into`, except that it can be used to convert numerics between each /// other. pub trait As { @@ -161,15 +185,6 @@ macro_rules! impl_numerics { impl_numerics!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); -/// A structure that performs identity conversion. -pub struct Identity; -impl Convert for Identity { - fn convert(a: T) -> T { a } -} -impl Convert for () { - fn convert(_: T) -> () { () } -} - /// A meta trait for arithmetic. pub trait SimpleArithmetic: Zero + One + IntegerSquareRoot + As + diff --git a/core/state-machine/src/ext.rs b/core/state-machine/src/ext.rs index 2eb63f9f35cdd..abfde7ee7b9e0 100644 --- a/core/state-machine/src/ext.rs +++ b/core/state-machine/src/ext.rs @@ -26,7 +26,7 @@ use primitives::storage::well_known_keys::is_child_storage_key; use trie::{MemoryDB, TrieDBMut, TrieMut, default_child_trie_root, is_child_trie_key_valid}; use heapsize::HeapSizeOf; -const EXT_NOT_ALLOWED_TO_FAIL: &'static str = "Externalities not allowed to fail within runtime"; +const EXT_NOT_ALLOWED_TO_FAIL: &str = "Externalities not allowed to fail within runtime"; /// Errors that can occur when interacting with the externalities. #[derive(Debug, Copy, Clone)] diff --git a/core/test-client/src/block_builder_ext.rs b/core/test-client/src/block_builder_ext.rs index 17a96cfa271a8..e427b5789291e 100644 --- a/core/test-client/src/block_builder_ext.rs +++ b/core/test-client/src/block_builder_ext.rs @@ -17,7 +17,7 @@ //! Block Builder extensions for tests. use client; -use keyring; +use super::AccountKeyring; use runtime; use runtime_primitives::traits::ProvideRuntimeApi; use client::block_builder::api::BlockBuilder; @@ -38,9 +38,8 @@ impl<'a, A> BlockBuilderExt for client::block_builder::BlockBuilder<'a, runtime: } fn sign_tx(transfer: runtime::Transfer) -> runtime::Extrinsic { - let signature = keyring::Keyring::from_raw_public(transfer.from.to_fixed_bytes()) + let signature = AccountKeyring::from_public(&transfer.from) .unwrap() - .sign(&parity_codec::Encode::encode(&transfer)) - .into(); + .sign(&parity_codec::Encode::encode(&transfer)); runtime::Extrinsic::Transfer(transfer, signature) } diff --git a/core/test-client/src/lib.rs b/core/test-client/src/lib.rs index 34a17d3301911..6eb6db4d4bcea 100644 --- a/core/test-client/src/lib.rs +++ b/core/test-client/src/lib.rs @@ -29,9 +29,9 @@ pub use client::ExecutionStrategies; pub use client::blockchain; pub use client::backend; pub use executor::NativeExecutor; -pub use keyring; pub use runtime; pub use consensus; +pub use keyring::{AuthorityKeyring, AccountKeyring}; use std::sync::Arc; use futures::future::FutureResult; @@ -39,7 +39,6 @@ use primitives::Blake2Hasher; use runtime_primitives::StorageOverlay; use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, NumberFor}; use runtime::genesismap::{GenesisConfig, additional_storage_with_genesis}; -use keyring::Keyring; use state_machine::ExecutionStrategy; use client::LocalCallExecutor; @@ -165,10 +164,16 @@ pub fn new_with_backend( fn genesis_config(support_changes_trie: bool) -> GenesisConfig { GenesisConfig::new(support_changes_trie, vec![ - Keyring::Alice.to_raw_public().into(), - Keyring::Bob.to_raw_public().into(), - Keyring::Charlie.to_raw_public().into(), - ], 1000) + AuthorityKeyring::Alice.into(), + AuthorityKeyring::Bob.into(), + AuthorityKeyring::Charlie.into(), + ], vec![ + AccountKeyring::Alice.into(), + AccountKeyring::Bob.into(), + AccountKeyring::Charlie.into(), + ], + 1000 + ) } fn genesis_storage(support_changes_trie: bool) -> StorageOverlay { diff --git a/core/test-client/src/trait_tests.rs b/core/test-client/src/trait_tests.rs index b678d83fdb5d8..aa51f7d8bf9e3 100644 --- a/core/test-client/src/trait_tests.rs +++ b/core/test-client/src/trait_tests.rs @@ -20,10 +20,9 @@ #![allow(missing_docs)] use std::sync::Arc; -use keyring::Keyring; use consensus::BlockOrigin; use primitives::Blake2Hasher; -use crate::TestClient; +use crate::{TestClient, AccountKeyring}; use runtime_primitives::traits::Block as BlockT; use crate::backend; use crate::blockchain::{Backend as BlockChainBackendT, HeaderBackend}; @@ -88,8 +87,8 @@ pub fn test_leaves_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 41, nonce: 0, }).unwrap(); @@ -117,8 +116,8 @@ pub fn test_leaves_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 1, }).unwrap(); @@ -132,8 +131,8 @@ pub fn test_leaves_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 0, }).unwrap(); @@ -180,8 +179,8 @@ pub fn test_children_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise B2 has the same hash as A2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 41, nonce: 0, }).unwrap(); @@ -200,8 +199,8 @@ pub fn test_children_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(b2.hash())).unwrap(); // this push is required as otherwise C3 has the same hash as B3 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 1, }).unwrap(); @@ -212,8 +211,8 @@ pub fn test_children_for_backend(backend: Arc) where let mut builder = client.new_block_at(&BlockId::Hash(a1.hash())).unwrap(); // this push is required as otherwise D2 has the same hash as B2 and won't get imported builder.push_transfer(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Ferdie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Ferdie.into(), amount: 1, nonce: 0, }).unwrap(); @@ -269,8 +268,8 @@ pub fn test_blockchain_query_by_number_gets_canonical(backend: Arc(backend: Arc(backend: Arc, - pub authorities: Vec, - pub balances: Vec<(Ed25519AuthorityId, u64)>, + pub authorities: Vec, + pub balances: Vec<(AccountId, u64)>, } impl GenesisConfig { - pub fn new_simple(authorities: Vec, balance: u64) -> Self { - Self::new(false, authorities, balance) - } - - pub fn new(support_changes_trie: bool, authorities: Vec, balance: u64) -> Self { + pub fn new(support_changes_trie: bool, authorities: Vec, endowed_accounts: Vec, balance: u64) -> Self { GenesisConfig { changes_trie_config: match support_changes_trie { true => Some(super::changes_trie_config()), false => None, }, authorities: authorities.clone(), - balances: authorities.into_iter().map(|a| (a, balance)).collect(), + balances: endowed_accounts.into_iter().map(|a| (a, balance)).collect(), } } pub fn genesis_map(&self) -> HashMap, Vec> { let wasm_runtime = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm").to_vec(); let mut map: HashMap, Vec> = self.balances.iter() - .map(|&(account, balance)| (account.to_keyed_vec(b"balance:"), vec![].and(&balance))) + .map(|&(ref account, balance)| (account.to_keyed_vec(b"balance:"), vec![].and(&balance))) .map(|(k, v)| (twox_128(&k[..])[..].to_vec(), v.to_vec())) .chain(vec![ (well_known_keys::CODE.into(), wasm_runtime), diff --git a/core/test-runtime/src/lib.rs b/core/test-runtime/src/lib.rs index 59b56e3e0f084..b345c06e6cb4e 100644 --- a/core/test-runtime/src/lib.rs +++ b/core/test-runtime/src/lib.rs @@ -29,7 +29,7 @@ use substrate_client::{ impl_runtime_apis, }; use runtime_primitives::{ - ApplyResult, Ed25519Signature, transaction_validity::TransactionValidity, + ApplyResult, transaction_validity::TransactionValidity, create_runtime_str, traits::{ BlindCheckable, BlakeTwo256, Block as BlockT, Extrinsic as ExtrinsicT, @@ -38,7 +38,7 @@ use runtime_primitives::{ }; use runtime_version::RuntimeVersion; pub use primitives::hash::H256; -use primitives::{Ed25519AuthorityId, OpaqueMetadata}; +use primitives::{ed25519, sr25519, OpaqueMetadata}; #[cfg(any(feature = "std", test))] use runtime_version::NativeVersion; use inherents::{CheckInherentsResult, InherentData}; @@ -81,8 +81,8 @@ pub struct Transfer { #[derive(Clone, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug))] pub enum Extrinsic { - AuthoritiesChange(Vec), - Transfer(Transfer, Ed25519Signature), + AuthoritiesChange(Vec), + Transfer(Transfer, AccountSignature), } #[cfg(feature = "std")] @@ -125,8 +125,14 @@ impl Extrinsic { } } +// The identity type used by authorities. +pub type AuthorityId = ed25519::Public; +// The signature type used by authorities. +pub type AuthoritySignature = ed25519::Signature; /// An identifier for an account on this system. -pub type AccountId = H256; +pub type AccountId = sr25519::Public; +// The signature type used by accounts/transactions. +pub type AccountSignature = sr25519::Signature; /// A simple hash type for all our hashing. pub type Hash = H256; /// The block number type used in this runtime. @@ -134,7 +140,7 @@ pub type BlockNumber = u64; /// Index of a transaction. pub type Index = u64; /// The item of a block digest. -pub type DigestItem = runtime_primitives::generic::DigestItem; +pub type DigestItem = runtime_primitives::generic::DigestItem; /// The digest of a block. pub type Digest = runtime_primitives::generic::Digest; /// A test block. @@ -256,7 +262,7 @@ cfg_if! { version() } - fn authorities() -> Vec { + fn authorities() -> Vec { system::authorities() } @@ -347,7 +353,7 @@ cfg_if! { version() } - fn authorities() -> Vec { + fn authorities() -> Vec { system::authorities() } diff --git a/core/test-runtime/src/system.rs b/core/test-runtime/src/system.rs index bfa5de70d0de7..f1e04473ece18 100644 --- a/core/test-runtime/src/system.rs +++ b/core/test-runtime/src/system.rs @@ -26,8 +26,8 @@ use runtime_primitives::generic; use runtime_primitives::{ApplyError, ApplyOutcome, ApplyResult, transaction_validity::TransactionValidity}; use parity_codec::{KeyedVec, Encode}; use super::{AccountId, BlockNumber, Extrinsic, Transfer, H256 as Hash, Block, Header, Digest}; -use primitives::{Ed25519AuthorityId, Blake2Hasher}; -use primitives::storage::well_known_keys; +use primitives::{Blake2Hasher, storage::well_known_keys}; +use primitives::ed25519::Public as AuthorityId; const NONCE_OF: &[u8] = b"nonce:"; const BALANCE_OF: &[u8] = b"balance:"; @@ -37,7 +37,7 @@ storage_items! { // The current block number being processed. Set by `execute_block`. Number: b"sys:num" => required BlockNumber; ParentHash: b"sys:pha" => required Hash; - NewAuthorities: b"sys:new_auth" => Vec; + NewAuthorities: b"sys:new_auth" => Vec; } pub fn balance_of_key(who: AccountId) -> Vec { @@ -53,7 +53,7 @@ pub fn nonce_of(who: AccountId) -> u64 { } /// Get authorities ar given block. -pub fn authorities() -> Vec { +pub fn authorities() -> Vec { let len: u32 = storage::unhashed::get(well_known_keys::AUTHORITY_COUNT) .expect("There are always authorities in test-runtime"); (0..len) @@ -71,6 +71,36 @@ pub fn initialise_block(header: &Header) { } /// Actually execute all transitioning for `block`. +pub fn polish_block(block: &mut Block) { + let header = &mut block.header; + + // check transaction trie root represents the transactions. + let txs = block.extrinsics.iter().map(Encode::encode).collect::>(); + let txs = txs.iter().map(Vec::as_slice).collect::>(); + let txs_root = enumerated_trie_root::(&txs).into(); + info_expect_equal_hash(&txs_root, &header.extrinsics_root); + header.extrinsics_root = txs_root; + + // execute transactions + block.extrinsics.iter().enumerate().for_each(|(i, e)| { + storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); + execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); + storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); + }); + + header.state_root = storage_root().into(); + + // check digest + let mut digest = Digest::default(); + if let Some(storage_changes_root) = storage_changes_root(header.parent_hash.into(), header.number - 1) { + digest.push(generic::DigestItem::ChangesTrieRoot(storage_changes_root.into())); + } + if let Some(new_authorities) = ::take() { + digest.push(generic::DigestItem::AuthoritiesChange(new_authorities)); + } + header.digest = digest; +} + pub fn execute_block(block: Block) { let ref header = block.header; @@ -83,9 +113,9 @@ pub fn execute_block(block: Block) { // execute transactions block.extrinsics.iter().enumerate().for_each(|(i, e)| { - storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); - execute_transaction_backend(e).map_err(|_| ()).expect("Extrinsic error"); - storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); + storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(i as u32)); + execute_transaction_backend(e).unwrap_or_else(|_| panic!("Invalid transaction")); + storage::unhashed::kill(well_known_keys::EXTRINSIC_INDEX); }); // check storage root. @@ -122,7 +152,7 @@ pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity { } let hash = |from: &AccountId, nonce: u64| { - twox_128(&nonce.to_keyed_vec(from.as_bytes())).to_vec() + twox_128(&nonce.to_keyed_vec(&from.encode())).to_vec() }; let requires = if tx.nonce != expected_nonce && tx.nonce > 0 { let mut deps = Vec::new(); @@ -144,7 +174,6 @@ pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity { } } - /// Execute a transaction outside of the block execution function. /// This doesn't attempt to validate anything regarding the block. pub fn execute_transaction(utx: Extrinsic) -> ApplyResult { @@ -225,8 +254,8 @@ fn execute_transfer_backend(tx: &Transfer) -> ApplyResult { Ok(ApplyOutcome::Success) } -fn execute_new_authorities_backend(new_authorities: &[Ed25519AuthorityId]) -> ApplyResult { - let new_authorities: Vec = new_authorities.iter().cloned().collect(); +fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyResult { + let new_authorities: Vec = new_authorities.iter().cloned().collect(); ::put(new_authorities); Ok(ApplyOutcome::Success) } @@ -258,12 +287,11 @@ mod tests { use runtime_io::{with_externalities, twox_128, TestExternalities}; use parity_codec::{Joiner, KeyedVec}; - use keyring::Keyring; - use crate::{Header, Digest, Extrinsic, Transfer}; + use substrate_test_client::{AuthorityKeyring, AccountKeyring}; + use crate::{Header, Extrinsic, Transfer}; use primitives::{Blake2Hasher, map}; use primitives::storage::well_known_keys; use substrate_executor::WasmExecutor; - use hex_literal::{hex, hex_impl}; const WASM_CODE: &'static [u8] = include_bytes!("../wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm"); @@ -272,36 +300,34 @@ mod tests { TestExternalities::new(map![ twox_128(b"latest").to_vec() => vec![69u8; 32], twox_128(well_known_keys::AUTHORITY_COUNT).to_vec() => vec![].and(&3u32), - twox_128(&0u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => Keyring::Alice.to_raw_public().to_vec(), - twox_128(&1u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => Keyring::Bob.to_raw_public().to_vec(), - twox_128(&2u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => Keyring::Charlie.to_raw_public().to_vec(), - twox_128(&Keyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + twox_128(&0u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Alice.to_raw_public().to_vec(), + twox_128(&1u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Bob.to_raw_public().to_vec(), + twox_128(&2u32.to_keyed_vec(well_known_keys::AUTHORITY_PREFIX)).to_vec() => AuthorityKeyring::Charlie.to_raw_public().to_vec(), + twox_128(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ]) } fn construct_signed_tx(tx: Transfer) -> Extrinsic { - let signature = Keyring::from_raw_public(tx.from.to_fixed_bytes()).unwrap().sign(&tx.encode()).into(); + let signature = AccountKeyring::from_public(&tx.from).unwrap().sign(&tx.encode()).into(); Extrinsic::Transfer(tx, signature) } fn block_import_works(block_executor: F) where F: Fn(Block, &mut TestExternalities) { - let mut t = new_test_ext(); - let h = Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("e51369d0b37e4aa1383f1e7a34c2eec75f18ee6b4b199a440f4f2456906e0eb7").into(), - extrinsics_root: hex!("03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314").into(), - digest: Digest { logs: vec![], }, + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), }; - - let b = Block { + let mut b = Block { header: h, extrinsics: vec![], }; - block_executor(b, &mut t); + with_externalities(&mut new_test_ext(), || polish_block(&mut b)); + block_executor(b, &mut new_test_ext()); } #[test] @@ -321,69 +347,74 @@ mod tests { } fn block_import_with_transaction_works(block_executor: F) where F: Fn(Block, &mut TestExternalities) { - let mut t = new_test_ext(); - - with_externalities(&mut t, || { - assert_eq!(balance_of(Keyring::Alice.to_raw_public().into()), 111); - assert_eq!(balance_of(Keyring::Bob.to_raw_public().into()), 0); - }); - - let b = Block { + let mut b1 = Block { header: Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("f61a14ce70846cd6a1714bbe1b63b2ca1172df1c8c01adfd798bb08bd30dc486").into(), - extrinsics_root: hex!("198205cb7729fec8ccdc2e58571a4858586a4f305898078e0e8bee1dddea7e4b").into(), - digest: Digest { logs: vec![], }, + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), }, extrinsics: vec![ construct_signed_tx(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Bob.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Bob.into(), amount: 69, nonce: 0, }) ], }; - with_externalities(&mut t, || { - execute_block(b.clone()); + let mut dummy_ext = new_test_ext(); + with_externalities(&mut dummy_ext, || polish_block(&mut b1)); - assert_eq!(balance_of(Keyring::Alice.to_raw_public().into()), 42); - assert_eq!(balance_of(Keyring::Bob.to_raw_public().into()), 69); - }); - - let b = Block { + let mut b2 = Block { header: Header { - parent_hash: b.header.hash(), + parent_hash: b1.header.hash(), number: 2, - state_root: hex!("a47383d9a5d6c8c7531386abccdf512c76729a1a19c59b6c2e4f95dde419923a").into(), - extrinsics_root: hex!("041fa8971dda28745967179a9f39e3ca1a595c510682105df1cff74ae6f05e0d").into(), - digest: Digest { logs: vec![], }, + state_root: Default::default(), + extrinsics_root: Default::default(), + digest: Default::default(), }, extrinsics: vec![ construct_signed_tx(Transfer { - from: Keyring::Bob.to_raw_public().into(), - to: Keyring::Alice.to_raw_public().into(), + from: AccountKeyring::Bob.into(), + to: AccountKeyring::Alice.into(), amount: 27, nonce: 0, }), construct_signed_tx(Transfer { - from: Keyring::Alice.to_raw_public().into(), - to: Keyring::Charlie.to_raw_public().into(), + from: AccountKeyring::Alice.into(), + to: AccountKeyring::Charlie.into(), amount: 69, nonce: 1, }), ], }; - block_executor(b, &mut t); + with_externalities(&mut dummy_ext, || polish_block(&mut b2)); + drop(dummy_ext); + + let mut t = new_test_ext(); with_externalities(&mut t, || { + assert_eq!(balance_of(AccountKeyring::Alice.into()), 111); + assert_eq!(balance_of(AccountKeyring::Bob.into()), 0); + }); + + block_executor(b1, &mut t); - assert_eq!(balance_of(Keyring::Alice.to_raw_public().into()), 0); - assert_eq!(balance_of(Keyring::Bob.to_raw_public().into()), 42); - assert_eq!(balance_of(Keyring::Charlie.to_raw_public().into()), 69); + with_externalities(&mut t, || { + assert_eq!(balance_of(AccountKeyring::Alice.into()), 42); + assert_eq!(balance_of(AccountKeyring::Bob.into()), 69); + }); + + block_executor(b2, &mut t); + + with_externalities(&mut t, || { + assert_eq!(balance_of(AccountKeyring::Alice.into()), 0); + assert_eq!(balance_of(AccountKeyring::Bob.into()), 42); + assert_eq!(balance_of(AccountKeyring::Charlie.into()), 69); }); } diff --git a/core/test-runtime/wasm/Cargo.lock b/core/test-runtime/wasm/Cargo.lock index fdba699543195..a5b87b4436956 100644 --- a/core/test-runtime/wasm/Cargo.lock +++ b/core/test-runtime/wasm/Cargo.lock @@ -1,5 +1,13 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arrayref" version = "0.3.5" @@ -481,6 +489,11 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hex-literal" version = "0.1.3" @@ -651,6 +664,11 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memoffset" version = "0.2.1" @@ -1120,6 +1138,26 @@ name = "redox_syscall" version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "regex" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ring" version = "0.14.6" @@ -1159,7 +1197,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "schnorrkel" version = "0.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/w3f/schnorrkel#3179838da9dd4896c12bb910e7c42477a3250641" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1168,6 +1206,7 @@ dependencies = [ "merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1441,11 +1480,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "substrate-bip39" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/paritytech/substrate-bip39#a28806512c977992af8d6740d45352f5a1c832a0" dependencies = [ "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1561,19 +1600,21 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", - "substrate-bip39 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)", "tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1947,6 +1988,11 @@ name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "uint" version = "0.6.1" @@ -1994,6 +2040,11 @@ dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vcpkg" version = "0.2.6" @@ -2066,6 +2117,7 @@ dependencies = [ ] [metadata] +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" @@ -2127,6 +2179,7 @@ dependencies = [ "checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "27455ce8b4a6666c87220e4b59c9a83995476bdadc10197905e61dbe906e36fa" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" "checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" @@ -2149,6 +2202,7 @@ dependencies = [ "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" @@ -2201,12 +2255,14 @@ dependencies = [ "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" "checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" -"checksum schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe554f318830b48e5da8ab1ccb1ffd02b79228364dac7766b7cd1ec461ca5116" +"checksum schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)" = "" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" @@ -2226,7 +2282,7 @@ dependencies = [ "checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum substrate-bip39 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec6183ce9e04bec5f113ff19c8ef5355dad20a4196134b5402732bf5d3c1a351" +"checksum substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)" = "" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" "checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec" @@ -2254,12 +2310,14 @@ dependencies = [ "checksum trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c6fef2705af3258ec46a7e22286090394a44216201a1cf7d04b78db825e543" "checksum twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "555cd4909480122bbbf21e34faac4cb08a171f324775670447ed116726c474af" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21ef487a11df1ed468cf613c78798c26282da5c30e9d49f824872d4c77b47d1d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm b/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm index 416fd30a5c971..ff8a7a70c368b 100644 Binary files a/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm and b/core/test-runtime/wasm/target/wasm32-unknown-unknown/release/substrate_test_runtime.compact.wasm differ diff --git a/core/transaction-pool/graph/src/pool.rs b/core/transaction-pool/graph/src/pool.rs index 202e9c752a581..0c4b4a6c1343d 100644 --- a/core/transaction-pool/graph/src/pool.rs +++ b/core/transaction-pool/graph/src/pool.rs @@ -453,7 +453,7 @@ mod tests { use super::*; use futures::Stream; use parity_codec::Encode; - use test_runtime::{Block, Extrinsic, Transfer, H256}; + use test_runtime::{Block, Extrinsic, Transfer, H256, AccountId}; use assert_matches::assert_matches; use crate::watcher; @@ -493,7 +493,7 @@ mod tests { /// Returns a block hash given the block id. fn block_id_to_hash(&self, at: &BlockId) -> Result>, Self::Error> { Ok(match at { - BlockId::Number(num) => Some(H256::from_low_u64_be(*num)), + BlockId::Number(num) => Some(H256::from_low_u64_be(*num)).into(), BlockId::Hash(_) => None, }) } @@ -502,7 +502,7 @@ mod tests { fn hash_and_length(&self, uxt: &ExtrinsicFor) -> (Self::Hash, usize) { let len = uxt.encode().len(); ( - (uxt.transfer().from.to_low_u64_be() << 5) + uxt.transfer().nonce, + (H256::from(uxt.transfer().from.clone()).to_low_u64_be() << 5) + uxt.transfer().nonce, len ) } @@ -524,8 +524,8 @@ mod tests { // when let hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -539,8 +539,8 @@ mod tests { // given let pool = pool(); let uxt = uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, }); @@ -564,21 +564,21 @@ mod tests { // when let _hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); let _hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap(); // future doesn't count let _hash = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 3, })).unwrap(); @@ -600,20 +600,20 @@ mod tests { // given let pool = pool(); let hash1 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); let hash2 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap(); let hash3 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 3, })).unwrap(); @@ -636,8 +636,8 @@ mod tests { // given let pool = pool(); let hash1 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -662,8 +662,8 @@ mod tests { }, TestApi::default()); let hash1 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap(); @@ -671,8 +671,8 @@ mod tests { // when let hash2 = pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(2), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(2)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 10, })).unwrap(); @@ -697,8 +697,8 @@ mod tests { // when pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap_err(); @@ -717,8 +717,8 @@ mod tests { // given let pool = pool(); let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -733,7 +733,7 @@ mod tests { // then let mut stream = watcher.into_stream().wait(); assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Finalised(H256::from_low_u64_be(2))))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Finalised(H256::from_low_u64_be(2).into())))); assert_eq!(stream.next(), None); } @@ -742,8 +742,8 @@ mod tests { // given let pool = pool(); let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -758,7 +758,7 @@ mod tests { // then let mut stream = watcher.into_stream().wait(); assert_eq!(stream.next(), Some(Ok(watcher::Status::Ready))); - assert_eq!(stream.next(), Some(Ok(watcher::Status::Finalised(H256::from_low_u64_be(2))))); + assert_eq!(stream.next(), Some(Ok(watcher::Status::Finalised(H256::from_low_u64_be(2).into())))); assert_eq!(stream.next(), None); } @@ -767,8 +767,8 @@ mod tests { // given let pool = pool(); let watcher = pool.submit_and_watch(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 1, })).unwrap(); @@ -777,8 +777,8 @@ mod tests { // when pool.submit_one(&BlockId::Number(0), uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, })).unwrap(); @@ -795,8 +795,8 @@ mod tests { // given let pool = pool(); let uxt = uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, }); @@ -819,8 +819,8 @@ mod tests { // given let pool = pool(); let uxt = uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, }); @@ -853,8 +853,8 @@ mod tests { }, TestApi::default()); let xt = uxt(Transfer { - from: H256::from_low_u64_be(1), - to: H256::from_low_u64_be(2), + from: AccountId::from_h256(H256::from_low_u64_be(1)), + to: AccountId::from_h256(H256::from_low_u64_be(2)), amount: 5, nonce: 0, }); @@ -863,8 +863,8 @@ mod tests { // when let xt = uxt(Transfer { - from: H256::from_low_u64_be(2), - to: H256::from_low_u64_be(1), + from: AccountId::from_h256(H256::from_low_u64_be(2)), + to: AccountId::from_h256(H256::from_low_u64_be(1)), amount: 4, nonce: 1, }); diff --git a/core/transaction-pool/src/tests.rs b/core/transaction-pool/src/tests.rs index e7a0f03339bbc..cab44f49cc79c 100644 --- a/core/transaction-pool/src/tests.rs +++ b/core/transaction-pool/src/tests.rs @@ -17,10 +17,9 @@ use super::*; -use keyring::Keyring::{self, *}; use parity_codec::Encode; use txpool::{self, Pool}; -use test_client::runtime::{AccountId, Block, Hash, Index, Extrinsic, Transfer}; +use test_client::{runtime::{AccountId, Block, Hash, Index, Extrinsic, Transfer}, AccountKeyring::{self, *}}; use sr_primitives::{ generic::{self, BlockId}, traits::{Hash as HashT, BlakeTwo256}, @@ -86,9 +85,9 @@ fn number_of(at: &BlockId) -> u64 { } } -fn uxt(who: Keyring, nonce: Index) -> Extrinsic { +fn uxt(who: AccountKeyring, nonce: Index) -> Extrinsic { let transfer = Transfer { - from: who.to_raw_public().into(), + from: who.into(), to: AccountId::default(), nonce, amount: 1, diff --git a/node-template/build.rs b/node-template/build.rs index d30f13c0c9d79..afc39d3b63c5e 100644 --- a/node-template/build.rs +++ b/node-template/build.rs @@ -1,6 +1,6 @@ use vergen::{ConstantsFlags, generate_cargo_keys}; -const ERROR_MSG: &'static str = "Failed to generate metadata files"; +const ERROR_MSG: &str = "Failed to generate metadata files"; fn main() { generate_cargo_keys(ConstantsFlags::all()).expect(ERROR_MSG); diff --git a/node-template/runtime/src/lib.rs b/node-template/runtime/src/lib.rs index fd696e9500a85..f46f8df249b6d 100644 --- a/node-template/runtime/src/lib.rs +++ b/node-template/runtime/src/lib.rs @@ -11,10 +11,10 @@ use parity_codec::{Encode, Decode}; use rstd::prelude::*; #[cfg(feature = "std")] use primitives::bytes; -use primitives::{Ed25519AuthorityId, OpaqueMetadata}; +use primitives::{ed25519, OpaqueMetadata}; use runtime_primitives::{ - ApplyResult, transaction_validity::TransactionValidity, Ed25519Signature, generic, - traits::{self, BlakeTwo256, Block as BlockT, StaticLookup}, create_runtime_str + ApplyResult, transaction_validity::TransactionValidity, generic, create_runtime_str, + traits::{self, BlakeTwo256, Block as BlockT, StaticLookup, Verify} }; use client::{ block_builder::api::{CheckInherentsResult, InherentData, self as block_builder_api}, @@ -34,8 +34,17 @@ pub use runtime_primitives::{Permill, Perbill}; pub use timestamp::BlockPeriod; pub use support::{StorageValue, construct_runtime}; -/// Alias to Ed25519 pubkey that identifies an account on the chain. -pub type AccountId = primitives::H256; +/// The type that is used for identifying authorities. +pub type AuthorityId = ::Signer; + +/// The type used by authorities to prove their ID. +pub type AuthoritySignature = ed25519::Signature; + +/// Alias to pubkey that identifies an account on the chain. +pub type AccountId = ::Signer; + +/// The type used by authorities to prove their ID. +pub type AccountSignature = ed25519::Signature; /// A hash of some data used by the chain. pub type Hash = primitives::H256; @@ -66,13 +75,13 @@ pub mod opaque { } } /// Opaque block header type. - pub type Header = generic::Header>; + pub type Header = generic::Header>; /// Opaque block type. pub type Block = generic::Block; /// Opaque block identifier type. pub type BlockId = generic::BlockId; /// Opaque session key type. - pub type SessionKey = Ed25519AuthorityId; + pub type SessionKey = AuthorityId; } /// This runtime version. @@ -125,7 +134,7 @@ impl aura::Trait for Runtime { impl consensus::Trait for Runtime { /// The identifier we use to refer to authorities. - type SessionKey = Ed25519AuthorityId; + type SessionKey = AuthorityId; // The aura module handles offline-reports internally // rather than using an explicit report system. type InherentOfflineReport = (); @@ -179,7 +188,7 @@ impl template::Trait for Runtime { } construct_runtime!( - pub enum Runtime with Log(InternalLog: DigestItem) where + pub enum Runtime with Log(InternalLog: DigestItem) where Block = Block, NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic @@ -208,7 +217,7 @@ pub type Block = generic::Block; /// BlockId type as expected by this runtime. pub type BlockId = generic::BlockId; /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedMortalCompactExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. @@ -221,7 +230,7 @@ impl_runtime_apis! { VERSION } - fn authorities() -> Vec { + fn authorities() -> Vec { Consensus::authorities() } diff --git a/node-template/runtime/wasm/Cargo.lock b/node-template/runtime/wasm/Cargo.lock index bfcafe4e79233..98c611de64ec2 100644 --- a/node-template/runtime/wasm/Cargo.lock +++ b/node-template/runtime/wasm/Cargo.lock @@ -1,5 +1,13 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arrayref" version = "0.3.5" @@ -36,7 +44,7 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -53,7 +61,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitmask" version = "0.5.0" -source = "git+https://github.com/paritytech/bitmask#c2d8d196e30b018d1385be8357fdca61b978facf" +source = "git+https://github.com/paritytech/bitmask#a84e147be602631617badd18b6b9af83391db4a9" [[package]] name = "blake2-rfc" @@ -118,7 +126,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -141,7 +149,7 @@ name = "clear_on_drop" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -370,7 +378,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -481,6 +489,11 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hex-literal" version = "0.1.3" @@ -651,6 +664,11 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memoffset" version = "0.2.1" @@ -832,7 +850,7 @@ name = "openssl-sys" version = "0.9.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -870,7 +888,7 @@ dependencies = [ "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -919,7 +937,7 @@ dependencies = [ "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -976,7 +994,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1154,12 +1172,32 @@ name = "redox_syscall" version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "regex" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ring" version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1245,7 +1283,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1357,7 +1395,7 @@ dependencies = [ "proc-macro-crate 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1594,7 +1632,7 @@ dependencies = [ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "sr-api-macros 0.1.0", "srml-support-procedural-tools 0.1.0", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1605,7 +1643,7 @@ dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "srml-support-procedural-tools-derive 0.1.0", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1614,7 +1652,7 @@ version = "0.1.0" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1780,11 +1818,13 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", @@ -1864,7 +1904,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.27" +version = "0.15.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1879,7 +1919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2137,6 +2177,11 @@ name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "uint" version = "0.6.1" @@ -2184,6 +2229,11 @@ dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vcpkg" version = "0.2.6" @@ -2256,6 +2306,7 @@ dependencies = [ ] [metadata] +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" @@ -2272,7 +2323,7 @@ dependencies = [ "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" +"checksum cc 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ce8bb087aacff865633f0bd5aeaed910fe2fe55b55f4739527f2e023a2e53d" "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" @@ -2317,6 +2368,7 @@ dependencies = [ "checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "27455ce8b4a6666c87220e4b59c9a83995476bdadc10197905e61dbe906e36fa" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" "checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" @@ -2339,6 +2391,7 @@ dependencies = [ "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" @@ -2391,6 +2444,8 @@ dependencies = [ "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" "checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" @@ -2420,7 +2475,7 @@ dependencies = [ "checksum substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)" = "" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" -"checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec" +"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" @@ -2445,12 +2500,14 @@ dependencies = [ "checksum trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c6fef2705af3258ec46a7e22286090394a44216201a1cf7d04b78db825e543" "checksum twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "555cd4909480122bbbf21e34faac4cb08a171f324775670447ed116726c474af" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21ef487a11df1ed468cf613c78798c26282da5c30e9d49f824872d4c77b47d1d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/node-template/src/chain_spec.rs b/node-template/src/chain_spec.rs index b9f61e45f546b..fa5b44c65a02b 100644 --- a/node-template/src/chain_spec.rs +++ b/node-template/src/chain_spec.rs @@ -1,10 +1,13 @@ -use primitives::{Ed25519AuthorityId, ed25519}; +use primitives::{ed25519, Pair}; use node_template_runtime::{ AccountId, GenesisConfig, ConsensusConfig, TimestampConfig, BalancesConfig, SudoConfig, IndicesConfig, FeesConfig, }; +use substrate_cli::DEV_PHRASE; use substrate_service; +use ed25519::Public as AuthorityId; + // Note this is the URL for the telemetry server //const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; @@ -22,6 +25,18 @@ pub enum Alternative { LocalTestnet, } +fn authority_key(s: &str) -> AuthorityId { + ed25519::Pair::from_string(&format!("{}//{}", DEV_PHRASE, s), None) + .expect("static values are valid; qed") + .public() +} + +fn account_key(s: &str) -> AccountId { + ed25519::Pair::from_string(&format!("{}//{}", DEV_PHRASE, s), None) + .expect("static values are valid; qed") + .public() +} + impl Alternative { /// Get an actual chain config from one of the alternatives. pub(crate) fn load(self) -> Result { @@ -30,11 +45,11 @@ impl Alternative { "Development", "dev", || testnet_genesis(vec![ - ed25519::Pair::from_seed(b"Alice ").public().into(), + authority_key("Alice") ], vec![ - ed25519::Pair::from_seed(b"Alice ").public().0.into(), + account_key("Alice") ], - ed25519::Pair::from_seed(b"Alice ").public().0.into() + account_key("Alice") ), vec![], None, @@ -46,17 +61,17 @@ impl Alternative { "Local Testnet", "local_testnet", || testnet_genesis(vec![ - ed25519::Pair::from_seed(b"Alice ").public().into(), - ed25519::Pair::from_seed(b"Bob ").public().into(), + authority_key("Alice"), + authority_key("Bob"), ], vec![ - ed25519::Pair::from_seed(b"Alice ").public().0.into(), - ed25519::Pair::from_seed(b"Bob ").public().0.into(), - ed25519::Pair::from_seed(b"Charlie ").public().0.into(), - ed25519::Pair::from_seed(b"Dave ").public().0.into(), - ed25519::Pair::from_seed(b"Eve ").public().0.into(), - ed25519::Pair::from_seed(b"Ferdie ").public().0.into(), + account_key("Alice"), + account_key("Bob"), + account_key("Charlie"), + account_key("Dave"), + account_key("Eve"), + account_key("Ferdie"), ], - ed25519::Pair::from_seed(b"Alice ").public().0.into() + account_key("Alice"), ), vec![], None, @@ -76,7 +91,7 @@ impl Alternative { } } -fn testnet_genesis(initial_authorities: Vec, endowed_accounts: Vec, root_key: AccountId) -> GenesisConfig { +fn testnet_genesis(initial_authorities: Vec, endowed_accounts: Vec, root_key: AccountId) -> GenesisConfig { GenesisConfig { consensus: Some(ConsensusConfig { code: include_bytes!("../runtime/wasm/target/wasm32-unknown-unknown/release/node_template_runtime_wasm.compact.wasm").to_vec(), @@ -93,7 +108,7 @@ fn testnet_genesis(initial_authorities: Vec, endowed_account existential_deposit: 500, transfer_fee: 0, creation_fee: 0, - balances: endowed_accounts.iter().map(|&k|(k, (1 << 60))).collect(), + balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(), vesting: vec![], }), sudo: Some(SudoConfig { diff --git a/node-template/src/service.rs b/node-template/src/service.rs index cc51fba51c3f4..1bb97256aea70 100644 --- a/node-template/src/service.rs +++ b/node-template/src/service.rs @@ -15,7 +15,7 @@ use basic_authorship::ProposerFactory; use node_executor; use consensus::{import_queue, start_aura, AuraImportQueue, SlotDuration, NothingExtra}; use substrate_client as client; -use primitives::ed25519::Pair; +use primitives::{ed25519::Pair, Pair as _Pair}; use inherents::InherentDataProviders; use network::construct_simple_protocol; use substrate_executor::native_executor_instance; diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs index 27441a9ecc210..784dcf5a75d59 100644 --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -16,7 +16,7 @@ //! Substrate chain configurations. -use primitives::{Ed25519AuthorityId as AuthorityId, ed25519}; +use primitives::{ed25519::Public as AuthorityId, ed25519, sr25519, Pair, crypto::UncheckedInto}; use node_primitives::AccountId; use node_runtime::{ConsensusConfig, CouncilSeatsConfig, CouncilVotingConfig, DemocracyConfig, SessionConfig, StakingConfig, TimestampConfig, BalancesConfig, TreasuryConfig, @@ -24,9 +24,8 @@ use node_runtime::{ConsensusConfig, CouncilSeatsConfig, CouncilVotingConfig, Dem pub use node_runtime::GenesisConfig; use substrate_service; use hex_literal::{hex, hex_impl}; - -use substrate_keystore::pad_seed; use substrate_telemetry::TelemetryEndpoints; +use cli::DEV_PHRASE; const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; @@ -40,25 +39,30 @@ pub fn dried_danta_config() -> Result { fn staging_testnet_config_genesis() -> GenesisConfig { // stash, controller, session-key + // generated with secret: + // for i in 1 2 3 4 ; do for j in stash controller; do subkey -p danta-$i-$j restore $secret; done; done + // and + // for i in 1 2 3 4 ; do for j in session; do subkey --ed25519 -p danta-$i-$j restore $secret; done; done let initial_authorities: Vec<(AccountId, AccountId, AuthorityId)> = vec![( - hex!["fbecf7767fc63a6f9fa8094bbc5751d7269cd8e619cfdd9edfbe1fbc716b173e"].into(), // 5Hm2GcbuUct7sWX8d56zRktxr9D9Lw5hTFjSUhUoVHwFNmYW TODO: change once we switch to sr25519 - hex!["6ed35e632190b9c795f019030e6c5cff1508655db28c83577e0a4366c9bd5773"].into(), // 5Ea1uyGz6H5WHZhWvPDxxLXWyiUkzWDwx54Hcn8LJ5dbFawH TODO: change once we switch to sr25519 - hex!["82c39b31a2b79a90f8e66e7a77fdb85a4ed5517f2ae39f6a80565e8ecae85cf5"].into(), + hex!["d807f8bd6b4b02b3db716dd5372960b094ed0e62b5704a07bc990130a642992b"].unchecked_into(), // 5GwxZv7LxSUQn89TLUaLi3oEWhFcabqW3nHcEg2J88gZNhrb + hex!["1a934af462454e512e22b5d9455c0c3c2df479b1c61406b3d990f6bc2eb25e09"].unchecked_into(), // 5CfYrg5cW8UebBdfJpJbKFhZLyk7yHWXUgdxZnSGb2dWKgpt + hex!["831fcce3a9565baf093b52568a8cb9875cb54974d80da8fc4f0cc767128a23e9"].unchecked_into(), // 5F2daQPHK7yv4Yuwyz3cggvvn1R5u1ofGMQ5LK5XvnfebMcX ),( - hex!["30b76ef977b84a575992ef52f561db315221123c68074269d3d51ce211c4a3dc"].into(), // 5DAaeTwVuyUmTyLBR5vKEDWeDJ75nhLutDuCJH58it7EHDM2 TODO: change once we switch to sr25519 - hex!["a270edf24cb2a472b0e913fc43bfd4da0ef337cc715eaf94073d5198f7659f0c"].into(), // 5FjhAKgzpuzt1dYWE7H7Jb1sEHSuG5hcyZdPtfX829gmFVXh TODO: change once we switch to sr25519 - hex!["4de37a07567ebcbf8c64568428a835269a566723687058e017b6d69db00a77e7"].into(), + hex!["12652f26e427c56268095bb0ec5824471e37722b073a9fa5de61c61c1de94656"].unchecked_into(), // 5CUpn2JmpsWkHQjZgWjN3rqPEUnjjUQZYcMk14nbUgR2Gpab + hex!["5279e73e22971d729276ebad4eb6804d1b9c0c35bd32e8aba4513c674760a461"].unchecked_into(), // 5Dvqzke7Mdp3fP6Ysut7UXPSepPr3Qguys6LNkZGPSwXwAkR + hex!["dbe61640d854bb7bf83cbfaf638a8a4c76c49a919ec3bbdd86799061fc1903e4"].unchecked_into(), // 5H32hCtKf6nXSckviVhUvWb7N14wDCRunRkCM29mxEXwjcUZ ),( - hex!["7b9e79c1bfc71ad0c4389565c01e79269dc512cb9bd856489671662481355417"].into(), // 5ErnpkRUbmM3WdbQwnVwfZeYs3iKmggEQceyB9db9ft18dSn TODO: change once we switch to sr25519 - hex!["9ffec660c4d328306cf5e38faf4b132fb5c9f38287af95d9b25629fc29de3945"].into(), // 5FgV9vxNpdCXMUmHCLQcsN4mUUUG6ZpFuvAMrm5X4BUnFhie TODO: change once we switch to sr25519 - hex!["063d7787ebca768b7445dfebe7d62cbb1625ff4dba288ea34488da266dd6dca5"].into(), + hex!["a81d738fdeeaed440cfce5635e0820d0d23e89207cf66a62b8c0d2a968e37d32"].unchecked_into(), // 5Fs8ehAjDEnenDwULCPnEr3HVXgepAVfyk9ABW84NfxCYtWD + hex!["443a2c779a5f5dada8ee6921efec9673f67e5ce1bd6012899ff6c1adc437696c"].unchecked_into(), // 5DcAPqR269myKXhZmwbU1x2xLbuTojr85jHNRuDhrFdZ3vwi + hex!["5bc01f56225e8602372fb343dba65a73e20c55bdbb3b8343a8f34df298a616fb"].unchecked_into(), // 5E91HbY2xo2qDJzi3KY8nRXjDNAQE9WtmMaji6YRwT8DAuK1 ),( - hex!["7e58b096b95c4b3b271f27fedd9f2c51edd48b9d37046240e601180c9dcc8c27"].into(), // 5EvNEhYYd4b9giczuCo2o8bfLZoKW9jnTeUukfL1NWsAAeEx TODO: change once we switch to sr25519 - hex!["36dfc933bb0848d8addf16a961369b2e122633a5819a19e43c8142381a1280e3"].into(), // 5DJevPKpz4EEvmSpK7W6KemS3i5JYPq5FEuEewgRY2cZCxNg TODO: change once we switch to sr25519 - hex!["8101764f45778d4980dadaceee6e8af2517d3ab91ac9bec9cd1714fa5994081c"].into(), + hex!["e269e835e0bc07c497d55bc17c7bb29c85c5615f9e61582ffdeca7e5f5c66578"].unchecked_into(), // 5HBa95U5HDFCV1N5Xyrjti65F71tHRQcPbZBmkxRJ39SpqzM + hex!["3e9829e6fd4fc7501b504fc16f12177c6c7f38aeb3b8344efb9b15ee85118b2c"].unchecked_into(), // 5DUn2afs2QevZ6PrGu8snrt76157oacH6JXUD8JNM18VKMwK + hex!["0fd673ee5e95ed124bcd71463ff924c810573dad91527ab9d2b5af36f66ff84b"].unchecked_into(), // 5CRUHGLA1JYe2v4p479VCHybqjB9uBXjGkJ2npdduVdrTuUM )]; + // generated with secret: subkey -p danta-root restore $secret let endowed_accounts: Vec = vec![ - hex!["f295940fa750df68a686fcf4abd4111c8a9c5a5a5a83c4c8639c451a94a7adfd"].into(), // 5HYmsxGRAmZMjyZYmf7uGPL2YDQGHEt6NjGrfUuxNEgeGBRN TODO: change once we switch to sr25519 + hex!["343df6f04ffae0840f214f6cb0da00b612c7e9347f980e7afafc520582f79136"].unchecked_into(), // 5DFCkiP9vky31C1ZP3LpuQYinLAFwQqq6vda7NXa8ALCpq5D ]; const MILLICENTS: u128 = 1_000_000_000; const CENTS: u128 = 1_000 * MILLICENTS; // assume this is worth about a cent. @@ -79,8 +83,8 @@ fn staging_testnet_config_genesis() -> GenesisConfig { }), system: None, balances: Some(BalancesConfig { - balances: endowed_accounts.iter() - .map(|&k| (k, ENDOWMENT)) + balances: endowed_accounts.iter().cloned() + .map(|k| (k, ENDOWMENT)) .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH))) .collect(), existential_deposit: 1 * DOLLARS, @@ -94,7 +98,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig { .collect::>(), }), session: Some(SessionConfig { - validators: initial_authorities.iter().map(|x| x.1.into()).collect(), + validators: initial_authorities.iter().map(|x| x.1.clone()).collect(), session_length: 5 * MINUTES, keys: initial_authorities.iter().map(|x| (x.1.clone(), x.2.clone())).collect::>(), }), @@ -109,8 +113,8 @@ fn staging_testnet_config_genesis() -> GenesisConfig { bonding_duration: 60 * MINUTES, offline_slash_grace: 4, minimum_validator_count: 4, - stakers: initial_authorities.iter().map(|x| (x.0.into(), x.1.into(), STASH)).collect(), - invulnerables: initial_authorities.iter().map(|x| x.1.into()).collect(), + stakers: initial_authorities.iter().map(|x| (x.0.clone(), x.1.clone(), STASH)).collect(), + invulnerables: initial_authorities.iter().map(|x| x.1.clone()).collect(), }), democracy: Some(DemocracyConfig { launch_period: 10 * MINUTES, // 1 day per public referendum @@ -182,23 +186,26 @@ pub fn staging_testnet_config() -> ChainSpec { ) } -/// Helper function to generate AuthorityID from seed +/// Helper function to generate AccountId from seed pub fn get_account_id_from_seed(seed: &str) -> AccountId { - let padded_seed = pad_seed(seed); - // NOTE from ed25519 impl: - // prefer pkcs#8 unless security doesn't matter -- this is used primarily for tests. - ed25519::Pair::from_seed(&padded_seed).public().0.into() + sr25519::Pair::from_string(&format!("{}//{}", DEV_PHRASE, seed), None) + .expect("static values are valid; qed") + .public() +} + +/// Helper function to generate AuthorityId from seed +pub fn get_session_key_from_seed(seed: &str) -> AuthorityId { + ed25519::Pair::from_string(&format!("{}//{}", DEV_PHRASE, seed), None) + .expect("static values are valid; qed") + .public() } /// Helper function to generate stash, controller and session key from seed pub fn get_authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, AuthorityId) { - let padded_seed = pad_seed(seed); - // NOTE from ed25519 impl: - // prefer pkcs#8 unless security doesn't matter -- this is used primarily for tests. ( - get_account_id_from_seed(&format!("{}-stash", seed)), + get_account_id_from_seed(&format!("{}//stash", seed)), get_account_id_from_seed(seed), - ed25519::Pair::from_seed(&padded_seed).public().0.into() + get_session_key_from_seed(seed) ) } @@ -216,6 +223,12 @@ pub fn testnet_genesis( get_account_id_from_seed("Dave"), get_account_id_from_seed("Eve"), get_account_id_from_seed("Ferdie"), + get_account_id_from_seed("Alice//stash"), + get_account_id_from_seed("Bob//stash"), + get_account_id_from_seed("Charlie//stash"), + get_account_id_from_seed("Dave//stash"), + get_account_id_from_seed("Eve//stash"), + get_account_id_from_seed("Ferdie//stash"), ] }); @@ -235,11 +248,11 @@ pub fn testnet_genesis( existential_deposit: 500, transfer_fee: 0, creation_fee: 0, - balances: endowed_accounts.iter().map(|&k| (k.into(), ENDOWMENT)).collect(), + balances: endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT)).collect(), vesting: vec![], }), session: Some(SessionConfig { - validators: initial_authorities.iter().map(|x| x.1.into()).collect(), + validators: initial_authorities.iter().map(|x| x.1.clone()).collect(), session_length: 10, keys: initial_authorities.iter().map(|x| (x.1.clone(), x.2.clone())).collect::>(), }), @@ -254,8 +267,8 @@ pub fn testnet_genesis( current_offline_slash: 0, current_session_reward: 0, offline_slash_grace: 0, - stakers: initial_authorities.iter().map(|x| (x.0.into(), x.1.into(), STASH)).collect(), - invulnerables: initial_authorities.iter().map(|x| x.1.into()).collect(), + stakers: initial_authorities.iter().map(|x| (x.0.clone(), x.1.clone(), STASH)).collect(), + invulnerables: initial_authorities.iter().map(|x| x.1.clone()).collect(), }), democracy: Some(DemocracyConfig { launch_period: 9, @@ -267,7 +280,7 @@ pub fn testnet_genesis( council_seats: Some(CouncilSeatsConfig { active_council: endowed_accounts.iter() .filter(|&endowed| initial_authorities.iter().find(|&(_, controller, _)| controller == endowed).is_none()) - .map(|a| (a.clone().into(), 1000000)).collect(), + .map(|a| (a.clone(), 1000000)).collect(), candidacy_bond: 10, voter_bond: 2, present_slash_per_voter: 1, @@ -275,7 +288,7 @@ pub fn testnet_genesis( presentation_duration: 10, approval_voting_period: 20, term_duration: 1000000, - desired_seats: (endowed_accounts.len() - initial_authorities.len()) as u32, + desired_seats: (endowed_accounts.len() / 2 - initial_authorities.len()) as u32, inactive_grace_period: 1, }), council_voting: Some(CouncilVotingConfig { @@ -319,8 +332,8 @@ fn development_config_genesis() -> GenesisConfig { vec![ get_authority_keys_from_seed("Alice"), ], - get_account_id_from_seed("Alice").into(), - Some(vec![get_authority_keys_from_seed("Alice").0]), + get_account_id_from_seed("Alice"), + None, ) } @@ -335,11 +348,8 @@ fn local_testnet_genesis() -> GenesisConfig { get_authority_keys_from_seed("Alice"), get_authority_keys_from_seed("Bob"), ], - get_account_id_from_seed("Alice").into(), - Some(vec![ - get_authority_keys_from_seed("Alice").0, - get_authority_keys_from_seed("Bob").0, - ]), + get_account_id_from_seed("Alice"), + None, ) } diff --git a/node/cli/src/service.rs b/node/cli/src/service.rs index 1c865956f90a6..dd03b25bb9349 100644 --- a/node/cli/src/service.rs +++ b/node/cli/src/service.rs @@ -25,7 +25,7 @@ use client; use consensus::{import_queue, start_aura, AuraImportQueue, SlotDuration, NothingExtra}; use grandpa; use node_executor; -use primitives::ed25519::Pair; +use primitives::{Pair as _Pair, ed25519::Pair}; use node_primitives::Block; use node_runtime::{GenesisConfig, RuntimeApi}; use substrate_service::{ diff --git a/node/executor/src/lib.rs b/node/executor/src/lib.rs index 7db47236a8d82..8e1a2162da982 100644 --- a/node/executor/src/lib.rs +++ b/node/executor/src/lib.rs @@ -31,15 +31,13 @@ mod tests { use super::Executor; use substrate_executor::{WasmExecutor, NativeExecutionDispatch}; use parity_codec::{Encode, Decode, Joiner}; - use keyring::ed25519::Keyring; + use keyring::{AccountKeyring, AuthorityKeyring}; use runtime_support::{Hashable, StorageValue, StorageMap, traits::Currency}; use state_machine::{CodeExecutor, Externalities, TestExternalities}; - use primitives::{ - twox_128, Blake2Hasher, ChangesTrieConfiguration, ed25519::{Public, Pair}, NeverNativeValue, - NativeOrEncoded - }; + use primitives::{twox_128, Blake2Hasher, ChangesTrieConfiguration, NeverNativeValue, + NativeOrEncoded}; use node_primitives::{Hash, BlockNumber, AccountId}; - use runtime_primitives::traits::{Header as HeaderT, Digest as DigestT, Hash as HashT}; + use runtime_primitives::traits::{Header as HeaderT, Hash as HashT}; use runtime_primitives::{generic, generic::Era, ApplyOutcome, ApplyError, ApplyResult, Perbill}; use {balances, indices, session, system, consensus, timestamp, treasury, contract}; use contract::ContractAddressFor; @@ -55,27 +53,27 @@ mod tests { const GENESIS_HASH: [u8; 32] = [69u8; 32]; fn alice() -> AccountId { - AccountId::from(Keyring::Alice.to_raw_public()) + AccountKeyring::Alice.into() } fn bob() -> AccountId { - AccountId::from(Keyring::Bob.to_raw_public()) + AccountKeyring::Bob.into() } fn charlie() -> AccountId { - AccountId::from(Keyring::Charlie.to_raw_public()) + AccountKeyring::Charlie.into() } fn dave() -> AccountId { - AccountId::from(Keyring::Dave.to_raw_public()) + AccountKeyring::Dave.into() } fn eve() -> AccountId { - AccountId::from(Keyring::Eve.to_raw_public()) + AccountKeyring::Eve.into() } fn ferdie() -> AccountId { - AccountId::from(Keyring::Ferdie.to_raw_public()) + AccountKeyring::Ferdie.into() } fn sign(xt: CheckedExtrinsic) -> UncheckedExtrinsic { @@ -83,12 +81,12 @@ mod tests { Some((signed, index)) => { let era = Era::mortal(256, 0); let payload = (index.into(), xt.function, era, GENESIS_HASH); - let pair = Pair::from(Keyring::from_public(Public::from_raw(signed.clone().into())).unwrap()); + let key = AccountKeyring::from_public(&signed).unwrap(); let signature = payload.using_encoded(|b| { if b.len() > 256 { - pair.sign(&runtime_io::blake2_256(b)) + key.sign(&runtime_io::blake2_256(b)) } else { - pair.sign(b) + key.sign(b) } }).into(); UncheckedExtrinsic { @@ -259,7 +257,7 @@ mod tests { } fn new_test_ext(code: &[u8], support_changes_trie: bool) -> TestExternalities { - let three = [3u8; 32].into(); + let three = AccountId::from_raw([3u8; 32]); TestExternalities::new_with_code(code, GenesisConfig { consensus: Some(Default::default()), system: Some(SystemConfig { @@ -288,11 +286,11 @@ mod tests { }), session: Some(SessionConfig { session_length: 2, - validators: vec![Keyring::One.to_raw_public().into(), Keyring::Two.to_raw_public().into(), three], + validators: vec![AccountKeyring::One.into(), AccountKeyring::Two.into(), three], keys: vec![ - (alice(), keyring::ed25519::Keyring::Alice.to_raw_public().into()), - (bob(), keyring::ed25519::Keyring::Bob.to_raw_public().into()), - (charlie(), keyring::ed25519::Keyring::Charlie.to_raw_public().into()) + (alice(), AuthorityKeyring::Alice.into()), + (bob(), AuthorityKeyring::Bob.into()), + (charlie(), AuthorityKeyring::Charlie.into()) ] }), staking: Some(StakingConfig { @@ -317,11 +315,7 @@ mod tests { contract: Some(Default::default()), sudo: Some(Default::default()), grandpa: Some(GrandpaConfig { - authorities: vec![ // set these so no GRANDPA events fire when session changes - (keyring::ed25519::Keyring::Charlie.to_raw_public().into(), 1), - (keyring::ed25519::Keyring::Bob.to_raw_public().into(), 1), - (keyring::ed25519::Keyring::Alice.to_raw_public().into(), 1), - ], + authorities: vec![], }), fees: Some(FeesConfig { transaction_base_fee: 1, @@ -447,12 +441,7 @@ mod tests { ] ); - let mut digest = generic::Digest::::default(); - digest.push(Log::from(::grandpa::RawLog::AuthoritiesChangeSignal(0, vec![ - (Keyring::Alice.to_raw_public().into(), 1), - (Keyring::Bob.to_raw_public().into(), 1), - (Keyring::Charlie.to_raw_public().into(), 1), - ]))); + let digest = generic::Digest::::default(); assert_eq!(Header::decode(&mut &block2.0[..]).unwrap().digest, digest); (block1, block2) @@ -585,18 +574,6 @@ mod tests { phase: Phase::Finalization, event: Event::session(session::RawEvent::NewSession(1)) }, - // EventRecord { - // phase: Phase::Finalization, - // event: Event::staking(staking::RawEvent::Reward(0)) - // }, - EventRecord { - phase: Phase::Finalization, - event: Event::grandpa(::grandpa::RawEvent::NewAuthorities(vec![ - (Keyring::Alice.to_raw_public().into(), 1), - (Keyring::Bob.to_raw_public().into(), 1), - (Keyring::Charlie.to_raw_public().into(), 1), - ])), - }, EventRecord { phase: Phase::Finalization, event: Event::treasury(treasury::RawEvent::Spending(0)) @@ -767,7 +744,7 @@ mod tests { CheckedExtrinsic { signed: Some((charlie(), 2)), function: Call::Contract( - contract::Call::call::(indices::address::Address::Id(addr), 10, 10_000, vec![0x00, 0x01, 0x02, 0x03]) + contract::Call::call::(indices::address::Address::Id(addr.clone()), 10, 10_000, vec![0x00, 0x01, 0x02, 0x03]) ), }, ] diff --git a/node/primitives/src/lib.rs b/node/primitives/src/lib.rs index a73209a9ab161..8c23e5d32bf25 100644 --- a/node/primitives/src/lib.rs +++ b/node/primitives/src/lib.rs @@ -22,14 +22,14 @@ #![cfg_attr(not(feature = "std"), feature(alloc))] use runtime_primitives::{ - generic, traits::{Verify, BlakeTwo256}, Ed25519Signature, OpaqueExtrinsic + generic, traits::{Verify, BlakeTwo256}, OpaqueExtrinsic }; /// An index to a block. pub type BlockNumber = u64; -/// Alias to 512-bit hash when used in the context of a signature on the chain. -pub type Signature = Ed25519Signature; +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = primitives::sr25519::Signature; /// Some way of identifying an account on the chain. We intentionally make it equivalent /// to the public key of our transaction signing scheme. @@ -44,7 +44,10 @@ pub type Balance = u128; /// The Ed25519 pub key of an session that belongs to an authority of the chain. This is /// exactly equivalent to what the substrate calls an "authority". -pub type SessionKey = primitives::Ed25519AuthorityId; +pub type AuthorityId = ::Signer; + +/// Alias to 512-bit hash when used in the context of a session signature on the chain. +pub type AuthoritySignature = primitives::ed25519::Signature; /// Index of a transaction in the chain. pub type Index = u64; @@ -56,7 +59,8 @@ pub type Hash = primitives::H256; pub type Timestamp = u64; /// Header type. -pub type Header = generic::Header>; +/// +pub type Header = generic::Header>; /// Block type. pub type Block = generic::Block; /// Block ID. diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 45b252b04cb67..eab07326a0649 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -27,7 +27,7 @@ use support::{Serialize, Deserialize}; use support::construct_runtime; use substrate_primitives::u32_trait::{_2, _4}; use node_primitives::{ - AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, SessionKey, Signature + AccountId, AccountIndex, Balance, BlockNumber, Hash, Index, AuthorityId, Signature, AuthoritySignature }; use grandpa::fg_primitives::{self, ScheduledChange}; use client::{ @@ -37,7 +37,7 @@ use client::{ use runtime_primitives::{ApplyResult, generic, create_runtime_str}; use runtime_primitives::transaction_validity::TransactionValidity; use runtime_primitives::traits::{ - Convert, BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, + BlakeTwo256, Block as BlockT, DigestFor, NumberFor, StaticLookup, }; use version::RuntimeVersion; use council::{motions as council_motions, voting as council_voting}; @@ -60,7 +60,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("node"), impl_name: create_runtime_str!("substrate-node"), authoring_version: 10, - spec_version: 34, + spec_version: 35, impl_version: 35, apis: RUNTIME_API_VERSIONS, }; @@ -113,7 +113,7 @@ impl fees::Trait for Runtime { impl consensus::Trait for Runtime { type Log = Log; - type SessionKey = SessionKey; + type SessionKey = AuthorityId; // The Aura module handles offline-reports internally // rather than using an explicit report system. @@ -125,16 +125,8 @@ impl timestamp::Trait for Runtime { type OnTimestampSet = Aura; } -/// Session key conversion. -pub struct SessionKeyConversion; -impl Convert for SessionKeyConversion { - fn convert(a: AccountId) -> SessionKey { - a.to_fixed_bytes().into() - } -} - impl session::Trait for Runtime { - type ConvertAccountIdToSessionKey = SessionKeyConversion; + type ConvertAccountIdToSessionKey = (); type OnSessionChange = (Staking, grandpa::SyncedAuthorities); type Event = Event; } @@ -186,7 +178,7 @@ impl sudo::Trait for Runtime { } impl grandpa::Trait for Runtime { - type SessionKey = SessionKey; + type SessionKey = AuthorityId; type Log = Log; type Event = Event; } @@ -196,7 +188,7 @@ impl finality_tracker::Trait for Runtime { } construct_runtime!( - pub enum Runtime with Log(InternalLog: DigestItem) where + pub enum Runtime with Log(InternalLog: DigestItem) where Block = Block, NodeBlock = node_primitives::Block, UncheckedExtrinsic = UncheckedExtrinsic @@ -246,7 +238,7 @@ impl_runtime_apis! { VERSION } - fn authorities() -> Vec { + fn authorities() -> Vec { Consensus::authorities() } @@ -322,7 +314,7 @@ impl_runtime_apis! { None } - fn grandpa_authorities() -> Vec<(SessionKey, u64)> { + fn grandpa_authorities() -> Vec<(AuthorityId, u64)> { Grandpa::grandpa_authorities() } } diff --git a/node/runtime/wasm/Cargo.lock b/node/runtime/wasm/Cargo.lock index f6cfef7c80957..543020eed7a47 100644 --- a/node/runtime/wasm/Cargo.lock +++ b/node/runtime/wasm/Cargo.lock @@ -1,5 +1,13 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "aho-corasick" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "arrayref" version = "0.3.5" @@ -481,6 +489,11 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "hex-literal" version = "0.1.3" @@ -651,6 +664,11 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "memchr" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memoffset" version = "0.2.1" @@ -1189,6 +1207,26 @@ name = "redox_syscall" version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "regex" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ring" version = "0.14.6" @@ -1236,7 +1274,7 @@ dependencies = [ [[package]] name = "schnorrkel" version = "0.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/w3f/schnorrkel#3179838da9dd4896c12bb910e7c42477a3250641" dependencies = [ "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "curve25519-dalek 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1245,6 +1283,7 @@ dependencies = [ "merlin 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1610,6 +1649,7 @@ dependencies = [ "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 0.1.0", "sr-std 0.1.0", + "srml-consensus 0.1.0", "srml-finality-tracker 0.1.0", "srml-session 0.1.0", "srml-support 0.1.0", @@ -1818,11 +1858,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "substrate-bip39" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/paritytech/substrate-bip39#a28806512c977992af8d6740d45352f5a1c832a0" dependencies = [ "hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1949,19 +1989,21 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "hash-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "impl-serde 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-codec 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 0.1.0", - "substrate-bip39 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)", "tiny-bip39 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2306,6 +2348,11 @@ name = "typenum" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ucd-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "uint" version = "0.6.1" @@ -2353,6 +2400,11 @@ dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "utf8-ranges" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vcpkg" version = "0.2.6" @@ -2425,6 +2477,7 @@ dependencies = [ ] [metadata] +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" @@ -2486,6 +2539,7 @@ dependencies = [ "checksum hash256-std-hasher 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5c13dbac3cc50684760f54af18545c9e80fb75e93a3e586d71ebdc13138f6a4" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hex-literal 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "27455ce8b4a6666c87220e4b59c9a83995476bdadc10197905e61dbe906e36fa" "checksum hex-literal-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1d340b6514f232f6db1bd16db65302a5278a04fef9ce867cb932e7e5fa21130a" "checksum hmac 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a13f4163aa0c5ca1be584aace0e2212b2e41be5478218d4f657f5f778b2ae2a" @@ -2508,6 +2562,7 @@ dependencies = [ "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum memory-db 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94da53143d45f6bad3753f532e56ad57a6a26c0ca6881794583310c7cb4c885f" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" @@ -2561,13 +2616,15 @@ dependencies = [ "checksum rayon-core 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b055d1e92aba6877574d8fe604a63c8b5df60f60e5982bf7ccbb1338ea527356" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" "checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f7bf422d23a88c16d5090d455f182bc99c60af4df6a345c63428acf5129e347" -"checksum schnorrkel 0.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe554f318830b48e5da8ab1ccb1ffd02b79228364dac7766b7cd1ec461ca5116" +"checksum schnorrkel 0.0.0 (git+https://github.com/w3f/schnorrkel)" = "" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" @@ -2587,7 +2644,7 @@ dependencies = [ "checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum substrate-bip39 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec6183ce9e04bec5f113ff19c8ef5355dad20a4196134b5402732bf5d3c1a351" +"checksum substrate-bip39 0.2.0 (git+https://github.com/paritytech/substrate-bip39)" = "" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" "checksum subtle 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "702662512f3ddeb74a64ce2fbbf3707ee1b6bb663d28bb054e0779bbc720d926" "checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec" @@ -2615,12 +2672,14 @@ dependencies = [ "checksum trie-root 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3c6fef2705af3258ec46a7e22286090394a44216201a1cf7d04b78db825e543" "checksum twox-hash 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "555cd4909480122bbbf21e34faac4cb08a171f324775670447ed116726c474af" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum uint 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7780bb27fd8a22295e0d9d53ae3be253f715a0dccb1808527f478f1c2603708" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum wasmi 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21ef487a11df1ed468cf613c78798c26282da5c30e9d49f824872d4c77b47d1d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm b/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm index 2192c80bc519e..29139d149965f 100644 Binary files a/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm and b/node/runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm differ diff --git a/srml/consensus/src/lib.rs b/srml/consensus/src/lib.rs index 32d2a7b141d02..3da15255ae695 100644 --- a/srml/consensus/src/lib.rs +++ b/srml/consensus/src/lib.rs @@ -34,7 +34,7 @@ use inherents::{ }; #[cfg(any(feature = "std", test))] -use substrate_primitives::Ed25519AuthorityId; +use substrate_primitives::ed25519::Public as AuthorityId; mod mock; mod tests; @@ -135,7 +135,7 @@ impl RawLog { // Implementation for tests outside of this crate. #[cfg(any(feature = "std", test))] -impl From> for primitives::testing::DigestItem where N: Into { +impl From> for primitives::testing::DigestItem where N: Into { fn from(log: RawLog) -> primitives::testing::DigestItem { match log { RawLog::AuthoritiesChange(authorities) => diff --git a/srml/contract/src/lib.rs b/srml/contract/src/lib.rs index 8de372ffe894d..3f6cbde88f17a 100644 --- a/srml/contract/src/lib.rs +++ b/srml/contract/src/lib.rs @@ -67,6 +67,7 @@ use crate::account_db::AccountDb; #[cfg(feature = "std")] use serde_derive::{Serialize, Deserialize}; +use substrate_primitives::crypto::UncheckedFrom; use rstd::prelude::*; use rstd::marker::PhantomData; use parity_codec::{Codec, Encode, Decode}; @@ -120,7 +121,7 @@ pub trait Trait: fees::Trait + balances::Trait + timestamp::Trait { pub struct SimpleAddressDeterminator(PhantomData); impl ContractAddressFor, T::AccountId> for SimpleAddressDeterminator where - T::AccountId: From + AsRef<[u8]> + T::AccountId: UncheckedFrom + AsRef<[u8]> { fn contract_address_for(code_hash: &CodeHash, data: &[u8], origin: &T::AccountId) -> T::AccountId { let data_hash = T::Hashing::hash(data); @@ -130,7 +131,7 @@ where buf.extend_from_slice(data_hash.as_ref()); buf.extend_from_slice(origin.as_ref()); - T::Hashing::hash(&buf[..]).into() + UncheckedFrom::unchecked_from(T::Hashing::hash(&buf[..])) } } diff --git a/srml/contract/src/wasm/mod.rs b/srml/contract/src/wasm/mod.rs index c617725c51782..04428280d05bb 100644 --- a/srml/contract/src/wasm/mod.rs +++ b/srml/contract/src/wasm/mod.rs @@ -580,7 +580,7 @@ mod tests { /// calls `ext_caller`, loads the address from the scratch buffer and /// compares it with the constant 42. - const CODE_CALLER: &'static str = r#" + const CODE_CALLER: &str = r#" (module (import "env" "ext_caller" (func $ext_caller)) (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) @@ -645,7 +645,7 @@ mod tests { /// calls `ext_address`, loads the address from the scratch buffer and /// compares it with the constant 69. - const CODE_ADDRESS: &'static str = r#" + const CODE_ADDRESS: &str = r#" (module (import "env" "ext_address" (func $ext_address)) (import "env" "ext_scratch_size" (func $ext_scratch_size (result i32))) diff --git a/srml/grandpa/Cargo.toml b/srml/grandpa/Cargo.toml index ac4ea857de063..de260b622e51e 100644 --- a/srml/grandpa/Cargo.toml +++ b/srml/grandpa/Cargo.toml @@ -16,6 +16,7 @@ primitives = { package = "sr-primitives", path = "../../core/sr-primitives", def srml-support = { path = "../support", default-features = false } system = { package = "srml-system", path = "../system", default-features = false } session = { package = "srml-session", path = "../session", default-features = false } +consensus = { package = "srml-consensus", path = "../consensus", default-features = false } finality-tracker = { package = "srml-finality-tracker", path = "../finality-tracker", default-features = false } [dev-dependencies] @@ -33,6 +34,7 @@ std = [ "srml-support/std", "primitives/std", "system/std", + "consensus/std", "session/std", "finality-tracker/std", ] diff --git a/srml/grandpa/src/lib.rs b/srml/grandpa/src/lib.rs index 37d2da66c0887..0715ce034ad7b 100644 --- a/srml/grandpa/src/lib.rs +++ b/srml/grandpa/src/lib.rs @@ -40,10 +40,11 @@ use srml_support::{Parameter, decl_event, decl_storage, decl_module}; use srml_support::dispatch::Result; use srml_support::storage::StorageValue; use srml_support::storage::unhashed::StorageVec; -use primitives::traits::{CurrentHeight, Convert}; -use substrate_primitives::Ed25519AuthorityId; +use primitives::traits::CurrentHeight; +use substrate_primitives::ed25519; use system::ensure_signed; use primitives::traits::MaybeSerializeDebug; +use ed25519::Public as AuthorityId; mod mock; mod tests; @@ -100,7 +101,7 @@ impl RawLog { } impl GrandpaChangeSignal for RawLog - where N: Clone, SessionKey: Clone + Into, + where N: Clone, SessionKey: Clone + Into, { fn as_signal(&self) -> Option> { RawLog::as_signal(self).map(|(delay, next_authorities)| ScheduledChange { @@ -309,7 +310,7 @@ impl Module { } } -impl Module where Ed25519AuthorityId: core::convert::From<::SessionKey> { +impl Module where AuthorityId: core::convert::From<::SessionKey> { /// See if the digest contains any standard scheduled change. pub fn scrape_digest_change(log: &Log) -> Option> @@ -340,19 +341,14 @@ impl Default for SyncedAuthorities { } impl session::OnSessionChange for SyncedAuthorities where - T: Trait, - T: session::Trait, - ::ConvertAccountIdToSessionKey: Convert< - ::AccountId, - ::SessionKey, - >, + T: Trait + consensus::Trait::SessionKey>, + ::Log: From::SessionKey>> { fn on_session_change(_: X, _: bool) { use primitives::traits::Zero; - let next_authorities = >::validators() + let next_authorities = >::authorities() .into_iter() - .map(T::ConvertAccountIdToSessionKey::convert) .map(|key| (key, 1)) // evenly-weighted. .collect::::SessionKey, u64)>>(); @@ -365,22 +361,17 @@ impl session::OnSessionChange for SyncedAuthorities where } impl finality_tracker::OnFinalizationStalled for SyncedAuthorities where - T: Trait, - T: session::Trait, + T: Trait + consensus::Trait::SessionKey>, + ::Log: From::SessionKey>>, T: finality_tracker::Trait, - ::ConvertAccountIdToSessionKey: Convert< - ::AccountId, - ::SessionKey, - >, { fn on_stalled(further_wait: T::BlockNumber) { // when we record old authority sets, we can use `finality_tracker::median` // to figure out _who_ failed. until then, we can't meaningfully guard // against `next == last` the way that normal session changes do. - let next_authorities = >::validators() + let next_authorities = >::authorities() .into_iter() - .map(T::ConvertAccountIdToSessionKey::convert) .map(|key| (key, 1)) // evenly-weighted. .collect::::SessionKey, u64)>>(); diff --git a/srml/grandpa/src/tests.rs b/srml/grandpa/src/tests.rs index 433602342f5a3..37902cfb17d8c 100644 --- a/srml/grandpa/src/tests.rs +++ b/srml/grandpa/src/tests.rs @@ -193,5 +193,6 @@ fn dispatch_forced_change() { Grandpa::on_finalise(11); header = System::finalise(); } + let _ = header; }); } diff --git a/srml/session/src/lib.rs b/srml/session/src/lib.rs index 8530e5bed656d..47fb0fca41734 100644 --- a/srml/session/src/lib.rs +++ b/srml/session/src/lib.rs @@ -51,7 +51,7 @@ macro_rules! impl_session_change { for_each_tuple!(impl_session_change); pub trait Trait: timestamp::Trait + consensus::Trait { - type ConvertAccountIdToSessionKey: Convert; + type ConvertAccountIdToSessionKey: Convert>; type OnSessionChange: OnSessionChange; type Event: From> + Into<::Event>; } @@ -184,16 +184,17 @@ impl Module { >::put(block_number); } - T::OnSessionChange::on_session_change(time_elapsed, apply_rewards); - // Update any changes in session keys. for (i, v) in Self::validators().into_iter().enumerate() { >::set_authority( i as u32, &>::get(&v) - .unwrap_or_else(|| T::ConvertAccountIdToSessionKey::convert(v)) + .or_else(|| T::ConvertAccountIdToSessionKey::convert(v)) + .unwrap_or_default() ); }; + + T::OnSessionChange::on_session_change(time_elapsed, apply_rewards); } /// Get the time that should have elapsed over a session if everything was working perfectly. diff --git a/subkey/Cargo.toml b/subkey/Cargo.toml index c5006c891684f..d6f8cdd88cdb1 100644 --- a/subkey/Cargo.toml +++ b/subkey/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "subkey" -version = "0.1.0" +version = "0.2.0" authors = ["Parity Technologies "] edition = "2018" @@ -12,6 +12,7 @@ tiny-bip39 = "0.6.0" rustc-hex = "2.0" substrate-bip39 = { git = "https://github.com/paritytech/substrate-bip39" } schnorrkel = { git = "https://github.com/w3f/schnorrkel" } +hex = "0.3" [features] bench = [] diff --git a/subkey/src/cli.yml b/subkey/src/cli.yml index a9182886167d7..cc131703eb8df 100644 --- a/subkey/src/cli.yml +++ b/subkey/src/cli.yml @@ -1,12 +1,7 @@ name: subkey author: "Parity Team " -about: A substrate key utility +about: Utility for generating and restoring with Substrate keys args: - - ed25519-legacy: - short: o - long: legacy - help: Use legacy, outdated Ed25519 cryptography - takes_value: false - ed25519: short: e long: ed25519 @@ -26,15 +21,41 @@ args: subcommands: - generate: about: Generate a random account - - restore: - about: Gets a public key and a SS58 address from the provided seed phrase + - inspect: + about: Gets a public key and a SS58 address from the provided Secret URI + args: + - uri: + index: 1 + required: true + help: A Key URI to be inspected. May be a secret seed, secret URI (with derivation paths and password), SS58 or public URI. + - sign: + about: Sign a message, provided on STDIN, with a given (secret) key + args: + - suri: + index: 1 + required: true + help: The secret key URI. + - hex: + short: h + long: hex + help: The message on STDIN is hex-encoded data + takes_value: false + - verify: + about: Verify a signature for a message, provided on STDIN, with a given (public or secret) key args: - - seed: + - sig: index: 1 required: true - help: 32 bytes long seed phrase used to restore the public key. If the provided seed is shorter than that, then - it will be right-padded with 0x20 bytes (ASCII space). If the provided seed is longer than - 32 bytes then seed will be truncated. + help: Signature, hex-encoded. + - uri: + index: 2 + required: true + help: The public or secret key URI. + - hex: + short: h + long: hex + help: The message on STDIN is hex-encoded data + takes_value: false - vanity: about: Generate a seed that provides a vanity address args: @@ -47,9 +68,3 @@ subcommands: help: Number of keys to generate takes_value: true default_value: "1" - - query: - about: Query an account by its seed - args: - - seed: - index: 1 - help: The 0x prefixed seed diff --git a/subkey/src/main.rs b/subkey/src/main.rs index 7cc28d857c65d..5caf58d45ba14 100644 --- a/subkey/src/main.rs +++ b/subkey/src/main.rs @@ -21,30 +21,35 @@ extern crate test; extern crate substrate_bip39; extern crate rustc_hex; +use std::io::{stdin, Read}; use clap::load_yaml; use rand::{RngCore, rngs::OsRng}; -use substrate_bip39::{mini_secret_from_entropy}; +use substrate_bip39::mini_secret_from_entropy; use bip39::{Mnemonic, Language, MnemonicType}; -use substrate_primitives::{ed25519, sr25519, hexdisplay::HexDisplay}; +use substrate_primitives::{ed25519, sr25519, hexdisplay::HexDisplay, Pair, crypto::Ss58Codec}; use schnorrkel::keys::MiniSecretKey; -use rustc_hex::FromHex; mod vanity; trait Crypto { type Seed: AsRef<[u8]> + AsMut<[u8]> + Sized + Default; - type Pair; + type Pair: Pair; fn generate_phrase() -> String { Mnemonic::new(MnemonicType::Words12, Language::English).phrase().to_owned() } - fn generate_seed() -> Self::Seed; + fn generate_seed() -> Self::Seed { + let mut seed: Self::Seed = Default::default(); + OsRng::new().unwrap().fill_bytes(seed.as_mut()); + seed + } fn seed_from_phrase(phrase: &str, password: Option<&str>) -> Self::Seed; fn pair_from_seed(seed: &Self::Seed) -> Self::Pair; - fn pair_from_phrase(phrase: &str, password: Option<&str>) -> Self::Pair { + fn pair_from_suri(phrase: &str, password: Option<&str>) -> Self::Pair { Self::pair_from_seed(&Self::seed_from_phrase(phrase, password)) } fn ss58_from_pair(pair: &Self::Pair) -> String; fn public_from_pair(pair: &Self::Pair) -> Vec; + fn seed_from_pair(_pair: &Self::Pair) -> Option<&Self::Seed> { None } fn print_from_seed(seed: &Self::Seed) { let pair = Self::pair_from_seed(seed); println!("Seed 0x{} is account:\n Public key (hex): 0x{}\n Address (SS58): {}", @@ -63,43 +68,43 @@ trait Crypto { Self::ss58_from_pair(&pair) ); } + fn print_from_uri(uri: &str, password: Option<&str>) where ::Public: Sized + Ss58Codec + AsRef<[u8]> { + if let Ok(pair) = Self::Pair::from_string(uri, password) { + let seed_text = Self::seed_from_pair(&pair) + .map_or_else(Default::default, |s| format!("\n Seed: 0x{}", HexDisplay::from(&s.as_ref()))); + println!("Secret Key URI `{}` is account:{}\n Public key (hex): 0x{}\n Address (SS58): {}", + uri, + seed_text, + HexDisplay::from(&Self::public_from_pair(&pair)), + Self::ss58_from_pair(&pair) + ); + } + if let Ok(public) = ::Public::from_string(uri) { + println!("Public Key URI `{}` is account:\n Public key (hex): 0x{}\n Address (SS58): {}", + uri, + HexDisplay::from(&public.as_ref()), + public.to_ss58check() + ); + } + } } -struct OriginalEd25519; +struct Ed25519; -impl Crypto for OriginalEd25519 { +impl Crypto for Ed25519 { type Seed = [u8; 32]; type Pair = ed25519::Pair; - fn generate_seed() -> Self::Seed { - let mut seed = [0u8; 32]; - OsRng::new().unwrap().fill_bytes(&mut seed[..]); - seed - } - fn seed_from_phrase(phrase: &str, password: Option<&str>) -> Self::Seed { - if password.is_some() { - panic!("Ed25519 original doesn't support passwords") - } - - let mut raw_seed = phrase.as_bytes(); - - if raw_seed.len() > 32 { - raw_seed = &raw_seed[..32]; - println!("seed is too long and will be truncated to: {}", HexDisplay::from(&raw_seed)); - } - - // Copy the raw_seed into a buffer that already contains ' ' 0x20. - // This will effectively get us padding for seeds shorter than 32. - let mut seed = [' ' as u8; 32]; - let len = raw_seed.len().min(32); - seed[..len].copy_from_slice(&raw_seed[..len]); - seed + Sr25519::seed_from_phrase(phrase, password) } - - fn pair_from_seed(seed: &Self::Seed) -> Self::Pair { ed25519::Pair::from_seed(seed) } + fn pair_from_suri(suri: &str, password_override: Option<&str>) -> Self::Pair { + ed25519::Pair::from_legacy_string(suri, password_override) + } + fn pair_from_seed(seed: &Self::Seed) -> Self::Pair { ed25519::Pair::from_seed(seed.clone()) } fn ss58_from_pair(pair: &Self::Pair) -> String { pair.public().to_ss58check() } fn public_from_pair(pair: &Self::Pair) -> Vec { (&pair.public().0[..]).to_owned() } + fn seed_from_pair(pair: &Self::Pair) -> Option<&Self::Seed> { Some(pair.seed()) } } struct Sr25519; @@ -108,12 +113,6 @@ impl Crypto for Sr25519 { type Seed = [u8; 32]; type Pair = sr25519::Pair; - fn generate_seed() -> Self::Seed { - let mut seed = [0u8; 32]; - OsRng::new().unwrap().fill_bytes(&mut seed[..]); - seed - } - fn seed_from_phrase(phrase: &str, password: Option<&str>) -> Self::Seed { mini_secret_from_entropy( Mnemonic::from_phrase(phrase, Language::English) @@ -127,11 +126,8 @@ impl Crypto for Sr25519 { .to_bytes() } - fn pair_from_phrase(phrase: &str, password: Option<&str>) -> Self::Pair { - sr25519::Pair::from_phrase(phrase, password) - .unwrap_or_else(|| - panic!("Phrase is not a valid BIP-39 phrase: \n {}", phrase) - ) + fn pair_from_suri(suri: &str, password: Option<&str>) -> Self::Pair { + sr25519::Pair::from_string(suri, password).expect("Invalid phrase") } fn pair_from_seed(seed: &Self::Seed) -> Self::Pair { @@ -143,7 +139,10 @@ impl Crypto for Sr25519 { fn public_from_pair(pair: &Self::Pair) -> Vec { (&pair.public().0[..]).to_owned() } } -fn execute>(matches: clap::ArgMatches) { +fn execute>(matches: clap::ArgMatches) where + <::Pair as Pair>::Signature: AsRef<[u8]> + AsMut<[u8]> + Default, + <::Pair as Pair>::Public: Sized + AsRef<[u8]> + Ss58Codec + AsRef<<::Pair as Pair>::Public>, +{ let password = matches.value_of("password"); match matches.subcommand() { ("generate", Some(_matches)) => { @@ -156,38 +155,61 @@ fn execute>(matches: clap::ArgMatches) { let key = vanity::generate_key::(&desired).expect("Key generation failed"); C::print_from_seed(&key.seed); } - ("restore", Some(matches)) => { - let phrase = matches.value_of("seed") - .expect("seed parameter is required; thus it can't be None; qed"); - C::print_from_phrase(phrase, password); + ("inspect", Some(matches)) => { + // TODO: Accept public key with derivation path. + let uri = matches.value_of("uri") + .expect("URI parameter is required; thus it can't be None; qed"); + C::print_from_uri(uri, password); }, - ("query", Some(matches)) => { - let seed_data = matches.value_of("seed") - .expect("seed parameter is required; thus it can't be None; qed"); - let seed_data = if seed_data.starts_with("0x") { - &seed_data[2..] + ("sign", Some(matches)) => { + let suri = matches.value_of("suri") + .expect("secret URI parameter is required; thus it can't be None; qed"); + let pair = C::pair_from_suri(suri, password); + let mut message = vec![]; + stdin().lock().read_to_end(&mut message).expect("Error reading from stdin"); + if matches.is_present("hex") { + message = hex::decode(&message).expect("Invalid hex in message"); + } + let sig = pair.sign(&message); + println!("{}", hex::encode(&sig)); + } + ("verify", Some(matches)) => { + let sig_data = matches.value_of("sig") + .expect("signature parameter is required; thus it can't be None; qed"); + let mut sig = <::Pair as Pair>::Signature::default(); + let sig_data = hex::decode(sig_data).expect("signature is invalid hex"); + if sig_data.len() != sig.as_ref().len() { + panic!("signature is an invalid length. {} bytes is not the expected value of {} bytes", sig_data.len(), sig.as_ref().len()); + } + sig.as_mut().copy_from_slice(&sig_data); + let uri = matches.value_of("uri") + .expect("public uri parameter is required; thus it can't be None; qed"); + let pubkey = <::Pair as Pair>::Public::from_string(uri).ok().or_else(|| + ::Pair::from_string(uri, password).ok().map(|p| p.public()) + ).expect("Invalid URI; expecting either a secret URI or a public URI."); + let mut message = vec![]; + stdin().lock().read_to_end(&mut message).expect("Error reading from stdin"); + if matches.is_present("hex") { + message = hex::decode(&message).expect("Invalid hex in message"); + } + if <::Pair as Pair>::verify(&sig, &message, &pubkey) { + println!("Signature verifies correctly.") } else { - seed_data - }; - let seed_data: Vec = seed_data.from_hex().expect("seed is not valid hex"); - let correct_size = ::std::mem::size_of::(); - if seed_data.len() != correct_size { - panic!("Seed is incorrect size. It must be {} bytes for this cryptography", correct_size); + println!("Signature invalid.") } - let mut seed = C::Seed::default(); - seed.as_mut().copy_from_slice(&seed_data); - C::print_from_seed(&seed); - }, + } _ => print_usage(&matches), } } fn main() { let yaml = load_yaml!("cli.yml"); - let matches = clap::App::from_yaml(yaml).get_matches(); + let matches = clap::App::from_yaml(yaml) + .version(env!("CARGO_PKG_VERSION")) + .get_matches(); - if matches.is_present("ed25519original") { - execute::(matches) + if matches.is_present("ed25519") { + execute::(matches) } else { execute::(matches) } diff --git a/subkey/src/vanity.rs b/subkey/src/vanity.rs index 07486cff4b851..785eb95aa5b20 100644 --- a/subkey/src/vanity.rs +++ b/subkey/src/vanity.rs @@ -104,13 +104,14 @@ pub(super) fn generate_key>(desired: &str) -> Result("j").unwrap().pair.public().to_ss58check().contains("j")); + assert!(generate_key::("j").unwrap().pair.public().to_ss58check().contains("j")); } #[test]