From 5a61b67d245cd2ad1db43442b679213378446d38 Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 28 May 2018 15:03:23 +0200 Subject: [PATCH 1/9] RPCs for versioning. --- Cargo.lock | 4 +-- polkadot/cli/Cargo.toml | 2 +- polkadot/cli/src/lib.rs | 20 +++++++++++-- polkadot/service/src/config.rs | 19 +++++++++++++ substrate/rpc-servers/src/lib.rs | 5 +++- substrate/rpc/src/lib.rs | 1 + substrate/rpc/src/system/error.rs | 47 +++++++++++++++++++++++++++++++ substrate/rpc/src/system/mod.rs | 37 ++++++++++++++++++++++++ substrate/rpc/src/system/tests.rs | 43 ++++++++++++++++++++++++++++ 9 files changed, 172 insertions(+), 6 deletions(-) create mode 100644 substrate/rpc/src/system/error.rs create mode 100644 substrate/rpc/src/system/mod.rs create mode 100644 substrate/rpc/src/system/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 976b1ea5ee5d2..4e7372118de1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1218,7 +1218,7 @@ name = "polkadot" version = "0.1.0" dependencies = [ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "polkadot-cli 0.1.0", + "polkadot-cli 0.2.0", ] [[package]] @@ -1242,7 +1242,7 @@ dependencies = [ [[package]] name = "polkadot-cli" -version = "0.1.0" +version = "0.2.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/polkadot/cli/Cargo.toml b/polkadot/cli/Cargo.toml index 5ec179b273493..f80b3b1d9fc18 100644 --- a/polkadot/cli/Cargo.toml +++ b/polkadot/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "polkadot-cli" -version = "0.1.0" +version = "0.2.0" authors = ["Parity Technologies "] description = "Polkadot node implementation in Rust." diff --git a/polkadot/cli/src/lib.rs b/polkadot/cli/src/lib.rs index 604c665910230..79c9b1cdce46e 100644 --- a/polkadot/cli/src/lib.rs +++ b/polkadot/cli/src/lib.rs @@ -95,6 +95,22 @@ impl substrate_rpc::author::AuthorApi for RpcTransactionPool { } } +struct Configuration(service::Configuration); + +impl substrate_rpc::system::SystemApi for Configuration { + fn system_version(&self) -> substrate_rpc::system::error::Result { + Ok(crate_version!().into()) + } + + fn system_chain(&self) -> substrate_rpc::system::error::Result { + Ok(match self.0.chain_spec { + ChainSpec::Development => "dev", + ChainSpec::LocalTestnet => "local", + ChainSpec::PoC1Testnet => "poc-1", + }.into()) + } +} + /// Parse command line arguments and start the node. /// /// IANA unassigned port ranges that we could use: @@ -195,7 +211,7 @@ pub fn run(args: I) -> error::Result<()> where config.keys = matches.values_of("key").unwrap_or_default().map(str::to_owned).collect(); - let service = service::Service::new(config)?; + let service = service::Service::new(config.clone())?; informant::start(&service, core.handle()); @@ -209,7 +225,7 @@ pub fn run(args: I) -> error::Result<()> where inner: service.transaction_pool(), network: service.network(), }; - rpc::rpc_handler(service.client(), chain, pool) + rpc::rpc_handler(service.client(), chain, pool, Configuration(config.clone())) }; ( start_server(http_address, |address| rpc::start_http(address, handler())), diff --git a/polkadot/service/src/config.rs b/polkadot/service/src/config.rs index 177675ea704a0..16b39631b9d9a 100644 --- a/polkadot/service/src/config.rs +++ b/polkadot/service/src/config.rs @@ -22,6 +22,7 @@ pub use network::NetworkConfiguration; /// The chain specification (this should eventually be replaced by a more general JSON-based chain /// specification). +#[derive(Clone)] pub enum ChainSpec { /// Whatever the current runtime is, with just Alice as an auth. Development, @@ -62,3 +63,21 @@ impl Default for Configuration { } } } + +impl Clone for Configuration { + fn clone(&self) -> Configuration { + Configuration { + roles: self.roles.clone(), + transaction_pool: transaction_pool::Options { + max_count: self.transaction_pool.max_count.clone(), + max_mem_usage: self.transaction_pool.max_mem_usage.clone(), + max_per_sender: self.transaction_pool.max_per_sender.clone(), + }, + network: self.network.clone(), + keystore_path: self.keystore_path.clone(), + database_path: self.database_path.clone(), + keys: self.keys.clone(), + chain_spec: self.chain_spec.clone(), + } + } +} diff --git a/substrate/rpc-servers/src/lib.rs b/substrate/rpc-servers/src/lib.rs index 0d0157553ec44..05e4cd70fd9ba 100644 --- a/substrate/rpc-servers/src/lib.rs +++ b/substrate/rpc-servers/src/lib.rs @@ -34,19 +34,22 @@ type Metadata = apis::metadata::Metadata; type RpcHandler = pubsub::PubSubHandler; /// Construct rpc `IoHandler` -pub fn rpc_handler( +pub fn rpc_handler( state: S, chain: C, author: A, + system: Y, ) -> RpcHandler where S: apis::state::StateApi, C: apis::chain::ChainApi, A: apis::author::AuthorApi, + Y: apis::system::SystemApi, { let mut io = pubsub::PubSubHandler::default(); io.extend_with(state.to_delegate()); io.extend_with(chain.to_delegate()); io.extend_with(author.to_delegate()); + io.extend_with(system.to_delegate()); io } diff --git a/substrate/rpc/src/lib.rs b/substrate/rpc/src/lib.rs index 54f8739e33f2e..59f278b3a787c 100644 --- a/substrate/rpc/src/lib.rs +++ b/substrate/rpc/src/lib.rs @@ -45,3 +45,4 @@ pub mod author; pub mod chain; pub mod metadata; pub mod state; +pub mod system; diff --git a/substrate/rpc/src/system/error.rs b/substrate/rpc/src/system/error.rs new file mode 100644 index 0000000000000..e3dadc328762b --- /dev/null +++ b/substrate/rpc/src/system/error.rs @@ -0,0 +1,47 @@ +// Copyright 2017 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 . + +//! System RPC module errors. + +use rpc; + +error_chain! { + errors { + /// Not implemented yet + Unimplemented { + description("not yet implemented"), + display("Method Not Implemented"), + } + /// Invalid format + InvalidFormat { + description("invalid format"), + display("Invalid format for the extrinsic data"), + } + } +} + +impl From for rpc::Error { + fn from(e: Error) -> Self { + match e { + Error(ErrorKind::Unimplemented, _) => rpc::Error { + code: rpc::ErrorCode::ServerError(-1), + message: "Not implemented yet".into(), + data: None, + }, + _ => rpc::Error::internal_error(), + } + } +} diff --git a/substrate/rpc/src/system/mod.rs b/substrate/rpc/src/system/mod.rs new file mode 100644 index 0000000000000..5dd72cf228127 --- /dev/null +++ b/substrate/rpc/src/system/mod.rs @@ -0,0 +1,37 @@ +// Copyright 2017 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 . + +//! Substrate system API. + +pub mod error; + +#[cfg(test)] +mod tests; + +use self::error::Result; + +build_rpc_trait! { + /// Substrate system RPC API + pub trait SystemApi { + /// Get the system's version. Given as a semver string. + #[rpc(name = "system_version")] + fn system_version(&self) -> Result; + + /// Get the chain's type. Given as a semver string. + #[rpc(name = "system_chain")] + fn system_chain(&self) -> Result; + } +} diff --git a/substrate/rpc/src/system/tests.rs b/substrate/rpc/src/system/tests.rs new file mode 100644 index 0000000000000..cd5510a2d678a --- /dev/null +++ b/substrate/rpc/src/system/tests.rs @@ -0,0 +1,43 @@ +// Copyright 2017 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 . + +use super::*; +use super::error::*; + +impl SystemApi for () { + fn system_version(&self) -> Result { + Ok("0.2.0".into()) + } + fn system_chain(&self) -> Result { + Ok("test".into()) + } +} + +#[test] +fn system_version_works() { + assert_matches!( + AuthorApi::system_version(&()), + Ok("0.2.0".to_owned()) + ); +} + +#[test] +fn system_chain_works() { + assert_matches!( + AuthorApi::system_chain(&()), + Ok("test".to_owned()) + ); +} From d580278eff7b166f485cb10d320e60dd846e5db8 Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 28 May 2018 16:18:36 +0200 Subject: [PATCH 2/9] Build fix for bad merge. --- polkadot/cli/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/polkadot/cli/src/lib.rs b/polkadot/cli/src/lib.rs index 9292f90736af5..7c6025061776e 100644 --- a/polkadot/cli/src/lib.rs +++ b/polkadot/cli/src/lib.rs @@ -205,12 +205,12 @@ pub fn run(args: I) -> error::Result<()> where config.keys = matches.values_of("key").unwrap_or_default().map(str::to_owned).collect(); match role == service::Role::LIGHT { - true => run_until_exit(core, service::new_light(config.clone())?, &matches), - false => run_until_exit(core, service::new_full(config.clone())?, &matches), + true => run_until_exit(core, service::new_light(config.clone())?, &matches, config), + false => run_until_exit(core, service::new_full(config.clone())?, &matches, config), } } -fn run_until_exit(mut core: reactor::Core, service: service::Service, matches: &clap::ArgMatches) -> error::Result<()> +fn run_until_exit(mut core: reactor::Core, service: service::Service, matches: &clap::ArgMatches, config: service::Configuration) -> error::Result<()> where B: client::backend::Backend + Send + Sync + 'static, E: client::CallExecutor + Send + Sync + 'static, From e1ab201b788b60845363feee7c2398bbfea8bb3b Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 28 May 2018 16:22:22 +0200 Subject: [PATCH 3/9] Add system_name RPC --- polkadot/cli/src/lib.rs | 4 ++++ substrate/rpc/src/system/mod.rs | 8 ++++++-- substrate/rpc/src/system/tests.rs | 15 +++++++++++++-- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/polkadot/cli/src/lib.rs b/polkadot/cli/src/lib.rs index 7c6025061776e..d26ebf75568fc 100644 --- a/polkadot/cli/src/lib.rs +++ b/polkadot/cli/src/lib.rs @@ -98,6 +98,10 @@ impl substrate_rpc::author::AuthorApi for RpcTransactionPool { struct Configuration(service::Configuration); impl substrate_rpc::system::SystemApi for Configuration { + fn system_name(&self) -> substrate_rpc::system::error::Result { + Ok("parity-polkadot".into()) + } + fn system_version(&self) -> substrate_rpc::system::error::Result { Ok(crate_version!().into()) } diff --git a/substrate/rpc/src/system/mod.rs b/substrate/rpc/src/system/mod.rs index 5dd72cf228127..56d06be9e5cda 100644 --- a/substrate/rpc/src/system/mod.rs +++ b/substrate/rpc/src/system/mod.rs @@ -26,11 +26,15 @@ use self::error::Result; build_rpc_trait! { /// Substrate system RPC API pub trait SystemApi { - /// Get the system's version. Given as a semver string. + /// Get the node's implementation name. Plain old string. + #[rpc(name = "system_name")] + fn system_name(&self) -> Result; + + /// Get the node implementation's version. Should be a semver string. #[rpc(name = "system_version")] fn system_version(&self) -> Result; - /// Get the chain's type. Given as a semver string. + /// Get the chain's type. Given as a string identifier. #[rpc(name = "system_chain")] fn system_chain(&self) -> Result; } diff --git a/substrate/rpc/src/system/tests.rs b/substrate/rpc/src/system/tests.rs index cd5510a2d678a..6c9478cdf5546 100644 --- a/substrate/rpc/src/system/tests.rs +++ b/substrate/rpc/src/system/tests.rs @@ -18,14 +18,25 @@ use super::*; use super::error::*; impl SystemApi for () { + fn system_name(&self) -> Result { + Ok("testclient".into()) + } fn system_version(&self) -> Result { Ok("0.2.0".into()) } fn system_chain(&self) -> Result { - Ok("test".into()) + Ok("testchain".into()) } } +#[test] +fn system_name_works() { + assert_matches!( + AuthorApi::system_name(&()), + Ok("testclient".to_owned()) + ); +} + #[test] fn system_version_works() { assert_matches!( @@ -38,6 +49,6 @@ fn system_version_works() { fn system_chain_works() { assert_matches!( AuthorApi::system_chain(&()), - Ok("test".to_owned()) + Ok("testchain".to_owned()) ); } From 471e6d049ba50fdef5942ec8cc3c937faec8318d Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 28 May 2018 16:33:55 +0200 Subject: [PATCH 4/9] Fix tests. --- substrate/rpc/src/system/tests.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/substrate/rpc/src/system/tests.rs b/substrate/rpc/src/system/tests.rs index 6c9478cdf5546..f22cd5a157779 100644 --- a/substrate/rpc/src/system/tests.rs +++ b/substrate/rpc/src/system/tests.rs @@ -31,24 +31,24 @@ impl SystemApi for () { #[test] fn system_name_works() { - assert_matches!( - AuthorApi::system_name(&()), - Ok("testclient".to_owned()) + assert_eq!( + SystemApi::system_name(&()).unwrap(), + "testclient".to_owned() ); } #[test] fn system_version_works() { - assert_matches!( - AuthorApi::system_version(&()), - Ok("0.2.0".to_owned()) + assert_eq!( + SystemApi::system_version(&()).unwrap(), + "0.2.0".to_owned() ); } #[test] fn system_chain_works() { - assert_matches!( - AuthorApi::system_chain(&()), - Ok("testchain".to_owned()) + assert_eq!( + SystemApi::system_chain(&()).unwrap(), + "testchain".to_owned() ); } From 708c08abebfe36294abb0be16f1ff1d228520b28 Mon Sep 17 00:00:00 2001 From: Gav Date: Mon, 28 May 2018 17:13:50 +0200 Subject: [PATCH 5/9] Fix demo build. --- demo/cli/src/lib.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/demo/cli/src/lib.rs b/demo/cli/src/lib.rs index 306f26e8885c5..6a2730280db63 100644 --- a/demo/cli/src/lib.rs +++ b/demo/cli/src/lib.rs @@ -61,6 +61,19 @@ impl substrate_rpc::author::AuthorApi for DummyPool { } } +struct DummySystem; +impl substrate_rpc::system::SystemApi for DummySystem { + fn system_name(&self) -> substrate_rpc::system::error::Result { + Ok("substrate-demo".into()) + } + fn system_version(&self) -> substrate_rpc::system::error::Result { + Ok(crate_version!().into()) + } + fn system_chain(&self) -> substrate_rpc::system::error::Result { + Ok("default".into()) + } +} + /// Parse command line arguments and start the node. /// /// IANA unassigned port ranges that we could use: @@ -142,7 +155,7 @@ pub fn run(args: I) -> error::Result<()> where let _rpc_servers = { let handler = || { let chain = rpc::apis::chain::Chain::new(client.clone(), core.remote()); - rpc::rpc_handler(client.clone(), chain, DummyPool) + rpc::rpc_handler(client.clone(), chain, DummyPool, DummySystem) }; let http_address = "127.0.0.1:9933".parse().unwrap(); let ws_address = "127.0.0.1:9944".parse().unwrap(); From d1fb5a7f393d5a7a433324849b760a3dce0b50d3 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 29 May 2018 10:23:13 +0200 Subject: [PATCH 6/9] Remove BadFormat. --- substrate/rpc/src/system/error.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/substrate/rpc/src/system/error.rs b/substrate/rpc/src/system/error.rs index e3dadc328762b..2fe155f23e3fe 100644 --- a/substrate/rpc/src/system/error.rs +++ b/substrate/rpc/src/system/error.rs @@ -25,11 +25,6 @@ error_chain! { description("not yet implemented"), display("Method Not Implemented"), } - /// Invalid format - InvalidFormat { - description("invalid format"), - display("Invalid format for the extrinsic data"), - } } } From 61c245c28635ad9f0c6fe49ea6d5e79790970190 Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 29 May 2018 10:23:47 +0200 Subject: [PATCH 7/9] Add ss58check encoding and subkey. --- Cargo.lock | 16 +++++++++++ Cargo.toml | 1 + subkey/Cargo.toml | 8 ++++++ subkey/src/main.rs | 46 ++++++++++++++++++++++++++++++ substrate/ed25519/Cargo.toml | 2 ++ substrate/ed25519/src/lib.rs | 55 ++++++++++++++++++++++++++++++++++++ 6 files changed, 128 insertions(+) create mode 100644 subkey/Cargo.toml create mode 100644 subkey/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 9fafbf6f49cec..514469df42f58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,11 @@ dependencies = [ "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base58" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "base64" version = "0.9.0" @@ -310,6 +315,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "ed25519" version = "0.1.0" dependencies = [ + "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", "hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "substrate-primitives 0.1.0", @@ -1839,6 +1846,14 @@ name = "strsim" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "subkey" +version = "0.1.0" +dependencies = [ + "ed25519 0.1.0", + "substrate-primitives 0.1.0", +] + [[package]] name = "substrate-bft" version = "0.1.0" @@ -2706,6 +2721,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859" "checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" +"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" "checksum base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229d032f1a99302697f10b27167ae6d03d49d032e6a8e2550e8d3fc13356d2b4" "checksum bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5442186ef6560f30f1ee4b9c1e4c87a35a6879d3644550cc248ec2b955eb5fcd" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" diff --git a/Cargo.toml b/Cargo.toml index ea3dc865ab2e4..61f26c765753c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,7 @@ members = [ "demo/executor", "demo/cli", "safe-mix", + "subkey", ] exclude = [ "polkadot/runtime/wasm", diff --git a/subkey/Cargo.toml b/subkey/Cargo.toml new file mode 100644 index 0000000000000..9ca82bec54d40 --- /dev/null +++ b/subkey/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "subkey" +version = "0.1.0" +authors = ["Gav "] + +[dependencies] +ed25519 = { version = "*", path = "../substrate/ed25519" } +substrate-primitives = { version = "*", path = "../substrate/primitives" } diff --git a/subkey/src/main.rs b/subkey/src/main.rs new file mode 100644 index 0000000000000..db2713e3db367 --- /dev/null +++ b/subkey/src/main.rs @@ -0,0 +1,46 @@ +extern crate ed25519; +extern crate substrate_primitives; + +use ed25519::Pair; +use substrate_primitives::hexdisplay::HexDisplay; + +fn good_waypoint(done: u64) -> u64 { + match done { + 0 ... 1_000_000 => 100_000, + 0 ... 10_000_000 => 1_000_000, + 0 ... 100_000_000 => 10_000_000, + _ => 100_000_000, + } +} + +fn main() { + let desired = "GavWood"; + let score = |s: &str| { + for truncate in 0..desired.len() - 1 { + let snip_size = desired.len() - truncate; + let truncated = &desired[0..snip_size]; + if let Some(pos) = s.find(truncated) { + return (32 - pos) + (snip_size << 16); + } + } + 0 + }; + let mut best = 0; + let mut seed = Pair::generate().public().0; + let mut done = 0; + loop { + let p = Pair::from_seed(&seed); + let ss58 = p.public().to_ss58check(); + let s = score(&ss58); + if s > best { + println!("{}: {}", ss58, HexDisplay::from(&seed)); + best = s; + } + seed = p.public().0; + done += 1; + + if done % good_waypoint(done) == 0 { + println!("{} keys searched", done); + } + } +} diff --git a/substrate/ed25519/Cargo.toml b/substrate/ed25519/Cargo.toml index 1241bd69bf15d..34494fc8be9b0 100644 --- a/substrate/ed25519/Cargo.toml +++ b/substrate/ed25519/Cargo.toml @@ -8,3 +8,5 @@ ring = "0.12" untrusted = "0.5" substrate-primitives = { version = "0.1", path = "../primitives" } hex-literal = "0.1" +base58 = "0.1" +blake2-rfc = "0.2" diff --git a/substrate/ed25519/src/lib.rs b/substrate/ed25519/src/lib.rs index 390caa46c46a0..f659ad5405b9d 100644 --- a/substrate/ed25519/src/lib.rs +++ b/substrate/ed25519/src/lib.rs @@ -17,11 +17,14 @@ //! Simple Ed25519 API. extern crate ring; +extern crate base58; extern crate substrate_primitives as primitives; extern crate untrusted; +extern crate blake2_rfc; use ring::{rand, signature}; use primitives::hash::H512; +use base58::{ToBase58, FromBase58}; #[cfg(test)] #[macro_use] @@ -67,6 +70,14 @@ impl ::std::hash::Hash for Public { } } +#[derive(Clone, Copy, Eq, PartialEq, Debug)] +pub enum PublicError { + BadBase58, + BadLength, + UnknownVersion, + InvalidChecksum, +} + impl Public { /// A new instance from the given 32-byte `data`. pub fn from_raw(data: [u8; 32]) -> Self { @@ -80,6 +91,24 @@ impl Public { 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])) + } + /// Return a `Vec` filled with raw data. pub fn to_raw_vec(self) -> Vec { let r: &[u8; 32] = self.as_ref(); @@ -96,6 +125,15 @@ 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() + } } impl AsRef<[u8; 32]> for Public { @@ -281,4 +319,21 @@ mod test { let pair = Pair::generate(); let _pair2 = pair.derive_child_probably_bad(b"session_1234"); } + + #[test] + fn ss58check_roundtrip_works() { + let pair = Pair::from_seed(b"12345678901234567890123456789012"); + let public = pair.public(); + let s = public.to_ss58check(); + println!("Correct: {}", s); + let cmp = Public::from_ss58check(&s).unwrap(); + assert_eq!(cmp, public); + } + + #[test] + fn ss58check_known_works() { + let k = "5CGavy93sZgPPjHyziRohwVumxiHXMGmQLyuqQP4ZFx5vRU9"; + let enc = hex!["090fa15cb5b1666222fff584b4cc2b1761fe1e238346b340491b37e25ea183ff"]; + assert_eq!(Public::from_ss58check(k).unwrap(), Public::from_raw(enc)); + } } From c55ecc9aa71de2d2a6188b3830ce235d740087bc Mon Sep 17 00:00:00 2001 From: Gav Date: Tue, 29 May 2018 10:47:06 +0200 Subject: [PATCH 8/9] Improvements. --- subkey/src/main.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/subkey/src/main.rs b/subkey/src/main.rs index db2713e3db367..dba14ef37f877 100644 --- a/subkey/src/main.rs +++ b/subkey/src/main.rs @@ -1,6 +1,7 @@ extern crate ed25519; extern crate substrate_primitives; +use std::env::args; use ed25519::Pair; use substrate_primitives::hexdisplay::HexDisplay; @@ -14,17 +15,22 @@ fn good_waypoint(done: u64) -> u64 { } fn main() { - let desired = "GavWood"; + if args().len() != 2 { + println!("Usage: subkey "); + return; + } + let desired = args().last().unwrap(); let score = |s: &str| { for truncate in 0..desired.len() - 1 { let snip_size = desired.len() - truncate; let truncated = &desired[0..snip_size]; if let Some(pos) = s.find(truncated) { - return (32 - pos) + (snip_size << 16); + return (31 - pos) + (snip_size * 32); } } 0 }; + let top = 30 + (desired.len() * 32); let mut best = 0; let mut seed = Pair::generate().public().0; let mut done = 0; @@ -33,8 +39,11 @@ fn main() { let ss58 = p.public().to_ss58check(); let s = score(&ss58); if s > best { - println!("{}: {}", ss58, HexDisplay::from(&seed)); + println!("{}: {} ({}% complete)", ss58, HexDisplay::from(&seed), s * 100 / top); best = s; + if best == top { + break; + } } seed = p.public().0; done += 1; From 5911c898b72c364bb9939cdc3af8b998eea83f42 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Tue, 29 May 2018 14:23:05 +0200 Subject: [PATCH 9/9] Update Cargo.toml --- subkey/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subkey/Cargo.toml b/subkey/Cargo.toml index 9ca82bec54d40..942da8bdd6c18 100644 --- a/subkey/Cargo.toml +++ b/subkey/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "subkey" version = "0.1.0" -authors = ["Gav "] +authors = ["Parity Technologies "] [dependencies] ed25519 = { version = "*", path = "../substrate/ed25519" }