diff --git a/Cargo.lock b/Cargo.lock index cb4bcdb20..c9224e7b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2321,12 +2321,15 @@ dependencies = [ "hex-literal", "humanode-rpc", "humanode-runtime", + "indoc", "pallet-bioauth", "parity-scale-codec", "qr2term", "reqwest", "robonode-client", "sc-basic-authorship", + "sc-chain-spec", + "sc-chain-spec-derive", "sc-cli", "sc-client-api", "sc-consensus", @@ -2338,6 +2341,8 @@ dependencies = [ "sc-telemetry 4.0.0-dev", "sc-tracing 4.0.0-dev", "sc-transaction-pool", + "serde", + "serde_json", "sp-application-crypto", "sp-consensus", "sp-consensus-aura", @@ -2632,6 +2637,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "indoc" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a75aeaaef0ce18b58056d306c27b07436fbb34b8816c53094b76dd81803136" +dependencies = [ + "unindent", +] + [[package]] name = "infer" version = "0.2.3" @@ -8595,6 +8609,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "unindent" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" + [[package]] name = "universal-hash" version = "0.4.1" diff --git a/crates/humanode-peer/Cargo.toml b/crates/humanode-peer/Cargo.toml index 69a03f62c..3463629e0 100644 --- a/crates/humanode-peer/Cargo.toml +++ b/crates/humanode-peer/Cargo.toml @@ -27,6 +27,8 @@ hex-literal = "0.3" qr2term = "0.2" reqwest = "0.11" sc-basic-authorship = { git = "https://github.com/humanode-network/substrate", branch = "master" } +sc-chain-spec = { git = "https://github.com/humanode-network/substrate", branch = "master" } +sc-chain-spec-derive = { git = "https://github.com/humanode-network/substrate", branch = "master" } sc-cli = { git = "https://github.com/humanode-network/substrate", branch = "master" } sc-client-api = { git = "https://github.com/humanode-network/substrate", branch = "master" } sc-consensus = { git = "https://github.com/humanode-network/substrate", branch = "master" } @@ -38,6 +40,7 @@ sc-service = { git = "https://github.com/humanode-network/substrate", branch = " sc-telemetry = { git = "https://github.com/humanode-network/substrate", branch = "master" } sc-tracing = { git = "https://github.com/humanode-network/substrate", branch = "master" } sc-transaction-pool = { git = "https://github.com/humanode-network/substrate", branch = "master" } +serde = { version = "1", features = ["derive"] } sp-application-crypto = { git = "https://github.com/humanode-network/substrate", branch = "master" } sp-consensus = { git = "https://github.com/humanode-network/substrate", branch = "master" } sp-consensus-aura = { git = "https://github.com/humanode-network/substrate", branch = "master" } @@ -51,3 +54,7 @@ thiserror = "1" tokio = { version = "1", features = ["full"] } tracing = "0.1" url = "2" + +[dev-dependencies] +indoc = "1.0" +serde_json = "1" diff --git a/crates/humanode-peer/src/chain_spec.rs b/crates/humanode-peer/src/chain_spec.rs index 9b16406b9..84135a2bc 100644 --- a/crates/humanode-peer/src/chain_spec.rs +++ b/crates/humanode-peer/src/chain_spec.rs @@ -6,7 +6,9 @@ use humanode_runtime::{ RobonodePublicKeyWrapper, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use pallet_bioauth::StoredAuthTicket; +use sc_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup}; use sc_service::ChainType; +use serde::{Deserialize, Serialize}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::{ @@ -15,7 +17,20 @@ use sp_runtime::{ }; /// The concrete chain spec type we're using for the humanode network. -pub type ChainSpec = sc_service::GenericChainSpec; +pub type ChainSpec = sc_service::GenericChainSpec; + +/// Extensions for ChainSpec. +#[derive( + Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension, Default, +)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "camelCase")] +pub struct Extensions { + /// The URL of robonode to authenticate with. + pub robonode_url: Option, + /// The Web App URL, necessary for printing the Web App QR Code. + pub webapp_url: Option, +} /// Generate a crypto pair from seed. pub fn get_from_seed(seed: &str) -> ::Public { @@ -97,7 +112,7 @@ pub fn local_testnet_config() -> Result { // Properties None, // Extensions - None, + Extensions::default(), )) } @@ -146,7 +161,7 @@ pub fn development_config() -> Result { // Properties None, // Extensions - None, + Extensions::default(), )) } @@ -193,3 +208,70 @@ fn testnet_genesis( }, } } + +#[cfg(test)] +mod tests { + use indoc::indoc; + + use super::*; + + #[test] + fn deserialize_bioauth_flow_params_extensions() { + let expected = Extensions { + robonode_url: Some("dummy_robonode_url".into()), + webapp_url: Some("dummy_webapp_url".into()), + }; + let value = serde_json::json!({ + "robonodeUrl": "dummy_robonode_url", + "webappUrl": "dummy_webapp_url" + }); + + let sample: Extensions = serde_json::from_value(value).unwrap(); + + assert_eq!(sample, expected) + } + + #[test] + fn deserialize_chain_spec() { + let chain_spec_file_content = indoc! {r#" + { + "name": "Local Testnet", + "id": "local_testnet", + "chainType": "Local", + "bootNodes": [], + "telemetryEndpoints": null, + "protocolId": null, + "properties": null, + "robonodeUrl": "dummy_robonode_url", + "webappUrl": "dummy_webapp_url", + "consensusEngine": null, + "codeSubstitutes": {}, + "genesis": { + "runtime": { + "system": { "changesTrieConfig": null, "code": "0x0" }, + "aura": { + "authorities": [] + }, + "balances": { + "balances": [] + }, + "sudo": { "key": "0" }, + "bioauth": { + "storedAuthTickets": [], + "robonodePublicKey": [] + } + } + } + } + "#}; + let bytes = chain_spec_file_content.as_bytes(); + let sample: ChainSpec = ChainSpec::from_json_bytes(bytes).unwrap(); + + let expected = Extensions { + robonode_url: Some("dummy_robonode_url".into()), + webapp_url: Some("dummy_webapp_url".into()), + }; + + assert_eq!(sample.extensions().to_owned(), expected) + } +} diff --git a/crates/humanode-peer/src/cli/config.rs b/crates/humanode-peer/src/cli/config.rs index ff3629c0b..e932391a3 100644 --- a/crates/humanode-peer/src/cli/config.rs +++ b/crates/humanode-peer/src/cli/config.rs @@ -1,6 +1,11 @@ //! Machinery to populate the configuration from the CLI arguments. -use crate::configuration::{self, Configuration}; +use sc_chain_spec::get_extension; + +use crate::{ + chain_spec::Extensions, + configuration::{self, Configuration}, +}; use super::params; @@ -18,6 +23,10 @@ pub trait CliConfigurationExt: SubstrateCliConfigurationProvider { task_executor, )?; + let extensions = get_extension::(substrate.chain_spec.extensions()) + .cloned() + .unwrap_or_default(); + let bioauth_flow = self.bioauth_params().map(|params| { let rpc_url = params.rpc_url.clone().or_else(|| { substrate @@ -27,8 +36,12 @@ pub trait CliConfigurationExt: SubstrateCliConfigurationProvider { }); configuration::BioauthFlow { - robonode_url: params.robonode_url.clone(), - webapp_url: Some(params.webapp_url.clone()), + robonode_url: params + .robonode_url + .clone() + .or(extensions.robonode_url) + .unwrap_or_else(|| "http://127.0.0.1:3033".into()), + webapp_url: params.webapp_url.clone().or(extensions.webapp_url), rpc_url, } }); diff --git a/crates/humanode-peer/src/cli/params.rs b/crates/humanode-peer/src/cli/params.rs index 6694116e4..346f737d5 100644 --- a/crates/humanode-peer/src/cli/params.rs +++ b/crates/humanode-peer/src/cli/params.rs @@ -7,12 +7,8 @@ use structopt::StructOpt; pub struct BioauthFlowParams { /// The URL to use for the web app. /// Used to print the QR Code to the console, so it doesn't matter much. - #[structopt( - long, - value_name = "WEBAPP_URL", - default_value = "https://webapp-test-1.dev.humanode.io" - )] - pub webapp_url: String, + #[structopt(long, value_name = "WEBAPP_URL")] + pub webapp_url: Option, /// The URL to pass to the web app to connect to the node RPC. /// If not passed, a URL with `localhost` and the HTTP RPC port will be used. @@ -20,11 +16,6 @@ pub struct BioauthFlowParams { pub rpc_url: Option, /// The URL of robonode to authenticate with. - /// It should be a part of the genesis, but it isn't yet (TODO). - #[structopt( - long, - value_name = "ROBONODE_URL", - default_value = "http://127.0.0.1:3033" - )] - pub robonode_url: String, + #[structopt(long, value_name = "ROBONODE_URL")] + pub robonode_url: Option, }