From b3fbcf432d3287eb1bc1834a4ea36b82729d665f Mon Sep 17 00:00:00 2001
From: hinto-janaiyo <hinto.janaiyo@protonmail.com>
Date: Fri, 18 Nov 2022 21:47:14 -0500
Subject: [PATCH] Update CHANGELOG.md

---
 CHANGELOG.md  | 35 +++++++++++++++++++++++++++++++++++
 README.md     | 22 ++++++++++++++++++++++
 src/README.md | 43 ++++++++++++++++++++-----------------------
 src/node.rs   | 19 +++++++++++++++----
 4 files changed, 92 insertions(+), 27 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bae8bf7..b155358 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,38 @@
+## v0.2.0
+## Prototype Release
+* Added `Simple` P2Pool tab:
+	- Monero address input with valid address check (base58 regex)
+	- [Community Monero node selector](https://github.com/hinto-janaiyo/gupax/tree/main/README.md#community-monero-nodes) 
+	- Community node ping button (asynchronous `JSON-RPC` calls to all nodes)
+		- `<300ms = GREEN`
+		- `<1000ms = YELLOW`
+		- `<5000ms = RED`
+		- `>5000ms = BLACK`
+	- `Auto-select` - Pick the fastest node after ping automatically
+	- `Auto-ping` - Automatically ping nodes on Gupax startup
+* Added `Advanced` P2Pool tab:
+	- Overriding command arguments to P2Pool
+	- Manual node database, select/add/delete a custom `Name/IP/RPC/ZMQ` (max 1000 nodes)
+	- P2Pool main/mini toggle
+	- Out/In Peers slider
+	- Log level slider
+* Added command arguments:
+	- `-h | --help         Print this help message`
+	- `-v | --version      Print version and build info`
+	- `-l | --node-list    Print the manual node list`
+	- `-s | --state        Print Gupax state`
+	- `-n | --no-startup   Disable all auto-startup settings for this instance`
+	- `-r | --reset        Reset all Gupax state and the manual node list`
+	- `-f | --ferris       Print an extremely cute crab`
+* Added a native `File Explorer/Finder/GTK` file selector for picking P2Pool/XMRig binary path in `Gupax` tab
+* Added detailed console log levels `RUST_LOG=(trace|debug|info|warn|error) ./gupax`
+* [Added new PGP key](https://github.com/hinto-janaiyo/gupax/blob/main/pgp/hinto-janaiyo.asc)
+* Created website (HTML/CSS only, no JavaScript): https://gupax.io
+
+
+---
+
+
 ## v0.1.0
 ## Prototype Release
 * Added package updater (by default, via Tor using [`Arti`](https://blog.torproject.org/arti_100_released/))
diff --git a/README.md b/README.md
index 7d96f05..477fe06 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@
 
 ## Contents
 * [What is Monero, P2Pool, XMRig, and Gupax?](##what-is-monero-p2pool-xmrig-and-gupax)
+* [Community Monero Nodes](#community-monero-nodes)
 * [Demo](#Demo)
 * [Implementation](#Implementation)
 * [Planned](#Planned)
@@ -51,6 +52,27 @@ Both Monero and P2Pool have built in miners but XMRig is quite faster than both
 
 With Monero GUI managing the Monero node on one side and Gupax managing P2Pool/XMRig on the other, it is (hopefully) very easy for anyone to start mining Monero at **max hashrate in a decentralized, permissionless, and trustless manner**.
 
+## Community Monero Nodes
+| Name           | IP/Domain                        | RPC Port |
+|----------------|----------------------------------|----------|
+| C3pool         | node.c3pool.com                  | 18081    |
+| Cake           | xmr-node.cakewallet.com          | 18081    |
+| CakeEu         | xmr-node-eu.cakewallet.com       | 18081    |
+| CakeUk         | xmr-node-uk.cakewallet.com       | 18081    |
+| CakeUs         | xmr-node-usa-east.cakewallet.com | 18081    |
+| Feather1       | selsta1.featherwallet.net        | 18081    |
+| Feather2       | selsta2.featherwallet.net        | 18081    |
+| MajesticBankIs | node.majesticbank.is             | 18089    |
+| MajesticBankSu | node.majesticbank.su             | 18089    |
+| Monerujo       | nodex.monerujo.io                | 18081    |
+| Rino           | node.community.rino.io           | 18081    |
+| Seth           | node.sethforprivacy.com          | 18089    |
+| Singapore      | node.supportxmr.com              | 18081    |
+| SupportXmr     | node.supportxmr.ir               | 18081    |
+| SupportXmrIr   | singapore.node.xmr.pm            | 18089    |
+| XmrVsBeast     | p2pmd.xmrvsbeast.com             | 18081    |
+**Note: All have ZMQ port on 18083**
+
 ## Demo
 https://user-images.githubusercontent.com/101352116/194763334-d8e936c9-a71e-474e-ac65-3a339b96a9d2.mp4
 
diff --git a/src/README.md b/src/README.md
index 52f8f2b..9cb9e5b 100644
--- a/src/README.md
+++ b/src/README.md
@@ -8,11 +8,11 @@
 | File/Folder    | Purpose |
 |----------------|---------|
 | `constants.rs` | General constants needed in Gupax
-| `disk.rs`      | Code for writing to disk: `state.toml`, `nodes.toml`; This holds the structs for mutable [State]
-| `ferris.rs`    | Cute crab `--ferris`
+| `disk.rs`      | Code for writing to disk: `state.toml`, `node.toml`; This holds the structs for mutable [State]
+| `ferris.rs`    | Cute crab bytes
 | `gupax.rs`     | `Gupax` tab
-| `main.rs`      | `App/Tab/State` + misc functions
-| `node.rs`      | Community node feature
+| `main.rs`      | `App/Tab/State` + misc data/functions
+| `node.rs`      | Community node ping code for the `P2Pool` simple tab
 | `p2pool.rs`    | `P2Pool` tab
 | `status.rs`    | `Status` tab
 | `update.rs`    | Update code for the `Gupax` tab
@@ -22,29 +22,27 @@
 This is how Gupax works internally when starting up, divided into 3 sections.
 
 1. **INIT**
-	- Initialize custom console logging with `log`, `env_logger` || *warn!*
-	- Initialize misc data (structs, text styles, thread count, images, etc) || *panic!*
-	- Check for admin privilege (for XMRig) || *warn!*
-	- Attempt to read `gupax.toml` || *warn!*, *initialize config with default options*
+	- Initialize custom console logging with `log`, `env_logger`
+	- Initialize misc data (structs, text styles, thread count, images, etc)
+	- Check for admin privilege (for XMRig)
+	- Start initializing main `App` struct
+	- Parse command arguments
+	- Attempt to read disk files `state.toml`, `node.toml`
 	- If errors were found, pop-up window
 	
 2. **AUTO**
-	- If `auto_update` == `true`, pop-up auto-updating window || *info!*, *skip auto-update*
-	- Multi-threaded GitHub API check on Gupax -> P2Pool -> XMRig || *warn!*, *skip auto-update*
-	- Multi-threaded download if current version != new version || *warn!*, *skip auto-update*
-	- After download, atomically replace current binaries with new || *warn!*, *skip auto-update*
-	- Update version metadata || *warn!*, *skip auto-update*
-	- If `auto_select` == `true`, ping community nodes and select fastest one || *warn!*
+	- If `auto_update` == `true`, spawn auto-updating thread
+	- If `auto_select` == `true`, spawn community node ping thread
 
 3. **MAIN**
-	- All data must be initialized at this point, either via `gupax.toml` or default options || *panic!*
-	- Start `App` frame || *panic!*
-	- Write state to `gupax.toml` on user clicking `Save` (after checking input for correctness) || *warn!*
-	- If `ask_before_quit` == `true`, check for running processes, unsaved state, and update connections before quitting
+	- All data should be initialized at this point, either via `state.toml` or default options
+	- Start `App` frame
+	- Do `App` stuff
+	- If `ask_before_quit` == `true`, ask before quitting
 	- Kill processes, kill connections, exit
 
 ## State
-Internal state is saved in the "OS data folder" as `gupax.toml`, using the [TOML](https://github.com/toml-lang/toml) format. If the version can't be parsed (not in the `vX.X.X` or `vX.X` format), the auto-updater will be skipped. [If not found, a default `gupax.toml` file will be created with `State::default`.](https://github.com/hinto-janaiyo/gupax/blob/main/src/state.rs) Gupax will `panic!` if `gupax.toml` has IO or parsing issues.
+Internal state is saved in the "OS data folder" as `state.toml`, using the [TOML](https://github.com/toml-lang/toml) format. If not found, a default `state.toml` file will be created. Given a slightly corrupted state file, Gupax will attempt to merge it with a new default one. This will most likely happen if the internal data structure of `state.toml` is changed in the future (e.g removing an outdated setting). Merging silently in the background is a good non-interactive way to handle this. If Gupax can't read/write to disk at all, or if there are any other big issues, it will show an un-recoverable error window.
 
 | OS       | Data Folder                              | Example                                                   |
 |----------|----------------------------------------- |-----------------------------------------------------------|
@@ -57,8 +55,7 @@ Every frame, the max available `[width, height]` are calculated, and those are u
 
 ```
 Main [App] outer frame (default: [1280.0, 720.0])
-├─ Inner frame (1264.0, 704.0)
-   ├─ TopPanel     = [width: (max-90.0)/5.0, height: max/10.0]
-   ├─ BottomPanel  = [width: max, height: max/18.0]
-   ├─ CentralPanel = [width: (max/8.0), height: the rest
+   ├─ TopPanel     = height: 1/12th
+   ├─ BottomPanel  = height: 1/20th
+   ├─ CentralPanel = height: the rest
 ```
diff --git a/src/node.rs b/src/node.rs
index ffdf942..861d4ae 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -213,6 +213,9 @@ pub fn format_enum(id: NodeEnum) -> String {
 // default = GRAY
 #[tokio::main]
 pub async fn ping(ping: Arc<Mutex<Ping>>, og: Arc<Mutex<State>>) -> Result<(), anyhow::Error> {
+	// Timer
+	let now = Instant::now();
+
 	// Start ping
 	ping.lock().unwrap().pinging = true;
 	ping.lock().unwrap().prog = 0.0;
@@ -251,6 +254,7 @@ pub async fn ping(ping: Arc<Mutex<Ping>>, og: Arc<Mutex<State>>) -> Result<(), a
 
 	let info = format!("Fastest node: {}ms ... {} @ {}", node_vec[0].ms, node_vec[0].id, node_vec[0].ip);
 	info!("Ping | {}", info);
+	info!("Ping | Took [{}] seconds...", now.elapsed().as_secs_f32());
 	let mut ping = ping.lock().unwrap();
 		ping.fastest = node_vec[0].id;
 		ping.nodes = node_vec;
@@ -267,9 +271,18 @@ async fn response(client: hyper::client::Client<hyper::client::HttpConnector>, r
 	let id = ip_to_enum(ip);
 	let now = Instant::now();
 	let ms;
+	let info;
 	match tokio::time::timeout(Duration::from_secs(5), client.request(request)).await {
-		Ok(_) => ms = now.elapsed().as_millis(),
-		Err(e) => { warn!("Ping | {}: {} ... FAIL ... {}", id, ip, e); ms = 5000; },
+		Ok(_) => {
+			ms = now.elapsed().as_millis();
+			info = format!("{}ms ... {}: {}", ms, id, ip);
+			info!("Ping | {}", info)
+		},
+		Err(e) => {
+			ms = 5000;
+			info = format!("{}ms ... {}: {}", ms, id, ip);
+			warn!("Ping | {}", info)
+		},
 	};
 	let color;
 	if ms < 300 {
@@ -281,8 +294,6 @@ async fn response(client: hyper::client::Client<hyper::client::HttpConnector>, r
 	} else {
 		color = Color32::BLACK;
 	}
-	let info = format!("{}ms ... {}: {}", ms, id, ip);
-	info!("Ping | {}", info);
 	let mut ping = ping.lock().unwrap();
 	ping.msg = info;
 	ping.prog += percent;