From c4d534ec98e6c968feee74ffdfc7c980a2c3a165 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Thu, 13 Jul 2023 11:45:04 -0400 Subject: [PATCH] impl backup hosts --- src/constants.rs | 7 +++++-- src/disk.rs | 2 ++ src/helper.rs | 45 ++++++++++++++++++++++++++++++++++++++++----- src/main.rs | 44 +++++++++++++++++++++++++++++++++++++++++--- src/p2pool.rs | 16 ++++++++++++++-- 5 files changed, 102 insertions(+), 12 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index fc31324..edf61c3 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -272,6 +272,7 @@ pub const P2POOL_IN: &str = "How many in-bound peers to allow? (othe pub const P2POOL_LOG: &str = "Verbosity of the console log"; pub const P2POOL_AUTO_NODE: &str = "Automatically ping the remote Monero nodes at Gupax startup"; pub const P2POOL_AUTO_SELECT: &str = "Automatically select the fastest remote Monero node after pinging"; +pub const P2POOL_BACKUP_HOST: &str = "Automatically switch to the other nodes listed if the current one is down"; pub const P2POOL_SELECT_FASTEST: &str = "Select the fastest remote Monero node"; pub const P2POOL_SELECT_RANDOM: &str = "Select a random remote Monero node"; pub const P2POOL_SELECT_LAST: &str = "Select the previous remote Monero node"; @@ -297,7 +298,8 @@ Start P2Pool with these arguments and override all below settings"#; pub const P2POOL_SIMPLE: &str = r#"Use simple P2Pool settings: - Remote remote Monero node - - Default P2Pool settings + Mini"#; + - Default P2Pool settings + Mini + - Backup host setting"#; pub const P2POOL_ADVANCED: &str = r#"Use advanced P2Pool settings: - Terminal input @@ -305,7 +307,8 @@ r#"Use advanced P2Pool settings: - Manual node list - P2Pool Main/Mini selection - Out/In peer setting - - Log level setting"#; + - Log level setting + - Backup host setting"#; pub const P2POOL_NAME: &str = "Add a unique name to identify this node; Only [A-Za-z0-9-_.] and spaces allowed; Max length = 30 characters"; pub const P2POOL_NODE_IP: &str = "Specify the Monero Node IP to connect to with P2Pool; It must be a valid IPv4 address or a valid domain name; Max length = 255 characters"; pub const P2POOL_RPC_PORT: &str = "Specify the RPC port of the Monero node; [1-65535]"; diff --git a/src/disk.rs b/src/disk.rs index 0ebbcb6..9d0ed86 100644 --- a/src/disk.rs +++ b/src/disk.rs @@ -1016,6 +1016,7 @@ pub struct P2pool { pub simple: bool, pub mini: bool, pub auto_ping: bool, + pub backup_host: bool, pub auto_select: bool, pub out_peers: u16, pub in_peers: u16, @@ -1108,6 +1109,7 @@ impl Default for P2pool { mini: true, auto_ping: true, auto_select: true, + backup_host: true, out_peers: 10, in_peers: 10, log_level: 3, diff --git a/src/helper.rs b/src/helper.rs index c74c700..ababd9b 100644 --- a/src/helper.rs +++ b/src/helper.rs @@ -328,7 +328,7 @@ impl Helper { // The "restart frontend" to a "frontend" function. // Basically calls to kill the current p2pool, waits a little, then starts the below function in a a new thread, then exit. - pub fn restart_p2pool(helper: &Arc>, state: &crate::disk::P2pool, path: &std::path::PathBuf) { + pub fn restart_p2pool(helper: &Arc>, state: &crate::disk::P2pool, path: &std::path::PathBuf, backup_hosts: Option>) { info!("P2Pool | Attempting to restart..."); lock2!(helper,p2pool).signal = ProcessSignal::Restart; lock2!(helper,p2pool).state = ProcessState::Middle; @@ -344,16 +344,21 @@ impl Helper { } // Ok, process is not alive, start the new one! info!("P2Pool | Old process seems dead, starting new one!"); - Self::start_p2pool(&helper, &state, &path); + Self::start_p2pool(&helper, &state, &path, backup_hosts); }); info!("P2Pool | Restart ... OK"); } // The "frontend" function that parses the arguments, and spawns either the [Simple] or [Advanced] P2Pool watchdog thread. - pub fn start_p2pool(helper: &Arc>, state: &crate::disk::P2pool, path: &std::path::PathBuf) { + pub fn start_p2pool( + helper: &Arc>, + state: &crate::disk::P2pool, + path: &std::path::PathBuf, + backup_hosts: Option>, + ) { lock2!(helper,p2pool).state = ProcessState::Middle; - let (args, api_path_local, api_path_network, api_path_pool) = Self::build_p2pool_args_and_mutate_img(helper, state, path); + let (args, api_path_local, api_path_network, api_path_pool) = Self::build_p2pool_args_and_mutate_img(helper, state, path, backup_hosts); // Print arguments & user settings to console crate::disk::print_dash(&format!( @@ -387,7 +392,12 @@ impl Helper { // Takes in some [State/P2pool] and parses it to build the actual command arguments. // Returns the [Vec] of actual arguments, and mutates the [ImgP2pool] for the main GUI thread // It returns a value... and mutates a deeply nested passed argument... this is some pretty bad code... - pub fn build_p2pool_args_and_mutate_img(helper: &Arc>, state: &crate::disk::P2pool, path: &std::path::PathBuf) -> (Vec, PathBuf, PathBuf, PathBuf) { + pub fn build_p2pool_args_and_mutate_img( + helper: &Arc>, + state: &crate::disk::P2pool, + path: &std::path::PathBuf, + backup_hosts: Option>, + ) -> (Vec, PathBuf, PathBuf, PathBuf) { let mut args = Vec::with_capacity(500); let path = path.clone(); let mut api_path = path; @@ -406,6 +416,18 @@ impl Helper { args.push("--no-color".to_string()); // Remove color escape sequences, Gupax terminal can't parse it :( args.push("--mini".to_string()); // P2Pool Mini args.push("--light-mode".to_string()); // Assume user is not using P2Pool to mine. + + // Push other nodes if `backup_host`. + if let Some(nodes) = backup_hosts { + for node in nodes { + if (node.ip.as_str(), node.rpc.as_str(), node.zmq.as_str()) != (ip, rpc, zmq) { + args.push("--host".to_string()); args.push(node.ip.to_string()); + args.push("--rpc-port".to_string()); args.push(node.rpc.to_string()); + args.push("--zmq-port".to_string()); args.push(node.zmq.to_string()); + } + } + } + *lock2!(helper,img_p2pool) = ImgP2pool { mini: "P2Pool Mini".to_string(), address: Self::head_tail_of_monero_address(&state.address), @@ -458,6 +480,19 @@ impl Helper { args.push("--no-color".to_string()); // Remove color escape sequences args.push("--light-mode".to_string()); // Assume user is not using P2Pool to mine. if state.mini { args.push("--mini".to_string()); }; // Mini + + // Push other nodes if `backup_host`. + if let Some(nodes) = backup_hosts { + for node in nodes { + let ip = if node.ip == "localhost" { "127.0.0.1" } else { &node.ip }; + if (node.ip.as_str(), node.rpc.as_str(), node.zmq.as_str()) != (ip, &state.rpc, &state.zmq) { + args.push("--host".to_string()); args.push(node.ip.to_string()); + args.push("--rpc-port".to_string()); args.push(node.rpc.to_string()); + args.push("--zmq-port".to_string()); args.push(node.zmq.to_string()); + } + } + } + *lock2!(helper,img_p2pool) = ImgP2pool { mini: if state.mini { "P2Pool Mini".to_string() } else { "P2Pool Main".to_string() }, address: Self::head_tail_of_monero_address(&state.address), diff --git a/src/main.rs b/src/main.rs index 788bf47..a635436 100644 --- a/src/main.rs +++ b/src/main.rs @@ -527,6 +527,43 @@ impl App { info!("App ... OK"); app } + + pub fn gather_backup_hosts(&self) -> Option> { + if !self.state.p2pool.backup_host { + return None; + } + + if self.state.p2pool.simple { + let mut ip = lock!(self.ping).fastest.to_string(); + + let mut vec = Vec::with_capacity(REMOTE_NODES.len()); + + for _ in 0..REMOTE_NODES.len() { + let (ip_new, rpc, zmq) = RemoteNode::get_ip_rpc_zmq(&ip); + + let node = Node { + ip: ip_new.into(), + rpc: rpc.into(), + zmq: zmq.into(), + }; + + vec.push(node); + ip = RemoteNode::get_next_from_ping(ip_new, &lock!(self.ping).nodes); + } + + return Some(vec); + } + + if !self.state.p2pool.simple { + return Some(self.node_vec + .iter() + .map(|(_, node)| node.clone()) + .collect() + ); + } + + None + } } //---------------------------------------------------------------------------------------------------- [Tab] Enum + Impl @@ -855,7 +892,8 @@ fn init_auto(app: &mut App) { } else if !crate::update::check_p2pool_path(&app.state.gupax.p2pool_path) { warn!("Gupax | P2Pool path is not valid! Skipping auto-p2pool..."); } else { - Helper::start_p2pool(&app.helper, &app.state.p2pool, &app.state.gupax.absolute_p2pool_path); + let backup_hosts = app.gather_backup_hosts(); + Helper::start_p2pool(&app.helper, &app.state.p2pool, &app.state.gupax.absolute_p2pool_path, backup_hosts); } } else { info!("Skipping auto-p2pool..."); @@ -1641,7 +1679,7 @@ impl eframe::App for App { if key.is_up() && !wants_input || ui.add_sized([width, height], Button::new("⟲")).on_hover_text("Restart P2Pool").clicked() { lock!(self.og).update_absolute_path(); self.state.update_absolute_path(); - Helper::restart_p2pool(&self.helper, &self.state.p2pool, &self.state.gupax.absolute_p2pool_path); + Helper::restart_p2pool(&self.helper, &self.state.p2pool, &self.state.gupax.absolute_p2pool_path, self.gather_backup_hosts()); } if key.is_down() && !wants_input || ui.add_sized([width, height], Button::new("⏹")).on_hover_text("Stop P2Pool").clicked() { Helper::stop_p2pool(&self.helper); @@ -1672,7 +1710,7 @@ impl eframe::App for App { if (ui_enabled && key.is_up() && !wants_input) || ui.add_sized([width, height], Button::new(RichText::new("▶").color(color))).on_hover_text("Start P2Pool").on_disabled_hover_text(text).clicked() { lock!(self.og).update_absolute_path(); self.state.update_absolute_path(); - Helper::start_p2pool(&self.helper, &self.state.p2pool, &self.state.gupax.absolute_p2pool_path); + Helper::start_p2pool(&self.helper, &self.state.p2pool, &self.state.gupax.absolute_p2pool_path, self.gather_backup_hosts()); } } }); diff --git a/src/p2pool.rs b/src/p2pool.rs index 8586b17..5420546 100644 --- a/src/p2pool.rs +++ b/src/p2pool.rs @@ -223,11 +223,15 @@ impl crate::disk::P2pool { debug!("P2Pool Tab | Rendering [Auto-*] buttons"); ui.group(|ui| { ui.horizontal(|ui| { - let width = (width/2.0)-(SPACE*1.75); - // [Auto-node] + [Auto-select] + let width = (width/3.0)-(SPACE*1.75); + // [Auto-node] ui.add_sized([width, height], Checkbox::new(&mut self.auto_select, "Auto-select")).on_hover_text(P2POOL_AUTO_SELECT); ui.separator(); + // [Auto-node] ui.add_sized([width, height], Checkbox::new(&mut self.auto_ping, "Auto-ping")).on_hover_text(P2POOL_AUTO_NODE); + ui.separator(); + // [Backup host] + ui.add_sized([width, height], Checkbox::new(&mut self.backup_host, "Backup host")).on_hover_text(P2POOL_BACKUP_HOST); })}); debug!("P2Pool Tab | Rendering warning text"); @@ -484,6 +488,14 @@ impl crate::disk::P2pool { }); })}); }); + + debug!("P2Pool Tab | Rendering Backup host button"); + ui.group(|ui| { + let width = width - SPACE; + let height = ui.available_height() / 3.0; + // [Backup host] + ui.add_sized([width, height], Checkbox::new(&mut self.backup_host, "Backup host")).on_hover_text(P2POOL_BACKUP_HOST); + }); } } }