From 1548aa3473e42e3f13e6ce20878898220104413c Mon Sep 17 00:00:00 2001 From: hinto-janaiyo Date: Sat, 28 Jan 2023 20:57:12 -0500 Subject: [PATCH] Add GitHub Actions --- .github/workflows/linux-build.yml | 32 +++++++ .github/workflows/linux-test.yml | 32 +++++++ .github/workflows/macos-build.yml | 28 ++++++ .github/workflows/macos-test.yml | 28 ++++++ .github/workflows/ping.yml | 27 ++++++ .github/workflows/windows-build.yml | 28 ++++++ .github/workflows/windows-test.yml | 28 ++++++ CHANGELOG.md | 2 +- Cargo.lock | 12 +-- README.md | 8 +- src/node.rs | 140 ++++++++++++++++++---------- 11 files changed, 307 insertions(+), 58 deletions(-) create mode 100644 .github/workflows/linux-build.yml create mode 100644 .github/workflows/linux-test.yml create mode 100644 .github/workflows/macos-build.yml create mode 100644 .github/workflows/macos-test.yml create mode 100644 .github/workflows/ping.yml create mode 100644 .github/workflows/windows-build.yml create mode 100644 .github/workflows/windows-test.yml diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml new file mode 100644 index 0000000..3f2ccbf --- /dev/null +++ b/.github/workflows/linux-build.yml @@ -0,0 +1,32 @@ +name: Linux Build + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - name: Cache + uses: actions/cache@v3.2.3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: linux cargo build + - uses: actions/checkout@v3 + - name: Install dependencies + run: | + sudo apt update + sudo apt install -y libgtk-3-dev + - name: Build + run: cargo build diff --git a/.github/workflows/linux-test.yml b/.github/workflows/linux-test.yml new file mode 100644 index 0000000..d210b8a --- /dev/null +++ b/.github/workflows/linux-test.yml @@ -0,0 +1,32 @@ +name: Linux Tests + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - name: Cache + uses: actions/cache@v3.2.3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: linux cargo test + - uses: actions/checkout@v3 + - name: Install dependencies + run: | + sudo apt update + sudo apt install -y libgtk-3-dev + - name: Test + run: cargo test diff --git a/.github/workflows/macos-build.yml b/.github/workflows/macos-build.yml new file mode 100644 index 0000000..63558e4 --- /dev/null +++ b/.github/workflows/macos-build.yml @@ -0,0 +1,28 @@ +name: macOS Build + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: macos-latest + + steps: + - name: Cache + uses: actions/cache@v3.2.3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: macos cargo build + - uses: actions/checkout@v3 + - name: Build + run: cargo build diff --git a/.github/workflows/macos-test.yml b/.github/workflows/macos-test.yml new file mode 100644 index 0000000..859121b --- /dev/null +++ b/.github/workflows/macos-test.yml @@ -0,0 +1,28 @@ +name: macOS Tests + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: macos-latest + + steps: + - name: Cache + uses: actions/cache@v3.2.3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: macos cargo test + - uses: actions/checkout@v3 + - name: Test + run: cargo test diff --git a/.github/workflows/ping.yml b/.github/workflows/ping.yml new file mode 100644 index 0000000..e0fea88 --- /dev/null +++ b/.github/workflows/ping.yml @@ -0,0 +1,27 @@ +# This uses the unit test in the [node.rs] file to ping all REMOTE_NODES +# and attempts to serialize their JSON data to make sure they are working. + +name: Daily Remote Node Ping +on: + schedule: + - cron: "0 4 * * *" + workflow_dispatch: +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Cache + uses: actions/cache@v3.2.3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ping + - uses: actions/checkout@v3 + - name: Install dependencies + run: | + sudo apt update + sudo apt install -y libgtk-3-dev + - name: Ping + run: cargo test -- --ignored --nocapture diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml new file mode 100644 index 0000000..c917818 --- /dev/null +++ b/.github/workflows/windows-build.yml @@ -0,0 +1,28 @@ +name: Windows Build + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: windows-latest + + steps: + - name: Cache + uses: actions/cache@v3.2.3 + with: + path: | + ~\.cargo\registry + ~\.cargo\git + target + key: windows cargo build + - uses: actions/checkout@v3 + - name: Build + run: cargo build diff --git a/.github/workflows/windows-test.yml b/.github/workflows/windows-test.yml new file mode 100644 index 0000000..9def36c --- /dev/null +++ b/.github/workflows/windows-test.yml @@ -0,0 +1,28 @@ +name: Windows Tests + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: windows-latest + + steps: + - name: Cache + uses: actions/cache@v3.2.3 + with: + path: | + ~\.cargo\registry + ~\.cargo\git + target + key: windows cargo test + - uses: actions/checkout@v3 + - name: Test + run: cargo test diff --git a/CHANGELOG.md b/CHANGELOG.md index 694d989..2b46ac0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ * **P2Pool:** Added warning in `[P2Pool Simple]` tab about privacy/practical downsides when using remote nodes; Hyperlinks to [Running a Local Monero Node](https://github.com/hinto-janaiyo/gupax#running-a-local-monero-node). ## Fixes -* **Ping:** Fixed ping end lag; Remote node pings are as fast as the slowest ping instead of always being 10 seconds flat +* **Ping:** Fixed ping end lag; Remote node pings are as fast as the slowest ping instead of always taking 10 seconds flat * **UI:** Top/Bottom bars are smaller, fixes some UI overflowing or being cramped ## Bundled Versions diff --git a/Cargo.lock b/Cargo.lock index 4c7e2fb..deb2839 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -468,9 +468,9 @@ checksum = "ceea694ffdf0118d2df95ace6fd9edfc6d27f88408d0d73b390f2d9e5699b3f2" [[package]] name = "cc" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -3398,9 +3398,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.8.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c4437699b6d34972de58652c68b98cb5b53a4199ab126db8e20ec8ded29a721" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation", @@ -4153,9 +4153,9 @@ checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" [[package]] name = "toml_edit" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729bfd096e40da9c001f778f5cdecbd2957929a24e10e5883d9392220a751581" +checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" dependencies = [ "indexmap", "nom8", diff --git a/README.md b/README.md index 31a6244..958d734 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,12 @@ Gupax is a (Windows|macOS|Linux) GUI for mining [**Monero**](https://github.com/ **To see a 3-minute video on how to download and run Gupax: [click here.](#How-To)** +![windows-build](https://github.com/hinto-janaiyo/gupax/actions/workflows/windows-build.yml/badge.svg) ![macos-build](https://github.com/hinto-janaiyo/gupax/actions/workflows/macos-build.yml/badge.svg) ![linux-build](https://github.com/hinto-janaiyo/gupax/actions/workflows/linux-build.yml/badge.svg) + +![windows-test](https://github.com/hinto-janaiyo/gupax/actions/workflows/windows-test.yml/badge.svg) ![macos-test](https://github.com/hinto-janaiyo/gupax/actions/workflows/macos-test.yml/badge.svg) ![linux-test](https://github.com/hinto-janaiyo/gupax/actions/workflows/linux-test.yml/badge.svg) + +![daily-ping](https://github.com/hinto-janaiyo/gupax/actions/workflows/ping.yml/badge.svg) + ## Contents @@ -557,13 +563,11 @@ These are the remote nodes used by Gupax in the `[P2Pool Simple]` tab. They are | reynald.ro | ๐Ÿ‡ซ๐Ÿ‡ท FR - รŽle-de-France | 18089 | 18084 | | node2.monerodevs.org | ๐Ÿ‡ซ๐Ÿ‡ท FR - Occitanie | 18089 | 18084 | | monero.homeqloud.com | ๐Ÿ‡ฌ๐Ÿ‡ท GR - East Macedonia and Thrace | 18089 | 18083 | -| home.allantaylor.kiwi | ๐Ÿ‡ณ๐Ÿ‡ฟ NZ - Canterbury | 18089 | 18083 | | ru.poiuty.com | ๐Ÿ‡ท๐Ÿ‡บ RU - Kuzbass | 18081 | 18084 | | radishfields.hopto.org | ๐Ÿ‡บ๐Ÿ‡ธ US - Colorado | 18081 | 18084 | | xmrbandwagon.hopto.org | ๐Ÿ‡บ๐Ÿ‡ธ US - Colorado | 18081 | 18084 | | xmr.spotlightsound.com | ๐Ÿ‡บ๐Ÿ‡ธ US - Kansas | 18081 | 18084 | | xmrnode.facspro.net | ๐Ÿ‡บ๐Ÿ‡ธ US - Nebraska | 18089 | 18084 | -| jameswillhoite.com | ๐Ÿ‡บ๐Ÿ‡ธ US - Ohio | 18089 | 18084 | | moneronode.ddns.net | ๐Ÿ‡บ๐Ÿ‡ธ US - Pennsylvania | 18089 | 18084 | | node.richfowler.net | ๐Ÿ‡บ๐Ÿ‡ธ US - Pennsylvania | 18089 | 18084 | | bunkernet.ddns.net | ๐Ÿ‡ฟ๐Ÿ‡ฆ ZA - Western Cape | 18089 | 18084 | diff --git a/src/node.rs b/src/node.rs index 75d5338..89cde1e 100644 --- a/src/node.rs +++ b/src/node.rs @@ -32,38 +32,35 @@ use hyper::{ //---------------------------------------------------------------------------------------------------- Node list // Remote Monero Nodes with ZMQ enabled, sourced from: [https://github.com/hinto-janaiyo/monero-nodes] -// The format is an array of tuples consisting of: (ARRAY_INDEX, IP, LOCATION, RPC_PORT, ZMQ_PORT) +// The format is an array of tuples consisting of: (IP, LOCATION, RPC_PORT, ZMQ_PORT) -pub const REMOTE_NODES: [(usize, &str, &str, &str, &str); 22] = [ - (0, "monero.10z.com.ar", "AR - Buenos Aires F.D.", "18089", "18084"), - (1, "escom.sadovo.com", "BG - Plovdiv", "18089", "18084"), - (2, "monero2.10z.com.ar", "BR - Sรฃo Paulo", "18089", "18083"), - (3, "monero1.heitechsoft.com", "CA - Ontario", "18081", "18084"), - (4, "node.monerodevs.org", "CA - Quebec", "18089", "18084"), - (5, "de.poiuty.com", "DE - Berlin", "18081", "18084"), - (6, "m1.poiuty.com", "DE - Berlin", "18081", "18084"), - (7, "p2pmd.xmrvsbeast.com", "DE - Hesse", "18081", "18083"), - (8, "fbx.tranbert.com", "FR - รŽle-de-France", "18089", "18084"), - (9, "reynald.ro", "FR - รŽle-de-France", "18089", "18084"), - (10, "node2.monerodevs.org", "FR - Occitanie", "18089", "18084"), - (11, "monero.homeqloud.com", "GR - East Macedonia and Thrace", "18089", "18083"), - (12, "home.allantaylor.kiwi", "NZ - Canterbury", "18089", "18083"), - (13, "ru.poiuty.com", "RU - Kuzbass", "18081", "18084"), - (14, "radishfields.hopto.org", "US - Colorado", "18081", "18084"), - (15, "xmrbandwagon.hopto.org", "US - Colorado", "18081", "18084"), - (16, "xmr.spotlightsound.com", "US - Kansas", "18081", "18084"), - (17, "xmrnode.facspro.net", "US - Nebraska", "18089", "18084"), - (18, "jameswillhoite.com", "US - Ohio", "18089", "18084"), - (19, "moneronode.ddns.net", "US - Pennsylvania", "18089", "18084"), - (20, "node.richfowler.net", "US - Pennsylvania", "18089", "18084"), - (21, "bunkernet.ddns.net", "ZA - Western Cape", "18089", "18084"), +pub const REMOTE_NODES: [(&str, &str, &str, &str); 20] = [ + ("monero.10z.com.ar", "AR - Buenos Aires F.D.", "18089", "18084"), + ("escom.sadovo.com", "BG - Plovdiv", "18089", "18084"), + ("monero2.10z.com.ar", "BR - Sรฃo Paulo", "18089", "18083"), + ("monero1.heitechsoft.com", "CA - Ontario", "18081", "18084"), + ("node.monerodevs.org", "CA - Quebec", "18089", "18084"), + ("de.poiuty.com", "DE - Berlin", "18081", "18084"), + ("m1.poiuty.com", "DE - Berlin", "18081", "18084"), + ("p2pmd.xmrvsbeast.com", "DE - Hesse", "18081", "18083"), + ("fbx.tranbert.com", "FR - รŽle-de-France", "18089", "18084"), + ("reynald.ro", "FR - รŽle-de-France", "18089", "18084"), + ("node2.monerodevs.org", "FR - Occitanie", "18089", "18084"), + ("monero.homeqloud.com", "GR - East Macedonia and Thrace", "18089", "18083"), + ("ru.poiuty.com", "RU - Kuzbass", "18081", "18084"), + ("radishfields.hopto.org", "US - Colorado", "18081", "18084"), + ("xmrbandwagon.hopto.org", "US - Colorado", "18081", "18084"), + ("xmr.spotlightsound.com", "US - Kansas", "18081", "18084"), + ("xmrnode.facspro.net", "US - Nebraska", "18089", "18084"), + ("moneronode.ddns.net", "US - Pennsylvania", "18089", "18084"), + ("node.richfowler.net", "US - Pennsylvania", "18089", "18084"), + ("bunkernet.ddns.net", "ZA - Western Cape", "18089", "18084"), ]; pub const REMOTE_NODE_LENGTH: usize = REMOTE_NODES.len(); pub const REMOTE_NODE_MAX_CHARS: usize = 24; // monero1.heitechsoft.com pub struct RemoteNode { - pub index: usize, pub ip: &'static str, pub location: &'static str, pub rpc: &'static str, @@ -78,9 +75,8 @@ impl Default for RemoteNode { impl RemoteNode { pub fn new() -> Self { - let (index, ip, location, rpc, zmq) = REMOTE_NODES[0]; + let (ip, location, rpc, zmq) = REMOTE_NODES[0]; Self { - index, ip, location, rpc, @@ -89,22 +85,22 @@ impl RemoteNode { } pub fn check_exists(og_ip: &str) -> String { - for (_, ip, _, _, _) in REMOTE_NODES { + for (ip, _, _, _) in REMOTE_NODES { if og_ip == ip { info!("Found remote node in array: {}", ip); return ip.to_string() } } - let ip = REMOTE_NODES[0].1.to_string(); + let ip = REMOTE_NODES[0].0.to_string(); warn!("[{}] remote node does not exist, returning default: {}", og_ip, ip); ip } // Returns a default if IP is not found. pub fn from_ip(from_ip: &str) -> Self { - for (index, ip, location, rpc, zmq) in REMOTE_NODES { + for (ip, location, rpc, zmq) in REMOTE_NODES { if from_ip == ip { - return Self { index, ip, location, rpc, zmq } + return Self { ip, location, rpc, zmq } } } Self::new() @@ -115,31 +111,31 @@ impl RemoteNode { if index > REMOTE_NODE_LENGTH { Self::new() } else { - let (index, ip, location, rpc, zmq) = REMOTE_NODES[index]; - Self { index, ip, location, rpc, zmq } + let (ip, location, rpc, zmq) = REMOTE_NODES[index]; + Self { ip, location, rpc, zmq } } } - pub fn from_tuple(t: (usize, &'static str, &'static str, &'static str, &'static str)) -> Self { - let (index, ip, location, rpc, zmq) = (t.0, t.1, t.2, t.3, t.4); - Self { index, ip, location, rpc, zmq } + pub fn from_tuple(t: (&'static str, &'static str, &'static str, &'static str)) -> Self { + let (ip, location, rpc, zmq) = (t.0, t.1, t.2, t.3); + Self { ip, location, rpc, zmq } } pub fn get_ip_rpc_zmq(og_ip: &str) -> (&str, &str, &str) { - for (_, ip, _, rpc, zmq) in REMOTE_NODES { + for (ip, _, rpc, zmq) in REMOTE_NODES { if og_ip == ip { return (ip, rpc, zmq) } } - let (_, ip, _, rpc, zmq) = REMOTE_NODES[0]; + let (ip, _, rpc, zmq) = REMOTE_NODES[0]; (ip, rpc, zmq) } // Return a random node (that isn't the one already selected). pub fn get_random(current_ip: &str) -> String { let mut rng = thread_rng().gen_range(0..REMOTE_NODE_LENGTH); - let mut node = REMOTE_NODES[rng].1; + let mut node = REMOTE_NODES[rng].0; while current_ip == node { rng = thread_rng().gen_range(0..REMOTE_NODE_LENGTH); - node = REMOTE_NODES[rng].1; + node = REMOTE_NODES[rng].0; } node.to_string() } @@ -148,7 +144,7 @@ impl RemoteNode { pub fn get_last(current_ip: &str) -> String { let mut found = false; let mut last = current_ip; - for (_, ip, _, _, _) in REMOTE_NODES { + for (ip, _, _, _) in REMOTE_NODES { if found { return ip.to_string() } if current_ip == ip { found = true; } else { last = ip; } } @@ -158,7 +154,7 @@ impl RemoteNode { // Return the node [+1] of this one pub fn get_next(current_ip: &str) -> String { let mut found = false; - for (_, ip, _, _, _) in REMOTE_NODES { + for (ip, _, _, _) in REMOTE_NODES { if found { return ip.to_string() } if current_ip == ip { found = true; } } @@ -206,7 +202,7 @@ pub fn format_ms(ms: u128) -> String { // format_ip_location(monero1.heitechsoft.com) -> "monero1.heitechsoft.com | XX - LOCATION" // [extra_space] controls whether extra space is appended so the list aligns. pub fn format_ip_location(og_ip: &str, extra_space: bool) -> String { - for (_, ip, location, _, _) in REMOTE_NODES { + for (ip, location, _, _) in REMOTE_NODES { if og_ip == ip { let ip = if extra_space { format_ip(ip) } else { ip.to_string() }; return format!("{} | {}", ip, location) @@ -255,7 +251,7 @@ pub struct NodeData { impl NodeData { pub fn new_vec() -> Vec { let mut vec = Vec::new(); - for (_, ip, _, _, _) in REMOTE_NODES { + for (ip, _, _, _) in REMOTE_NODES { vec.push(Self { ip, ms: 0, @@ -288,7 +284,7 @@ impl Ping { pub fn new() -> Self { Self { nodes: NodeData::new_vec(), - fastest: REMOTE_NODES[0].1, + fastest: REMOTE_NODES[0].0, pinging: false, msg: "No ping in progress".to_string(), prog: 0.0, @@ -360,7 +356,7 @@ impl Ping { let mut handles = Vec::with_capacity(REMOTE_NODE_LENGTH); let node_vec = arc_mut!(Vec::with_capacity(REMOTE_NODE_LENGTH)); - for (_, ip, _, rpc, zmq) in REMOTE_NODES { + for (ip, _, rpc, zmq) in REMOTE_NODES { let client = client.clone(); let ping = Arc::clone(&ping); let node_vec = Arc::clone(&node_vec); @@ -430,17 +426,63 @@ impl Ping { mod test { #[test] fn validate_node_ips() { - for (_, ip, _, _, _) in crate::REMOTE_NODES { + for (ip, location, rpc, zmq) in crate::REMOTE_NODES { assert!(ip.len() < 255); assert!(ip.is_ascii()); - assert!(ip.ends_with(":18081") || ip.ends_with(":18089")); + assert!(!location.is_empty()); + assert!(!ip.is_empty()); + assert!(rpc == "18081" || rpc == "18089"); + assert!(zmq == "18083" || zmq == "18084"); } } #[test] fn spacing() { - for (_, ip, _, _, _) in crate::REMOTE_NODES { + for (ip, _, _, _) in crate::REMOTE_NODES { assert!(crate::format_ip(ip).len() <= crate::REMOTE_NODE_MAX_CHARS); } } + + // This one pings the IPs defined in [REMOTE_NODES] and fully serializes the JSON data to make sure they work. + // This will only be ran with be ran with [cargo test -- --ignored]. + #[tokio::test] + #[ignore] + async fn full_ping() { + use hyper::{ + client::HttpConnector, + Client,Body,Request, + }; + use crate::{REMOTE_NODES,REMOTE_NODE_LENGTH}; + use serde::{Serialize,Deserialize}; + + #[derive(Deserialize,Serialize)] + struct GetInfo { + id: String, + jsonrpc: String, + } + + // Create HTTP client + let client: Client = Client::builder().build(HttpConnector::new()); + + // Random User Agent + let rand_user_agent = crate::Pkg::get_user_agent(); + + let mut n = 1; + for (ip, _, rpc, zmq) in REMOTE_NODES { + println!("[{}/{}] {} | {} | {}", n, REMOTE_NODE_LENGTH, ip, rpc, zmq); + let client = client.clone(); + let request = Request::builder() + .method("POST") + .uri("http://".to_string() + ip + ":" + rpc + "/json_rpc") + .header("User-Agent", rand_user_agent) + .body(hyper::Body::from(r#"{"jsonrpc":"2.0","id":"0","method":"get_info"}"#)) + .unwrap(); + let mut response = client.request(request).await.unwrap(); + let body = hyper::body::to_bytes(response.body_mut()).await.unwrap(); + let getinfo: GetInfo = serde_json::from_slice(&body).unwrap(); + assert!(getinfo.id == "0"); + assert!(getinfo.jsonrpc == "2.0"); + n += 1; + } + } }