From 9f8e2899922c0eec9167ed4f49c5d4c161330221 Mon Sep 17 00:00:00 2001 From: Cayle Sharrock Date: Wed, 10 Nov 2021 14:07:59 +0000 Subject: [PATCH] feat: add support for MultiAddr in RPC config (#3557) Motivation and Context --- Robust networking support in docker configurations requires us to be able to specify the gRPC address of things like the node and wallet in terms of domains instead of raw IP addresses. This adds support for MultiAddr specification of these addresses while still being 100% backwards compatible. Also included in #3534 How Has This Been Tested? --- No new tests added. --- Cargo.lock | 3 ++ applications/tari_base_node/src/main.rs | 10 ++++- .../tari_console_wallet/src/wallet_modes.rs | 12 +++--- .../tari_merge_mining_proxy/Cargo.toml | 1 + .../tari_merge_mining_proxy/src/main.rs | 4 +- .../tari_merge_mining_proxy/src/proxy.rs | 18 +++++--- applications/tari_mining_node/Cargo.toml | 1 + applications/tari_mining_node/src/config.rs | 19 ++++----- applications/tari_mining_node/src/errors.rs | 2 + applications/tari_mining_node/src/main.rs | 8 ++-- .../tari_stratum_transcoder/Cargo.toml | 1 + .../tari_stratum_transcoder/src/main.rs | 4 +- .../tari_stratum_transcoder/src/proxy.rs | 17 +++++--- common/src/configuration/global.rs | 41 +++++++++++-------- 14 files changed, 84 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7250677e8b..26d72745ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4748,6 +4748,7 @@ dependencies = [ "tari_app_grpc", "tari_app_utilities", "tari_common", + "tari_comms", "tari_core", "tari_crypto", "tari_utilities", @@ -4782,6 +4783,7 @@ dependencies = [ "tari_app_grpc", "tari_app_utilities", "tari_common", + "tari_comms", "tari_core", "tari_crypto", "thiserror", @@ -4936,6 +4938,7 @@ dependencies = [ "structopt", "tari_app_grpc", "tari_common", + "tari_comms", "tari_core", "tari_crypto", "tari_utilities", diff --git a/applications/tari_base_node/src/main.rs b/applications/tari_base_node/src/main.rs index a7561a6f37..c658bf74e5 100644 --- a/applications/tari_base_node/src/main.rs +++ b/applications/tari_base_node/src/main.rs @@ -114,7 +114,11 @@ use tari_app_utilities::{ utilities::setup_runtime, }; use tari_common::{configuration::bootstrap::ApplicationType, exit_codes::ExitCodes, ConfigBootstrap, GlobalConfig}; -use tari_comms::{peer_manager::PeerFeatures, tor::HiddenServiceControllerError}; +use tari_comms::{ + peer_manager::PeerFeatures, + tor::HiddenServiceControllerError, + utils::multiaddr::multiaddr_to_socketaddr, +}; use tari_core::chain_storage::ChainStorageError; use tari_shutdown::{Shutdown, ShutdownSignal}; use tokio::{ @@ -228,7 +232,9 @@ async fn run_node(node_config: Arc, bootstrap: ConfigBootstrap) -> if node_config.grpc_enabled { // Go, GRPC, go go let grpc = crate::grpc::base_node_grpc_server::BaseNodeGrpcServer::from_base_node_context(&ctx); - task::spawn(run_grpc(grpc, node_config.grpc_base_node_address, shutdown.to_signal())); + let socket_addr = multiaddr_to_socketaddr(&node_config.grpc_base_node_address) + .map_err(|e| ExitCodes::ConfigError(e.to_string()))?; + task::spawn(run_grpc(grpc, socket_addr, shutdown.to_signal())); } // Run, node, run! diff --git a/applications/tari_console_wallet/src/wallet_modes.rs b/applications/tari_console_wallet/src/wallet_modes.rs index 2193021b02..1caa9c979a 100644 --- a/applications/tari_console_wallet/src/wallet_modes.rs +++ b/applications/tari_console_wallet/src/wallet_modes.rs @@ -30,9 +30,9 @@ use crate::{ }; use log::*; use rand::{rngs::OsRng, seq::SliceRandom}; -use std::{fs, io::Stdout, net::SocketAddr, path::PathBuf}; +use std::{fs, io::Stdout, path::PathBuf}; use tari_common::{exit_codes::ExitCodes, ConfigBootstrap, GlobalConfig}; -use tari_comms::peer_manager::Peer; +use tari_comms::{multiaddr::Multiaddr, peer_manager::Peer, utils::multiaddr::multiaddr_to_socketaddr}; use tari_wallet::WalletSqlite; use tokio::runtime::Handle; use tonic::transport::Server; @@ -213,7 +213,7 @@ pub fn tui_mode(config: WalletModeConfig, mut wallet: WalletSqlite) -> Result<() .. } = config; let grpc = WalletGrpcServer::new(wallet.clone()); - handle.spawn(run_grpc(grpc, global_config.grpc_console_wallet_address)); + handle.spawn(run_grpc(grpc, global_config.grpc_console_wallet_address.clone())); let notifier = Notifier::new(notify_script, handle.clone(), wallet.clone()); @@ -294,12 +294,12 @@ pub fn grpc_mode(config: WalletModeConfig, wallet: WalletSqlite) -> Result<(), E Ok(()) } -async fn run_grpc(grpc: WalletGrpcServer, grpc_console_wallet_address: SocketAddr) -> Result<(), String> { +async fn run_grpc(grpc: WalletGrpcServer, grpc_console_wallet_address: Multiaddr) -> Result<(), String> { info!(target: LOG_TARGET, "Starting GRPC on {}", grpc_console_wallet_address); - + let socket = multiaddr_to_socketaddr(&grpc_console_wallet_address).map_err(|e| e.to_string())?; Server::builder() .add_service(tari_app_grpc::tari_rpc::wallet_server::WalletServer::new(grpc)) - .serve(grpc_console_wallet_address) + .serve(socket) .await .map_err(|e| format!("GRPC server returned error:{}", e))?; info!(target: LOG_TARGET, "Stopping GRPC"); diff --git a/applications/tari_merge_mining_proxy/Cargo.toml b/applications/tari_merge_mining_proxy/Cargo.toml index bdcc5dc430..aadc3bf6dc 100644 --- a/applications/tari_merge_mining_proxy/Cargo.toml +++ b/applications/tari_merge_mining_proxy/Cargo.toml @@ -14,6 +14,7 @@ envlog = ["env_logger"] [dependencies] tari_app_grpc = { path = "../tari_app_grpc" } tari_common = { path = "../../common" } +tari_comms = { path = "../../comms" } tari_core = { path = "../../base_layer/core", default-features = false, features = ["transactions"] } tari_app_utilities = { path = "../tari_app_utilities" } tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", branch = "main" } diff --git a/applications/tari_merge_mining_proxy/src/main.rs b/applications/tari_merge_mining_proxy/src/main.rs index 0df27490bb..b58d74d5d7 100644 --- a/applications/tari_merge_mining_proxy/src/main.rs +++ b/applications/tari_merge_mining_proxy/src/main.rs @@ -40,7 +40,7 @@ use crate::{block_template_data::BlockTemplateRepository, error::MmProxyError}; use futures::future; use hyper::{service::make_service_fn, Server}; use proxy::{MergeMiningProxyConfig, MergeMiningProxyService}; -use std::convert::Infallible; +use std::convert::{Infallible, TryFrom}; use tari_app_grpc::tari_rpc as grpc; use tari_app_utilities::initialization::init_configuration; use tari_common::configuration::bootstrap::ApplicationType; @@ -50,7 +50,7 @@ use tokio::time::Duration; async fn main() -> Result<(), anyhow::Error> { let (_, config, _) = init_configuration(ApplicationType::MergeMiningProxy)?; - let config = MergeMiningProxyConfig::from(config); + let config = MergeMiningProxyConfig::try_from(config)?; let addr = config.proxy_host_address; let client = reqwest::Client::builder() .connect_timeout(Duration::from_secs(5)) diff --git a/applications/tari_merge_mining_proxy/src/proxy.rs b/applications/tari_merge_mining_proxy/src/proxy.rs index ff31d8e8f9..f3a9ad5a96 100644 --- a/applications/tari_merge_mining_proxy/src/proxy.rs +++ b/applications/tari_merge_mining_proxy/src/proxy.rs @@ -34,6 +34,7 @@ use reqwest::{ResponseBuilderExt, Url}; use serde_json as json; use std::{ cmp, + convert::TryFrom, future::Future, net::SocketAddr, pin::Pin, @@ -46,6 +47,7 @@ use std::{ }; use tari_app_grpc::tari_rpc as grpc; use tari_common::{configuration::Network, GlobalConfig}; +use tari_comms::utils::multiaddr::multiaddr_to_socketaddr; use tari_core::proof_of_work::{monero_rx, monero_rx::FixedByteArray}; use tari_utilities::hex::Hex; use tracing::{debug, error, info, instrument, trace, warn}; @@ -70,20 +72,24 @@ pub struct MergeMiningProxyConfig { pub wait_for_initial_sync_at_startup: bool, } -impl From for MergeMiningProxyConfig { - fn from(config: GlobalConfig) -> Self { - Self { +impl TryFrom for MergeMiningProxyConfig { + type Error = std::io::Error; + + fn try_from(config: GlobalConfig) -> Result { + let grpc_base_node_address = multiaddr_to_socketaddr(&config.grpc_base_node_address)?; + let grpc_console_wallet_address = multiaddr_to_socketaddr(&config.grpc_console_wallet_address)?; + Ok(Self { network: config.network, monerod_url: config.monerod_url, monerod_username: config.monerod_username, monerod_password: config.monerod_password, monerod_use_auth: config.monerod_use_auth, - grpc_base_node_address: config.grpc_base_node_address, - grpc_console_wallet_address: config.grpc_console_wallet_address, + grpc_base_node_address, + grpc_console_wallet_address, proxy_host_address: config.proxy_host_address, proxy_submit_to_origin: config.proxy_submit_to_origin, wait_for_initial_sync_at_startup: config.wait_for_initial_sync_at_startup, - } + }) } } diff --git a/applications/tari_mining_node/Cargo.toml b/applications/tari_mining_node/Cargo.toml index e8431f0540..5ff573f720 100644 --- a/applications/tari_mining_node/Cargo.toml +++ b/applications/tari_mining_node/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" [dependencies] tari_core = { path = "../../base_layer/core", default-features = false } tari_common = { path = "../../common" } +tari_comms = { path = "../../comms" } tari_app_utilities = { path = "../tari_app_utilities"} tari_app_grpc = { path = "../tari_app_grpc" } tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", branch = "main" } diff --git a/applications/tari_mining_node/src/config.rs b/applications/tari_mining_node/src/config.rs index 6b46e8e195..69f618f919 100644 --- a/applications/tari_mining_node/src/config.rs +++ b/applications/tari_mining_node/src/config.rs @@ -40,11 +40,10 @@ use serde::{Deserialize, Serialize}; use std::time::Duration; use tari_app_grpc::tari_rpc::{pow_algo::PowAlgos, NewBlockTemplateRequest, PowAlgo}; use tari_common::{GlobalConfig, NetworkConfigPath}; +use tari_comms::utils::multiaddr::multiaddr_to_socketaddr; #[derive(Serialize, Deserialize, Debug)] pub struct MinerConfig { - pub base_node_grpc_address: Option, - pub wallet_grpc_address: Option, pub num_mining_threads: usize, pub mine_on_tip_only: bool, pub proof_of_work_algo: ProofOfWork, @@ -68,8 +67,6 @@ impl NetworkConfigPath for MinerConfig { impl Default for MinerConfig { fn default() -> Self { Self { - base_node_grpc_address: None, - wallet_grpc_address: None, num_mining_threads: num_cpus::get(), mine_on_tip_only: true, proof_of_work_algo: ProofOfWork::Sha3, @@ -82,16 +79,14 @@ impl Default for MinerConfig { } impl MinerConfig { - pub fn base_node_addr(&self, global: &GlobalConfig) -> String { - self.base_node_grpc_address - .clone() - .unwrap_or_else(|| format!("http://{}", global.grpc_base_node_address)) + pub fn base_node_addr(&self, global: &GlobalConfig) -> Result { + let socket = multiaddr_to_socketaddr(&global.grpc_base_node_address)?; + Ok(format!("http://{}", socket)) } - pub fn wallet_addr(&self, global: &GlobalConfig) -> String { - self.wallet_grpc_address - .clone() - .unwrap_or_else(|| format!("http://{}", global.grpc_console_wallet_address)) + pub fn wallet_addr(&self, global: &GlobalConfig) -> Result { + let socket = multiaddr_to_socketaddr(&global.grpc_console_wallet_address)?; + Ok(format!("http://{}", socket)) } pub fn pow_algo_request(&self) -> NewBlockTemplateRequest { diff --git a/applications/tari_mining_node/src/errors.rs b/applications/tari_mining_node/src/errors.rs index d8aed339d9..9dc4c304da 100644 --- a/applications/tari_mining_node/src/errors.rs +++ b/applications/tari_mining_node/src/errors.rs @@ -24,6 +24,8 @@ use thiserror::Error; #[derive(Debug, Error)] pub enum MinerError { + #[error("I/O error")] + IOError(#[from] std::io::Error), #[error("GRPC error: {0}")] GrpcStatus(#[from] tonic::Status), #[error("Connection error: {0}")] diff --git a/applications/tari_mining_node/src/main.rs b/applications/tari_mining_node/src/main.rs index 568bc67eb9..92ee565015 100644 --- a/applications/tari_mining_node/src/main.rs +++ b/applications/tari_mining_node/src/main.rs @@ -223,12 +223,12 @@ async fn connect( config: &MinerConfig, global: &GlobalConfig, ) -> Result<(BaseNodeClient, WalletClient), MinerError> { - let base_node_addr = config.base_node_addr(global); + let base_node_addr = config.base_node_addr(global)?; info!(target: LOG_TARGET, "Connecting to base node at {}", base_node_addr); - let node_conn = BaseNodeClient::connect(base_node_addr.clone()).await?; - let wallet_addr = config.wallet_addr(global); + let node_conn = BaseNodeClient::connect(base_node_addr).await?; + let wallet_addr = config.wallet_addr(global)?; info!(target: LOG_TARGET, "Connecting to wallet at {}", wallet_addr); - let wallet_conn = WalletClient::connect(wallet_addr.clone()).await?; + let wallet_conn = WalletClient::connect(wallet_addr).await?; Ok((node_conn, wallet_conn)) } diff --git a/applications/tari_stratum_transcoder/Cargo.toml b/applications/tari_stratum_transcoder/Cargo.toml index f02b8c5ba0..dc25e5d987 100644 --- a/applications/tari_stratum_transcoder/Cargo.toml +++ b/applications/tari_stratum_transcoder/Cargo.toml @@ -12,6 +12,7 @@ default = [] envlog = ["env_logger"] [dependencies] +tari_comms = { path = "../../comms" } tari_app_grpc = { path = "../tari_app_grpc" } tari_common = { path = "../../common" } tari_core = { path = "../../base_layer/core", default-features = false, features = ["transactions"] } diff --git a/applications/tari_stratum_transcoder/src/main.rs b/applications/tari_stratum_transcoder/src/main.rs index f742c92d6d..61e0da2d88 100644 --- a/applications/tari_stratum_transcoder/src/main.rs +++ b/applications/tari_stratum_transcoder/src/main.rs @@ -35,7 +35,7 @@ use crate::error::StratumTranscoderProxyError; use futures::future; use hyper::{service::make_service_fn, Server}; use proxy::{StratumTranscoderProxyConfig, StratumTranscoderProxyService}; -use std::convert::Infallible; +use std::convert::{Infallible, TryFrom}; use structopt::StructOpt; use tari_app_grpc::tari_rpc as grpc; use tari_common::{configuration::bootstrap::ApplicationType, ConfigBootstrap, GlobalConfig}; @@ -45,7 +45,7 @@ use tokio::time::Duration; async fn main() -> Result<(), StratumTranscoderProxyError> { let config = initialize()?; - let config = StratumTranscoderProxyConfig::from(config); + let config = StratumTranscoderProxyConfig::try_from(config)?; let addr = config.transcoder_host_address; let client = reqwest::Client::builder() .connect_timeout(Duration::from_secs(5)) diff --git a/applications/tari_stratum_transcoder/src/proxy.rs b/applications/tari_stratum_transcoder/src/proxy.rs index eac834d6e0..c3ce03ee56 100644 --- a/applications/tari_stratum_transcoder/src/proxy.rs +++ b/applications/tari_stratum_transcoder/src/proxy.rs @@ -44,6 +44,7 @@ use std::{ }; use tari_app_grpc::{tari_rpc as grpc, tari_rpc::GetCoinbaseRequest}; use tari_common::{configuration::Network, GlobalConfig}; +use tari_comms::utils::multiaddr::multiaddr_to_socketaddr; use tari_core::blocks::{Block, NewBlockTemplate}; use tari_utilities::{hex::Hex, message_format::MessageFormat}; use tracing::{debug, error}; @@ -58,14 +59,18 @@ pub struct StratumTranscoderProxyConfig { pub transcoder_host_address: SocketAddr, } -impl From for StratumTranscoderProxyConfig { - fn from(config: GlobalConfig) -> Self { - Self { +impl TryFrom for StratumTranscoderProxyConfig { + type Error = std::io::Error; + + fn try_from(config: GlobalConfig) -> Result { + let grpc_base_node_address = multiaddr_to_socketaddr(&config.grpc_base_node_address)?; + let grpc_console_wallet_address = multiaddr_to_socketaddr(&config.grpc_console_wallet_address)?; + Ok(Self { network: config.network, - grpc_base_node_address: config.grpc_base_node_address, - grpc_console_wallet_address: config.grpc_console_wallet_address, + grpc_base_node_address, + grpc_console_wallet_address, transcoder_host_address: config.transcoder_host_address, - } + }) } } diff --git a/common/src/configuration/global.rs b/common/src/configuration/global.rs index 958c1d40f1..b35004b990 100644 --- a/common/src/configuration/global.rs +++ b/common/src/configuration/global.rs @@ -27,7 +27,6 @@ use crate::{ ConfigurationError, }; use config::{Config, ConfigError, Environment}; -use multiaddr::Multiaddr; use std::{ convert::TryInto, fmt, @@ -35,9 +34,13 @@ use std::{ net::SocketAddr, num::{NonZeroU16, TryFromIntError}, path::PathBuf, + prelude::rust_2021::FromIterator, str::FromStr, time::Duration, }; + +use multiaddr::{Error, Multiaddr, Protocol}; + use tari_storage::lmdb_store::LMDBConfig; const DB_INIT_DEFAULT_MB: usize = 1000; @@ -74,8 +77,8 @@ pub struct GlobalConfig { pub base_node_identity_file: PathBuf, pub public_address: Multiaddr, pub grpc_enabled: bool, - pub grpc_base_node_address: SocketAddr, - pub grpc_console_wallet_address: SocketAddr, + pub grpc_base_node_address: Multiaddr, + pub grpc_console_wallet_address: Multiaddr, pub peer_seeds: Vec, pub dns_seeds: Vec, pub dns_seeds_name_server: DnsNameServer, @@ -192,7 +195,7 @@ fn convert_node_config( return Err(ConfigurationError::new( &key, &format!("DB initial size must be at least {} MB.", DB_INIT_MIN_MB), - )) + )); }, Ok(mb) => mb as usize, Err(e) => match e { @@ -207,7 +210,7 @@ fn convert_node_config( return Err(ConfigurationError::new( &key, &format!("DB grow size must be at least {} MB.", DB_GROW_SIZE_MIN_MB), - )) + )); }, Ok(mb) => mb as usize, Err(e) => match e { @@ -225,19 +228,19 @@ fn convert_node_config( "DB resize threshold must be at least {} MB.", DB_RESIZE_THRESHOLD_MIN_MB ), - )) + )); }, Ok(mb) if mb as usize >= grow_size_mb => { return Err(ConfigurationError::new( &key, "DB resize threshold must be less than grow size.", - )) + )); }, Ok(mb) if mb as usize >= init_size_mb => { return Err(ConfigurationError::new( &key, "DB resize threshold must be less than init size.", - )) + )); }, Ok(mb) => mb as usize, Err(e) => match e { @@ -341,20 +344,13 @@ fn convert_node_config( let key = config_string("base_node", net_str, "grpc_base_node_address"); let grpc_base_node_address = cfg .get_str(&key) - .map_err(|e| ConfigurationError::new(&key, &e.to_string())) - .and_then(|addr| { - addr.parse::() - .map_err(|e| ConfigurationError::new(&key, &e.to_string())) - })?; + .map(|addr| socket_or_multi(&addr).map_err(|e| ConfigurationError::new(&key, &e.to_string())))??; let key = config_string("base_node", net_str, "grpc_console_wallet_address"); let grpc_console_wallet_address = cfg .get_str(&key) .map_err(|e| ConfigurationError::new(&key, &e.to_string())) - .and_then(|addr| { - addr.parse::() - .map_err(|e| ConfigurationError::new(&key, &e.to_string())) - })?; + .map(|addr| socket_or_multi(&addr).map_err(|e| ConfigurationError::new(&key, &e.to_string())))??; // Peer and DNS seeds let key = "common.peer_seeds"; @@ -976,6 +972,17 @@ fn parse_key_value(s: &str, split_chr: char) -> (String, Option<&str>) { ) } +/// Interpret a string as either a socket address (first) or a multiaddr format string. +/// If the former, it gets converted into a MultiAddr before being returned. +pub fn socket_or_multi(addr: &str) -> Result { + addr.parse::() + .map(|socket| match socket { + SocketAddr::V4(ip4) => Multiaddr::from_iter([Protocol::Ip4(*ip4.ip()), Protocol::Tcp(ip4.port())]), + SocketAddr::V6(ip6) => Multiaddr::from_iter([Protocol::Ip6(*ip6.ip()), Protocol::Tcp(ip6.port())]), + }) + .or_else(|_| addr.parse::()) +} + impl FromStr for TorControlAuthentication { type Err = String;