From 14993b501ec71f37f4b59fced63d415a78f256bf Mon Sep 17 00:00:00 2001 From: zoz <97761083+0xzoz@users.noreply.github.com> Date: Wed, 22 Nov 2023 09:05:02 +1100 Subject: [PATCH] [tools] vfn configs (#109) Co-authored-by: 0o-de-lally <1364012+0o-de-lally@users.noreply.github.com> Co-authored-by: Yotam Katznelson Co-authored-by: sirouk <8901571+sirouk@users.noreply.github.com> --- tools/config/src/config_cli.rs | 30 ++++---- tools/config/src/make_yaml_public_fullnode.rs | 42 ++++++----- tools/config/src/make_yaml_validator.rs | 2 +- tools/config/src/validator_config.rs | 70 ++++++++++++++++--- tools/genesis/src/wizard.rs | 4 +- tools/wallet/src/keys.rs | 5 +- 6 files changed, 108 insertions(+), 45 deletions(-) diff --git a/tools/config/src/config_cli.rs b/tools/config/src/config_cli.rs index 802cad860..377b94862 100644 --- a/tools/config/src/config_cli.rs +++ b/tools/config/src/config_cli.rs @@ -1,5 +1,5 @@ use crate::make_yaml_public_fullnode::{download_genesis, init_fullnode_yaml}; -use crate::validator_config::initialize_validator_configs; +use crate::validator_config::{validator_dialogue, vfn_dialogue}; use crate::{legacy_config, make_profile}; use anyhow::{Context, Result}; use clap::Parser; @@ -90,6 +90,9 @@ enum ConfigSub { /// check the files generated #[clap(short, long)] check: bool, + // just make the VFN file + #[clap(short, long)] + vfn: bool, }, /// Generate a fullnode dir and add fullnode.yaml from template @@ -97,9 +100,6 @@ enum ConfigSub { /// path to libra config and data files defaults to $HOME/.libra #[clap(long)] home_path: Option, - /// private VFN (only for validators) - #[clap(short, long)] - vfn: bool, }, } @@ -185,10 +185,13 @@ impl ConfigCli { Ok(()) } - Some(ConfigSub::ValidatorInit { check }) => { + Some(ConfigSub::ValidatorInit { check, vfn }) => { + let home_dir = self.path.clone().unwrap_or_else(global_config_dir); + if *vfn { + vfn_dialogue(&home_dir, None, None).await?; + return Ok(()); + } if *check { - let home_dir = self.path.clone().unwrap_or_else(global_config_dir); - let public_keys_file = home_dir.join(OPERATOR_FILE); let public_identity = read_operator_file(public_keys_file.as_path())?; @@ -237,22 +240,15 @@ impl ConfigCli { ); std::fs::create_dir_all(&data_path)?; } - initialize_validator_configs(&data_path, None).await?; + validator_dialogue(&data_path, None).await?; println!("Validators' config initialized."); Ok(()) } - Some(ConfigSub::FullnodeInit { home_path, vfn }) => { + Some(ConfigSub::FullnodeInit { home_path }) => { download_genesis(home_path.to_owned()).await?; println!("downloaded genesis block"); - let p = if *vfn { - // no need for seed peers, will be identified - // to validator node - init_fullnode_yaml(home_path.to_owned(), true, true).await? - } else { - // we want seed peers, and will not have an identity - init_fullnode_yaml(home_path.to_owned(), true, false).await? - }; + let p = init_fullnode_yaml(home_path.to_owned(), true).await?; println!("config created at {}", p.display()); diff --git a/tools/config/src/make_yaml_public_fullnode.rs b/tools/config/src/make_yaml_public_fullnode.rs index 629ab8a0f..bc9a8207f 100644 --- a/tools/config/src/make_yaml_public_fullnode.rs +++ b/tools/config/src/make_yaml_public_fullnode.rs @@ -1,29 +1,29 @@ use diem_config::config::NodeConfig; -use diem_types::{network_address::NetworkAddress, waypoint::Waypoint, PeerId}; +use diem_crypto::x25519; +use diem_types::{ + network_address::{DnsName, NetworkAddress}, + waypoint::Waypoint, + PeerId, +}; use libra_types::global_config_dir; use std::{ collections::HashMap, path::{Path, PathBuf}, }; +const FN_FILENAME: &str = "fullnode.yaml"; +const VFN_FILENAME: &str = "vfn.yaml"; /// fetch seed peers and make a yaml file from template pub async fn init_fullnode_yaml( home_dir: Option, overwrite_peers: bool, - vfn: bool, ) -> anyhow::Result { let waypoint = get_genesis_waypoint(home_dir.clone()).await?; - let yaml = if vfn { - make_private_vfn_yaml(home_dir.clone(), waypoint)? - } else { - make_fullnode_yaml(home_dir.clone(), waypoint)? - }; - - let filename = if vfn { "vfn.yaml" } else { "fullnode.yaml" }; + let yaml = make_fullnode_yaml(home_dir.clone(), waypoint)?; let home = home_dir.unwrap_or_else(global_config_dir); - let p = home.join(filename); + let p = home.join(FN_FILENAME); std::fs::write(&p, yaml)?; if overwrite_peers { @@ -102,11 +102,13 @@ api: /// Create a VFN file to for validators to seed the public network pub fn make_private_vfn_yaml( - home_dir: Option, - waypoint: Waypoint, + home_dir: &Path, + val_net_pubkey: x25519::PublicKey, + val_host_addr: DnsName, ) -> anyhow::Result { - let home_dir = home_dir.unwrap_or_else(global_config_dir); let path = home_dir.display().to_string(); + let val_net_pubkey = val_net_pubkey.to_string(); + let val_host_addr = val_host_addr.to_string(); let template = format!( " @@ -114,7 +116,7 @@ base: role: 'full_node' data_dir: '{path}/data' waypoint: - from_config: '{waypoint}' + from_file: '{path}/genesis/waypoint.txt' execution: genesis_file_location: '{path}/genesis/genesis.blob' @@ -133,17 +135,25 @@ full_node_networks: - network_id: private: 'vfn' - # mutual_authentication: true listen_address: '/ip4/0.0.0.0/tcp/6181' identity: type: 'from_file' path: {path}/validator-full-node-identity.yaml + seeds: + {val_net_pubkey}: + addresses: + - '/ip4/{val_host_addr}/tcp/6181/noise-ik/0x{val_net_pubkey}/handshake/0' + role: 'Validator' api: - enabled: false + enabled: true address: '0.0.0.0:8080' " ); + + let p = home_dir.join(VFN_FILENAME); + std::fs::write(p, &template)?; + Ok(template) } diff --git a/tools/config/src/make_yaml_validator.rs b/tools/config/src/make_yaml_validator.rs index 809bfa2cd..9804bc95c 100644 --- a/tools/config/src/make_yaml_validator.rs +++ b/tools/config/src/make_yaml_validator.rs @@ -54,7 +54,7 @@ full_node_networks: listen_address: '/ip4/0.0.0.0/tcp/6181' identity: type: 'from_file' - path: {path}/validator-full-node-identity.yaml + path: {path}/validator-identity.yaml api: enabled: true diff --git a/tools/config/src/validator_config.rs b/tools/config/src/validator_config.rs index c25736ea0..77b02e26c 100644 --- a/tools/config/src/validator_config.rs +++ b/tools/config/src/validator_config.rs @@ -1,11 +1,16 @@ +use crate::make_yaml_public_fullnode::make_private_vfn_yaml; use crate::make_yaml_validator; -use anyhow::{bail, Context}; +use anyhow::{anyhow, bail, Context}; use dialoguer::{Confirm, Input}; +use diem_crypto::x25519; use diem_genesis::config::HostAndPort; +use diem_genesis::keys::PublicIdentity; use diem_types::chain_id::NamedChain; +use diem_types::network_address::DnsName; use libra_types::legacy_types::app_cfg::AppCfg; use libra_types::legacy_types::network_playlist::NetworkPlaylist; use libra_types::ol_progress::OLProgress; +use libra_wallet::utils::read_public_identity_file; use libra_wallet::validator_files::SetValidatorConfiguration; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -17,8 +22,8 @@ pub fn initialize_validator( mnem: Option, keep_legacy_address: bool, chain_name: Option, -) -> anyhow::Result<()> { - let (.., keys) = +) -> anyhow::Result { + let (.., pub_id, keys) = libra_wallet::keys::refresh_validator_files(mnem, home_path.clone(), keep_legacy_address)?; OLProgress::complete("initialized validator key files"); @@ -48,7 +53,7 @@ pub fn initialize_validator( ))?; OLProgress::complete("saved a user libra.yaml file locally"); - Ok(()) + Ok(pub_id) } async fn get_ip() -> anyhow::Result { @@ -72,7 +77,7 @@ pub async fn what_host() -> Result { }; let input: String = Input::new() - .with_prompt("Enter the DNS or IP address, with port 6180") + .with_prompt("Enter the DNS or IP address, with port. Use validator: 6180, VFN: 6181, fullnode: 6182") .interact_text() .unwrap(); let ip = input @@ -82,7 +87,7 @@ pub async fn what_host() -> Result { Ok(ip) } -pub async fn initialize_validator_configs( +pub async fn validator_dialogue( data_path: &Path, github_username: Option<&str>, ) -> Result<(), anyhow::Error> { @@ -99,19 +104,68 @@ pub async fn initialize_validator_configs( .with_prompt("Is this a legacy V5 address you wish to keep?") .interact()?; - initialize_validator( + let pub_id = initialize_validator( Some(data_path.to_path_buf()), github_username, - host, + host.clone(), None, keep_legacy_address, None, )?; + + // now set up the vfn.yaml on the same host for convenience + vfn_dialogue( + data_path, + Some(host.host), + pub_id.validator_network_public_key, + ) + .await?; } Ok(()) } +fn get_local_vfn_id(home: &Path) -> anyhow::Result { + let id = read_public_identity_file(&home.join("public-keys.yaml"))?; + + id.validator_network_public_key + .context("no validator public key found in public-keys.yaml") +} + +pub async fn vfn_dialogue( + home: &Path, + host: Option, + net_pubkey: Option, +) -> anyhow::Result<()> { + let dns = match host { + Some(d) => d, + None => { + println!("Let's get the network address of your VALIDATOR host"); + + what_host().await?.host + } + }; + + let pk = match net_pubkey { + Some(r) => r, + // maybe they already have the public-keys.yamlhere + None => get_local_vfn_id(home).map_err(|e| { + anyhow!("ERROR: cannot make vfn.yaml, make sure you have the public-keys.yaml on this host before starting, message: {}", e) + })?, + }; + + make_private_vfn_yaml( + home, + // NOTE: the VFN needs to identify the validator node, which uses the + // same validator_network public ID + pk, dns, + )?; + + println!("SUCCESS: on your VFN you should have vfn.yaml, validator-full-node.yaml files before starting node."); + + Ok(()) +} + #[test] fn test_validator_files_config() { use libra_types::global_config_dir; diff --git a/tools/genesis/src/wizard.rs b/tools/genesis/src/wizard.rs index e8ddaeead..373c5fbc6 100644 --- a/tools/genesis/src/wizard.rs +++ b/tools/genesis/src/wizard.rs @@ -26,7 +26,7 @@ use diem_github_client::Client; use libra_types::legacy_types::app_cfg::AppCfg; use libra_wallet::keys::VALIDATOR_FILE; -use libra_config::validator_config::initialize_validator_configs; +use libra_config::validator_config::validator_dialogue; pub const DEFAULT_GIT_BRANCH: &str = "main"; pub const GITHUB_TOKEN_FILENAME: &str = "github_token.txt"; @@ -92,7 +92,7 @@ impl GenesisWizard { // check the git token is as expected, and set it. self.git_token_check()?; - match initialize_validator_configs(&self.data_path, Some(&self.github_username)).await { + match validator_dialogue(&self.data_path, Some(&self.github_username)).await { Ok(_) => { println!("Validators' config initialized!"); } diff --git a/tools/wallet/src/keys.rs b/tools/wallet/src/keys.rs index f03ff6251..769119c9a 100644 --- a/tools/wallet/src/keys.rs +++ b/tools/wallet/src/keys.rs @@ -185,7 +185,10 @@ pub fn generate_key_objects_from_legacy( network_private_key: validator_network_key.private_key(), }; let vfn_blob = IdentityBlob { - account_address: Some(account_address), + // the VFN needs a different address than the validator + // otherwise it will think it is dialing itself, and + // will show a "self dial" error on the validator logs + account_address: Some(full_node_network_key.public_key().to_string().parse()?), account_private_key: None, consensus_private_key: None, network_private_key: full_node_network_key.private_key(),