From 652e0f3008e1f272a02f446630ac9e83c53139e8 Mon Sep 17 00:00:00 2001 From: TheCharlatan Date: Sat, 3 Dec 2022 00:53:54 +0100 Subject: [PATCH 1/2] Grpc/Server: Add network args to health check --- src/bus/types.rs | 44 +++++- src/cli/command.rs | 212 +++++++++++++++++----------- src/cli/opts.rs | 10 +- src/grpcd/proto/farcaster.proto | 22 ++- src/grpcd/runtime.rs | 239 +++++++++++++++++++++----------- 5 files changed, 360 insertions(+), 167 deletions(-) diff --git a/src/bus/types.rs b/src/bus/types.rs index f10275ec4..509bf0d98 100644 --- a/src/bus/types.rs +++ b/src/bus/types.rs @@ -1,6 +1,10 @@ -use std::fmt::{self, Debug, Display, Formatter}; +use std::{ + fmt::{self, Debug, Display, Formatter}, + str::FromStr, +}; use farcaster_core::{ + blockchain::Network, role::TradeRole, swap::{btcxmr::PublicOffer, SwapId}, }; @@ -210,6 +214,30 @@ impl From for rpc::FailureCode { impl rpc::FailureCodeExt for FailureCode {} +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, From)] +pub enum HealthCheckSelector { + #[display(inner)] + Network(Network), + #[display("all")] + All, +} + +impl FromStr for HealthCheckSelector { + type Err = farcaster_core::consensus::Error; + fn from_str(input: &str) -> Result { + match Network::from_str(&input) { + Ok(n) => Ok(HealthCheckSelector::Network(n)), + Err(err) => { + if input == "all" || input == "All" { + Ok(HealthCheckSelector::All) + } else { + Err(err) + } + } + } + } +} + #[derive(Clone, Debug, Display, NetworkEncode, NetworkDecode)] #[cfg_attr( feature = "serde", @@ -226,5 +254,19 @@ pub struct HealthReport { pub monero_local_health: Health, } +#[derive(Clone, Debug, Display, NetworkEncode, NetworkDecode)] +#[cfg_attr( + feature = "serde", + derive(Serialize, Deserialize), + serde(crate = "serde_crate") +)] +#[display(ReducedHealthReport::to_yaml_string)] +pub struct ReducedHealthReport { + pub bitcoin_health: Health, + pub monero_health: Health, +} + #[cfg(feature = "serde")] impl ToYamlString for HealthReport {} +#[cfg(feature = "serde")] +impl ToYamlString for ReducedHealthReport {} diff --git a/src/cli/command.rs b/src/cli/command.rs index 732c97756..5ae2c7bde 100644 --- a/src/cli/command.rs +++ b/src/cli/command.rs @@ -36,7 +36,9 @@ use crate::bus::{ info::{Address, InfoMsg}, AddressSecretKey, }; -use crate::bus::{BusMsg, Failure, FailureCode, HealthReport}; +use crate::bus::{ + BusMsg, Failure, FailureCode, HealthCheckSelector, HealthReport, ReducedHealthReport, +}; use crate::cli::opts::CheckpointSelector; use crate::client::Client; use crate::syncerd::{SweepAddressAddendum, SweepBitcoinAddress, SweepMoneroAddress}; @@ -204,95 +206,137 @@ impl Exec for Command { runtime.report_response_or_fail()?; } - Command::HealthCheck => { - runtime.request_ctl( - ServiceId::Farcasterd, - CtlMsg::HealthCheck(Blockchain::Bitcoin, Network::Testnet), - )?; - let bitcoin_testnet_health = match runtime.response()? { - BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, - _ => { - return Err(Error::Other( - "Server returned unexpected response for call health check".to_string(), - )) - } - }; + Command::HealthCheck { selector } => match selector { + HealthCheckSelector::Network(network) => { + runtime.request_ctl( + ServiceId::Farcasterd, + CtlMsg::HealthCheck(Blockchain::Bitcoin, network), + )?; + let bitcoin_health = match runtime.response()? { + BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, + _ => { + return Err(Error::Other( + "Server returned unexpected response for call health check" + .to_string(), + )) + } + }; - runtime.request_ctl( - ServiceId::Farcasterd, - CtlMsg::HealthCheck(Blockchain::Bitcoin, Network::Mainnet), - )?; - let bitcoin_mainnet_health = match runtime.response()? { - BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, - _ => { - return Err(Error::Other( - "Server returned unexpected response for call health check".to_string(), - )) - } - }; - runtime.request_ctl( - ServiceId::Farcasterd, - CtlMsg::HealthCheck(Blockchain::Bitcoin, Network::Local), - )?; - let bitcoin_local_health = match runtime.response()? { - BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, - _ => { - return Err(Error::Other( - "Server returned unexpected response for call health check".to_string(), - )) - } - }; + runtime.request_ctl( + ServiceId::Farcasterd, + CtlMsg::HealthCheck(Blockchain::Monero, network), + )?; + let monero_health = match runtime.response()? { + BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, + _ => { + return Err(Error::Other( + "Server returned unexpected response for call health check" + .to_string(), + )) + } + }; - runtime.request_ctl( - ServiceId::Farcasterd, - CtlMsg::HealthCheck(Blockchain::Monero, Network::Testnet), - )?; - let monero_testnet_health = match runtime.response()? { - BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, - _ => { - return Err(Error::Other( - "Server returned unexpected response for call health check".to_string(), - )) - } - }; + let health = ReducedHealthReport { + bitcoin_health, + monero_health, + }; + println!("{}", health); + } + HealthCheckSelector::All => { + runtime.request_ctl( + ServiceId::Farcasterd, + CtlMsg::HealthCheck(Blockchain::Bitcoin, Network::Testnet), + )?; + let bitcoin_testnet_health = match runtime.response()? { + BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, + _ => { + return Err(Error::Other( + "Server returned unexpected response for call health check" + .to_string(), + )) + } + }; - runtime.request_ctl( - ServiceId::Farcasterd, - CtlMsg::HealthCheck(Blockchain::Monero, Network::Mainnet), - )?; - let monero_mainnet_health = match runtime.response()? { - BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, - _ => { - return Err(Error::Other( - "Server returned unexpected response for call health check".to_string(), - )) - } - }; + runtime.request_ctl( + ServiceId::Farcasterd, + CtlMsg::HealthCheck(Blockchain::Bitcoin, Network::Mainnet), + )?; + let bitcoin_mainnet_health = match runtime.response()? { + BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, + _ => { + return Err(Error::Other( + "Server returned unexpected response for call health check" + .to_string(), + )) + } + }; + runtime.request_ctl( + ServiceId::Farcasterd, + CtlMsg::HealthCheck(Blockchain::Bitcoin, Network::Local), + )?; + let bitcoin_local_health = match runtime.response()? { + BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, + _ => { + return Err(Error::Other( + "Server returned unexpected response for call health check" + .to_string(), + )) + } + }; - runtime.request_ctl( - ServiceId::Farcasterd, - CtlMsg::HealthCheck(Blockchain::Monero, Network::Local), - )?; - let monero_local_health = match runtime.response()? { - BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, - _ => { - return Err(Error::Other( - "Server returned unexpected response for call health check".to_string(), - )) - } - }; + runtime.request_ctl( + ServiceId::Farcasterd, + CtlMsg::HealthCheck(Blockchain::Monero, Network::Testnet), + )?; + let monero_testnet_health = match runtime.response()? { + BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, + _ => { + return Err(Error::Other( + "Server returned unexpected response for call health check" + .to_string(), + )) + } + }; - let report = HealthReport { - bitcoin_testnet_health, - bitcoin_mainnet_health, - bitcoin_local_health, - monero_testnet_health, - monero_mainnet_health, - monero_local_health, - }; + runtime.request_ctl( + ServiceId::Farcasterd, + CtlMsg::HealthCheck(Blockchain::Monero, Network::Mainnet), + )?; + let monero_mainnet_health = match runtime.response()? { + BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, + _ => { + return Err(Error::Other( + "Server returned unexpected response for call health check" + .to_string(), + )) + } + }; - println!("{}", report); - } + runtime.request_ctl( + ServiceId::Farcasterd, + CtlMsg::HealthCheck(Blockchain::Monero, Network::Local), + )?; + let monero_local_health = match runtime.response()? { + BusMsg::Ctl(CtlMsg::HealthResult(health)) => health, + _ => { + return Err(Error::Other( + "Server returned unexpected response for call health check" + .to_string(), + )) + } + }; + + let report = HealthReport { + bitcoin_testnet_health, + bitcoin_mainnet_health, + bitcoin_local_health, + monero_testnet_health, + monero_mainnet_health, + monero_local_health, + }; + println!("{}", report); + } + }, Command::Make { network, diff --git a/src/cli/opts.rs b/src/cli/opts.rs index 8582995f9..3b5f955f9 100644 --- a/src/cli/opts.rs +++ b/src/cli/opts.rs @@ -25,6 +25,8 @@ use farcaster_core::{ swap::{btcxmr::PublicOffer, SwapId}, }; +use crate::bus::HealthCheckSelector; + /// Command-line tool for working with Farcaster node #[derive(Parser, Clone, PartialEq, Eq, Debug)] #[clap(name = "swap-cli", bin_name = "swap-cli", author, version)] @@ -111,7 +113,13 @@ pub enum Command { /// Checks the health of the syncers #[clap(aliases = &["hc"])] - HealthCheck, + HealthCheck { + #[clap( + default_value = "all", + possible_values = &["Mainnet", "mainnet", "Testnet", "testnet", "Local", "local", "all", "All"] + )] + selector: HealthCheckSelector, + }, /// Restores saved checkpoint of a swap #[clap(aliases = &["r"])] diff --git a/src/grpcd/proto/farcaster.proto b/src/grpcd/proto/farcaster.proto index bb58f039e..72030e479 100644 --- a/src/grpcd/proto/farcaster.proto +++ b/src/grpcd/proto/farcaster.proto @@ -23,16 +23,36 @@ service Farcaster { message HealthCheckRequest { uint32 id = 1; + HealthCheckSelector selector = 2; +} + +enum HealthCheckSelector { + CHECK_ALL = 0; + CHECK_MAINNET = 1; + CHECK_TESTNET = 2; + CHECK_LOCAL = 3; } message HealthCheckResponse { uint32 id = 1; + oneof health_report { + CompleteHealthReport complete_health_report = 2; + ReducedHealthReport reduced_health_report = 3; + } +} + +message CompleteHealthReport { string bitcoin_mainnet_health = 2; string bitcoin_testnet_health = 3; string bitcoin_local_health = 4; string monero_mainnet_health = 5; string monero_testnet_health = 6; - string monero_local_health = 7; + string monero_local_health = 7; +} + +message ReducedHealthReport { + string bitcoin_health = 2; + string monero_health = 7; } message InfoRequest { diff --git a/src/grpcd/runtime.rs b/src/grpcd/runtime.rs index 5c23dba40..bee9ceb88 100644 --- a/src/grpcd/runtime.rs +++ b/src/grpcd/runtime.rs @@ -7,6 +7,7 @@ use crate::bus::info::OfferStatusSelector; use crate::bus::info::ProgressEvent; use crate::bus::AddressSecretKey; use crate::bus::Failure; +use crate::bus::HealthCheckSelector; use crate::bus::OptionDetails; use crate::bus::Outcome; use crate::service::Endpoints; @@ -53,6 +54,7 @@ use self::farcaster::AbortSwapResponse; use self::farcaster::AddressSwapIdPair; use self::farcaster::CheckpointsRequest; use self::farcaster::CheckpointsResponse; +use self::farcaster::CompleteHealthReport; use self::farcaster::ConnectSwapRequest; use self::farcaster::ConnectSwapResponse; use self::farcaster::FundingAddressesRequest; @@ -71,6 +73,7 @@ use self::farcaster::PeersRequest; use self::farcaster::PeersResponse; use self::farcaster::ProgressRequest; use self::farcaster::ProgressResponse; +use self::farcaster::ReducedHealthReport; use self::farcaster::RestoreCheckpointRequest; use self::farcaster::RestoreCheckpointResponse; use self::farcaster::RevokeOfferRequest; @@ -321,6 +324,23 @@ impl From for farcaster::State { } } +impl From for HealthCheckSelector { + fn from(s: farcaster::HealthCheckSelector) -> Self { + match s { + farcaster::HealthCheckSelector::CheckAll => HealthCheckSelector::All, + farcaster::HealthCheckSelector::CheckLocal => { + HealthCheckSelector::Network(Network::Local) + } + farcaster::HealthCheckSelector::CheckMainnet => { + HealthCheckSelector::Network(Network::Mainnet) + } + farcaster::HealthCheckSelector::CheckTestnet => { + HealthCheckSelector::Network(Network::Testnet) + } + } + } +} + #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, PartialOrd, Hash, Display)] #[display(Debug)] pub struct IdCounter(u64); @@ -1062,99 +1082,158 @@ impl Farcaster for FarcasterService { &self, request: GrpcRequest, ) -> Result, Status> { - let oneshot_rx = self - .process_request(BusMsg::Bridge(BridgeMsg::Ctl { - request: CtlMsg::HealthCheck(Blockchain::Bitcoin, Network::Testnet), - service_id: ServiceId::Farcasterd, - })) - .await?; + let HealthCheckRequest { + id, + selector: grpc_selector, + } = request.into_inner(); - let bitcoin_testnet_health = match oneshot_rx.await { - Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, - _ => { - return Err(Status::internal("Error during health check".to_string())); - } - }; + let selector: HealthCheckSelector = farcaster::HealthCheckSelector::from_i32(grpc_selector) + .ok_or(Status::invalid_argument("selector"))? + .into(); - let oneshot_rx = self - .process_request(BusMsg::Bridge(BridgeMsg::Ctl { - request: CtlMsg::HealthCheck(Blockchain::Bitcoin, Network::Mainnet), - service_id: ServiceId::Farcasterd, - })) - .await?; + match selector { + HealthCheckSelector::Network(network) => { + let oneshot_rx = self + .process_request(BusMsg::Bridge(BridgeMsg::Ctl { + request: CtlMsg::HealthCheck(Blockchain::Bitcoin, network), + service_id: ServiceId::Farcasterd, + })) + .await?; - let bitcoin_mainnet_health = match oneshot_rx.await { - Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, - _ => { - return Err(Status::internal("Error during health check".to_string())); - } - }; + let bitcoin_health = match oneshot_rx.await { + Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, + _ => { + return Err(Status::internal("Error during health check".to_string())); + } + }; - let oneshot_rx = self - .process_request(BusMsg::Bridge(BridgeMsg::Ctl { - request: CtlMsg::HealthCheck(Blockchain::Bitcoin, Network::Local), - service_id: ServiceId::Farcasterd, - })) - .await?; + let oneshot_rx = self + .process_request(BusMsg::Bridge(BridgeMsg::Ctl { + request: CtlMsg::HealthCheck(Blockchain::Monero, network), + service_id: ServiceId::Farcasterd, + })) + .await?; - let bitcoin_local_health = match oneshot_rx.await { - Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, - _ => { - return Err(Status::internal("Error during health check".to_string())); + let monero_health = match oneshot_rx.await { + Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, + _ => { + return Err(Status::internal("Error during health check".to_string())); + } + }; + Ok(GrpcResponse::new(HealthCheckResponse { + id, + health_report: Some( + farcaster::health_check_response::HealthReport::ReducedHealthReport( + ReducedHealthReport { + bitcoin_health: bitcoin_health.to_string(), + monero_health: monero_health.to_string(), + }, + ), + ), + })) } - }; + HealthCheckSelector::All => { + let oneshot_rx = self + .process_request(BusMsg::Bridge(BridgeMsg::Ctl { + request: CtlMsg::HealthCheck(Blockchain::Bitcoin, Network::Testnet), + service_id: ServiceId::Farcasterd, + })) + .await?; - let oneshot_rx = self - .process_request(BusMsg::Bridge(BridgeMsg::Ctl { - request: CtlMsg::HealthCheck(Blockchain::Monero, Network::Testnet), - service_id: ServiceId::Farcasterd, - })) - .await?; + let bitcoin_testnet_health = match oneshot_rx.await { + Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, + _ => { + return Err(Status::internal("Error during health check".to_string())); + } + }; - let monero_testnet_health = match oneshot_rx.await { - Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, - _ => { - return Err(Status::internal("Error during health check".to_string())); - } - }; + let oneshot_rx = self + .process_request(BusMsg::Bridge(BridgeMsg::Ctl { + request: CtlMsg::HealthCheck(Blockchain::Bitcoin, Network::Mainnet), + service_id: ServiceId::Farcasterd, + })) + .await?; - let oneshot_rx = self - .process_request(BusMsg::Bridge(BridgeMsg::Ctl { - request: CtlMsg::HealthCheck(Blockchain::Monero, Network::Mainnet), - service_id: ServiceId::Farcasterd, - })) - .await?; + let bitcoin_mainnet_health = match oneshot_rx.await { + Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, + _ => { + return Err(Status::internal("Error during health check".to_string())); + } + }; - let monero_mainnet_health = match oneshot_rx.await { - Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, - _ => { - return Err(Status::internal("Error during health check".to_string())); - } - }; + let oneshot_rx = self + .process_request(BusMsg::Bridge(BridgeMsg::Ctl { + request: CtlMsg::HealthCheck(Blockchain::Bitcoin, Network::Local), + service_id: ServiceId::Farcasterd, + })) + .await?; - let oneshot_rx = self - .process_request(BusMsg::Bridge(BridgeMsg::Ctl { - request: CtlMsg::HealthCheck(Blockchain::Monero, Network::Local), - service_id: ServiceId::Farcasterd, - })) - .await?; + let bitcoin_local_health = match oneshot_rx.await { + Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, + _ => { + return Err(Status::internal("Error during health check".to_string())); + } + }; - let monero_local_health = match oneshot_rx.await { - Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, - _ => { - return Err(Status::internal("Error during health check".to_string())); - } - }; + let oneshot_rx = self + .process_request(BusMsg::Bridge(BridgeMsg::Ctl { + request: CtlMsg::HealthCheck(Blockchain::Monero, Network::Testnet), + service_id: ServiceId::Farcasterd, + })) + .await?; + + let monero_testnet_health = match oneshot_rx.await { + Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, + _ => { + return Err(Status::internal("Error during health check".to_string())); + } + }; + + let oneshot_rx = self + .process_request(BusMsg::Bridge(BridgeMsg::Ctl { + request: CtlMsg::HealthCheck(Blockchain::Monero, Network::Mainnet), + service_id: ServiceId::Farcasterd, + })) + .await?; + + let monero_mainnet_health = match oneshot_rx.await { + Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, + _ => { + return Err(Status::internal("Error during health check".to_string())); + } + }; - Ok(GrpcResponse::new(HealthCheckResponse { - id: request.into_inner().id, - bitcoin_mainnet_health: bitcoin_mainnet_health.to_string(), - bitcoin_testnet_health: bitcoin_testnet_health.to_string(), - bitcoin_local_health: bitcoin_local_health.to_string(), - monero_mainnet_health: monero_mainnet_health.to_string(), - monero_testnet_health: monero_testnet_health.to_string(), - monero_local_health: monero_local_health.to_string(), - })) + let oneshot_rx = self + .process_request(BusMsg::Bridge(BridgeMsg::Ctl { + request: CtlMsg::HealthCheck(Blockchain::Monero, Network::Local), + service_id: ServiceId::Farcasterd, + })) + .await?; + + let monero_local_health = match oneshot_rx.await { + Ok(BusMsg::Ctl(CtlMsg::HealthResult(health))) => health, + _ => { + return Err(Status::internal("Error during health check".to_string())); + } + }; + + Ok(GrpcResponse::new(HealthCheckResponse { + id, + health_report: Some( + farcaster::health_check_response::HealthReport::CompleteHealthReport( + CompleteHealthReport { + bitcoin_mainnet_health: bitcoin_mainnet_health.to_string(), + bitcoin_testnet_health: bitcoin_testnet_health.to_string(), + bitcoin_local_health: bitcoin_local_health.to_string(), + monero_mainnet_health: monero_mainnet_health.to_string(), + monero_testnet_health: monero_testnet_health.to_string(), + monero_local_health: monero_local_health.to_string(), + }, + ), + ), + })) + } + } } async fn sweep_address( From 0ac01903651f636e4efd11f6486b06c97e8db361 Mon Sep 17 00:00:00 2001 From: h4sh3d Date: Tue, 6 Dec 2022 17:08:11 +0100 Subject: [PATCH 2/2] fix: update default node to rino, outreach fails to connect --- farcasterd.toml | 2 +- src/config.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/farcasterd.toml b/farcasterd.toml index 5de04c7fb..2c959c690 100644 --- a/farcasterd.toml +++ b/farcasterd.toml @@ -51,7 +51,7 @@ bind_ip = "127.0.0.1" # Electrum Server used by the Bitcoin syncer electrum_server = "ssl://blockstream.info:700" # Monero daemon used by the Monero syncer -monero_daemon = "http://node.monerooutreach.org:18081" +monero_daemon = "http://node.community.rino.io:18081" # Monero Wallet RPC used by the Monero syncer # Point to local running wallet monero_rpc_wallet = "http://localhost:18083" diff --git a/src/config.rs b/src/config.rs index ce6fbc5e7..fb4291040 100644 --- a/src/config.rs +++ b/src/config.rs @@ -21,7 +21,7 @@ use std::path::Path; use serde::{Deserialize, Serialize}; pub const FARCASTER_MAINNET_ELECTRUM_SERVER: &str = "ssl://blockstream.info:700"; -pub const FARCASTER_MAINNET_MONERO_DAEMON: &str = "http://node.monerooutreach.org:18081"; +pub const FARCASTER_MAINNET_MONERO_DAEMON: &str = "http://node.community.rino.io:18081"; pub const FARCASTER_MAINNET_MONERO_RPC_WALLET: &str = "http://localhost:18083"; pub const FARCASTER_TESTNET_ELECTRUM_SERVER: &str = "ssl://blockstream.info:993";