From f3bb19063182d71c2cdc5f773ad088c28f55920f Mon Sep 17 00:00:00 2001 From: 1xstj <106580853+1xstj@users.noreply.github.com> Date: Mon, 8 Jan 2024 17:18:18 +0000 Subject: [PATCH] feat : re-introduce auto-insert-keys flag for babe --- Cargo.lock | 1 + node/Cargo.toml | 1 + node/src/cli.rs | 3 + node/src/command.rs | 1 + node/src/lib.rs | 1 + node/src/main.rs | 2 +- node/src/service.rs | 44 ++++++++++++++- node/src/utils.rs | 134 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 node/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 5e2df0be5..721574092 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14439,6 +14439,7 @@ dependencies = [ "frame-system", "frame-system-rpc-runtime-api", "futures 0.3.30", + "hex", "hex-literal", "jsonrpsee", "log", diff --git a/node/Cargo.toml b/node/Cargo.toml index f959569e9..dc7ad84ab 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -32,6 +32,7 @@ parity-scale-codec = { workspace = true } rand = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true } +hex = {workspace = true } # Substrate dependencies frame-benchmarking = { workspace = true } diff --git a/node/src/cli.rs b/node/src/cli.rs index 73973e0f9..552e0a493 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -31,6 +31,9 @@ pub struct Cli { #[command(flatten)] pub eth: EthConfiguration, + + #[arg(short, long)] + pub auto_insert_keys: bool, } #[derive(Debug, clap::Subcommand)] diff --git a/node/src/command.rs b/node/src/command.rs index 447b7f9b0..97b2a06d0 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -253,6 +253,7 @@ pub fn run() -> sc_cli::Result<()> { rpc_config, eth_config: cli.eth, debug_output: cli.output_path, + auto_insert_keys: cli.auto_insert_keys, }) .map_err(Into::into) .await diff --git a/node/src/lib.rs b/node/src/lib.rs index 01ad1fc66..33c1e48f1 100644 --- a/node/src/lib.rs +++ b/node/src/lib.rs @@ -6,3 +6,4 @@ pub mod mainnet_fixtures; pub mod rpc; pub mod service; pub mod testnet_fixtures; +pub mod utils; diff --git a/node/src/main.rs b/node/src/main.rs index fb1b1d978..4e8530ced 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -13,7 +13,7 @@ mod eth; mod mainnet_fixtures; mod rpc; mod testnet_fixtures; - +mod utils; fn main() -> sc_cli::Result<()> { command::run() } diff --git a/node/src/service.rs b/node/src/service.rs index 27502a45b..af47bddb1 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -131,6 +131,21 @@ pub fn new_partial( >, ServiceError, > { + println!(" ++++++++++++++++++++++++ + +++++++++++++++++++++++++++ + +++++++++++++++++++++++++++ + +++ ++++++ +++ @%%%%%%%%%%% %%% + ++++++ ++++ +++++ %%%%%%%%%%%% %%%@ + ++++++++++++++++++++++++++ %%%% %%%%@ %%% %%@ @%%%%%%% %%%@ %%%%@ + ++++++++ %%%% @%%%%%%%@ %%%%%%%%% @%%%%%%%%% %%%@ %%%%%%%%% + ++++++++ %%%% %%%%%%%%% %%%% @%%%@ %%%% %%%% %%%@ %%%%%%%%%% + ++++++++++++++++++++++++++ %%%% %%%%%%%%% %%% %%%% %%% @%%% %%%@ @%%%%% %%%%% + ++++++ ++++ ++++++ %%%% %%%%%%%%% %%% %%%% %%%%%%%%%% %%%@ %%%%%%%%%@ + +++ ++++++ +++ %%%% %%%%%%%%% %%% %%%@ %%%%%%%%% %%% %%%%%%%@ + ++++ +++++++++ +++ %%%% %%%% + ++++++++++++++++++++++++++++ %%%%%%%%% + +++++++++++++++++++++++ %%%%% \n"); + let telemetry = config .telemetry_endpoints .clone() @@ -267,10 +282,11 @@ pub struct RunFullParams { pub eth_config: EthConfiguration, pub rpc_config: RpcConfig, pub debug_output: Option, + pub auto_insert_keys: bool, } /// Builds a new service for a full client. pub async fn new_full( - RunFullParams { mut config, eth_config, rpc_config, debug_output: _ }: RunFullParams, + RunFullParams { mut config, eth_config, rpc_config, debug_output: _, auto_insert_keys }: RunFullParams, ) -> Result { let sc_service::PartialComponents { client, @@ -292,6 +308,32 @@ pub async fn new_full( ), } = new_partial(&config, ð_config)?; + if config.role.is_authority() { + if auto_insert_keys { + crate::utils::insert_controller_account_keys_into_keystore( + &config, + Some(keystore_container.keystore()), + ); + } else { + crate::utils::insert_dev_controller_account_keys_into_keystore( + &config, + Some(keystore_container.keystore()), + ); + } + + // finally check if keys are inserted correctly + if crate::utils::ensure_all_keys_exist_in_keystore(keystore_container.keystore()).is_err() { + println!(" + ++++++++++++++++++++++++++++++++++++++++++++++++ + Validator keys not found, validator keys are essential to run a validator on + Tangle Network, refer to https://docs.webb.tools/docs/ecosystem-roles/validator/required-keys/ on + how to generate and insert keys. OR start the node with --auto-insert-keys to automatically generate the keys. + ++++++++++++++++++++++++++++++++++++++++++++++++ + \n"); + panic!("Keys not detected!") + } + } + let FrontierPartialComponents { filter_pool, fee_history_cache, fee_history_cache_limit } = new_frontier_partial(ð_config)?; diff --git a/node/src/utils.rs b/node/src/utils.rs new file mode 100644 index 000000000..77643c6c9 --- /dev/null +++ b/node/src/utils.rs @@ -0,0 +1,134 @@ +use sc_service::{ChainType, Configuration}; +use sp_core::{ecdsa, ed25519, sr25519, ByteArray, Pair, Public}; +use sp_keystore::{Keystore, KeystorePtr}; +use sp_runtime::{ + key_types::{ACCOUNT, BABE, GRANDPA, IM_ONLINE}, + KeyTypeId, +}; + +/// Helper function to generate a crypto pair from seed. +pub fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{seed}"), None) + .expect("static values are valid; qed") + .public() +} + +/// Inserts a key of type `ACCOUNT` into the keystore for development/testing. +pub fn insert_controller_account_keys_into_keystore( + config: &Configuration, + key_store: Option, +) { + insert_account_keys_into_keystore::( + config, + ACCOUNT, + key_store.clone(), + "acco", + ); + insert_account_keys_into_keystore::( + config, + tangle_crypto_primitives::ROLE_KEY_TYPE, + key_store.clone(), + "Role", + ); + insert_account_keys_into_keystore::( + config, + GRANDPA, + key_store.clone(), + "Grandpa", + ); + insert_account_keys_into_keystore::(config, BABE, key_store.clone(), "Babe"); + insert_account_keys_into_keystore::( + config, + IM_ONLINE, + key_store.clone(), + "ImOnline", + ); +} + +/// Inserts keys of specified type into the keystore. +fn insert_account_keys_into_keystore( + config: &Configuration, + key_type: KeyTypeId, + key_store: Option, + key_name: &str, +) { + let seed = &config.network.node_name[..]; + + let pub_key = get_from_seed::(seed).to_raw_vec(); + if let Some(keystore) = key_store { + let _ = Keystore::insert(&*keystore, key_type, &format!("//{seed}"), &pub_key); + } + + println!("++++++++++++++++++++++++++++++++++++++++++++++++ + AUTO GENERATED KEYS + {:?} key inserted to keystore + Seed : //{:?} + Pubkey : {:?} + STORE THE KEYS SAFELY, NOT TO BE SHARED WITH ANYONE ELSE. + ++++++++++++++++++++++++++++++++++++++++++++++++ + \n", key_name, seed, pub_key.encode()); +} + +/// Inserts a key of type `ACCOUNT` into the keystore for development/testing. +/// +/// Currently, this only successfully inserts keys if the seed is development related. +/// i.e. for Alice, Bob, Charlie, etc. +pub fn insert_dev_controller_account_keys_into_keystore( + config: &Configuration, + key_store: Option, +) { + insert_dev_account_keys_into_keystore::(config, ACCOUNT, key_store.clone()); + insert_dev_account_keys_into_keystore::( + config, + tangle_crypto_primitives::ROLE_KEY_TYPE, + key_store.clone(), + ); +} + +/// Inserts keys of specified type into the keystore for predefined nodes in development mode. +pub fn insert_dev_account_keys_into_keystore( + config: &Configuration, + key_type: KeyTypeId, + key_store: Option, +) { + let chain_type = config.chain_spec.chain_type(); + let seed = &config.network.node_name[..]; + + match seed { + // When running the chain in dev or local test net, we insert the sr25519 account keys for + // collator accounts or validator accounts into the keystore Only if the node running is one + // of the predefined nodes Alice, Bob, Charlie, Dave, Eve or Ferdie + "Alice" | "Bob" | "Charlie" | "Dave" | "Eve" | "Ferdie" => { + if chain_type == ChainType::Development || chain_type == ChainType::Local { + let pub_key = get_from_seed::(seed).to_raw_vec(); + if let Some(keystore) = key_store { + let _ = Keystore::insert(&*keystore, key_type, &format!("//{seed}"), &pub_key); + } + } + }, + _ => {}, + } +} + +/// Ensures all keys exist in the keystore. +pub fn ensure_all_keys_exist_in_keystore(key_store: KeystorePtr) -> Result<(), String> { + let key_types = [tangle_crypto_primitives::ROLE_KEY_TYPE, ACCOUNT, GRANDPA, BABE, IM_ONLINE]; + + for key_type in key_types { + // Ensure key is present + if !ensure_keytype_exists_in_keystore(key_type, key_store.clone()) { + println!("{key_type:?} key not found!"); + return Err("Key not found!".to_string()) + } + } + + Ok(()) +} + +/// Checks if a key of a specific type exists in the keystore. +fn ensure_keytype_exists_in_keystore(key_type: KeyTypeId, key_store: KeystorePtr) -> bool { + match Keystore::keys(&key_store, key_type) { + Ok(keys) => !keys.is_empty(), + Err(_) => false, + } +}