p2pool: add [Ping] into GUI, add [simple], add address regex check

This commit is contained in:
hinto-janaiyo 2022-11-10 21:20:31 -05:00
parent 22a03a6034
commit 9638f9dc5b
No known key found for this signature in database
GPG key ID: D7483F6CA27D1B1D
10 changed files with 633 additions and 378 deletions

147
Cargo.lock generated
View file

@ -4,7 +4,7 @@ version = 3
[[package]] [[package]]
name = "Gupax" name = "Gupax"
version = "0.1.0" version = "0.2.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arti-client", "arti-client",
@ -15,7 +15,7 @@ dependencies = [
"eframe", "eframe",
"egui", "egui",
"egui_extras", "egui_extras",
"env_logger 0.9.1", "env_logger 0.9.3",
"figment", "figment",
"flate2", "flate2",
"hex-literal", "hex-literal",
@ -112,9 +112,9 @@ dependencies = [
[[package]] [[package]]
name = "ahash" name = "ahash"
version = "0.8.0" version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57e6e951cfbb2db8de1828d49073a113a29fd7117b1596caa781a258c7e38d72" checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"getrandom 0.2.8", "getrandom 0.2.8",
@ -294,9 +294,9 @@ dependencies = [
[[package]] [[package]]
name = "asynchronous-codec" name = "asynchronous-codec"
version = "0.6.0" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0de5164e5edbf51c45fb8c2d9664ae1c095cce1b265ecf7569093c0d66ef690" checksum = "06a0daa378f5fd10634e44b0a29b2a87b890657658e072a30d6f26e57ddee182"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-sink", "futures-sink",
@ -434,18 +434,18 @@ checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.12.1" version = "1.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f"
dependencies = [ dependencies = [
"bytemuck_derive", "bytemuck_derive",
] ]
[[package]] [[package]]
name = "bytemuck_derive" name = "bytemuck_derive"
version = "1.2.1" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9e1f5fa78f69496407a27ae9ed989e3c3b072310286f5ef385525e4cbc24a9" checksum = "5fe233b960f12f8007e3db2d136e3cb1c291bfd7396e384ee76025fc1a3932b4"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -487,9 +487,9 @@ dependencies = [
[[package]] [[package]]
name = "calloop" name = "calloop"
version = "0.10.1" version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a22a6a8f622f797120d452c630b0ab12e1331a1a753e2039ce7868d4ac77b4ee" checksum = "595eb0438b3c6d262395fe30e6de9a61beb57ea56290b00a07f227fe6e20cbf2"
dependencies = [ dependencies = [
"log", "log",
"nix 0.24.2", "nix 0.24.2",
@ -506,9 +506,9 @@ checksum = "ceea694ffdf0118d2df95ace6fd9edfc6d27f88408d0d73b390f2d9e5699b3f2"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.74" version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574" checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
dependencies = [ dependencies = [
"jobserver", "jobserver",
] ]
@ -603,9 +603,9 @@ dependencies = [
[[package]] [[package]]
name = "cocoa" name = "cocoa"
version = "0.24.0" version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"block", "block",
@ -893,9 +893,9 @@ dependencies = [
[[package]] [[package]]
name = "cxx" name = "cxx"
version = "1.0.80" version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" checksum = "97abf9f0eca9e52b7f81b945524e76710e6cb2366aead23b7d4fbf72e281f888"
dependencies = [ dependencies = [
"cc", "cc",
"cxxbridge-flags", "cxxbridge-flags",
@ -905,9 +905,9 @@ dependencies = [
[[package]] [[package]]
name = "cxx-build" name = "cxx-build"
version = "1.0.80" version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" checksum = "7cc32cc5fea1d894b77d269ddb9f192110069a8a9c1f1d441195fba90553dea3"
dependencies = [ dependencies = [
"cc", "cc",
"codespan-reporting", "codespan-reporting",
@ -920,15 +920,15 @@ dependencies = [
[[package]] [[package]]
name = "cxxbridge-flags" name = "cxxbridge-flags"
version = "1.0.80" version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" checksum = "8ca220e4794c934dc6b1207c3b42856ad4c302f2df1712e9f8d2eec5afaacf1f"
[[package]] [[package]]
name = "cxxbridge-macro" name = "cxxbridge-macro"
version = "1.0.80" version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1187,9 +1187,9 @@ dependencies = [
[[package]] [[package]]
name = "educe" name = "educe"
version = "0.4.19" version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c07b7cc9cd8c08d10db74fca3b20949b9b6199725c04a0cce6d543496098fcac" checksum = "cb0188e3c3ba8df5753894d54461f0e39bc91741dc5b22e1c46999ec2c71f4e4"
dependencies = [ dependencies = [
"enum-ordinalize", "enum-ordinalize",
"proc-macro2", "proc-macro2",
@ -1225,7 +1225,7 @@ version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc9fcd393c3daaaf5909008a1d948319d538b79c51871e4df0993260260a94e4" checksum = "fc9fcd393c3daaaf5909008a1d948319d538b79c51871e4df0993260260a94e4"
dependencies = [ dependencies = [
"ahash 0.8.0", "ahash 0.8.2",
"epaint", "epaint",
"nohash-hasher", "nohash-hasher",
"tracing", "tracing",
@ -1297,9 +1297,9 @@ dependencies = [
[[package]] [[package]]
name = "enum-ordinalize" name = "enum-ordinalize"
version = "3.1.11" version = "3.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2170fc0efee383079a8bdd05d6ea2a184d2a0f07a1c1dcabdb2fd5e9f24bc36c" checksum = "a62bb1df8b45ecb7ffa78dca1c17a438fb193eb083db0b1b494d2a61bcb5096a"
dependencies = [ dependencies = [
"num-bigint", "num-bigint",
"num-traits", "num-traits",
@ -1324,9 +1324,9 @@ dependencies = [
[[package]] [[package]]
name = "env_logger" name = "env_logger"
version = "0.9.1" version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
dependencies = [ dependencies = [
"atty", "atty",
"humantime 2.1.0", "humantime 2.1.0",
@ -1342,7 +1342,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ba04741be7f6602b1a1b28f1082cce45948a7032961c52814f8946b28493300" checksum = "5ba04741be7f6602b1a1b28f1082cce45948a7032961c52814f8946b28493300"
dependencies = [ dependencies = [
"ab_glyph", "ab_glyph",
"ahash 0.8.0", "ahash 0.8.2",
"atomic_refcell", "atomic_refcell",
"bytemuck", "bytemuck",
"emath", "emath",
@ -1983,9 +1983,9 @@ dependencies = [
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.14.20" version = "0.14.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
@ -2110,9 +2110,9 @@ dependencies = [
[[package]] [[package]]
name = "ipnet" name = "ipnet"
version = "2.5.0" version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745"
[[package]] [[package]]
name = "itertools" name = "itertools"
@ -2211,9 +2211,9 @@ checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
[[package]] [[package]]
name = "libloading" name = "libloading"
version = "0.7.3" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"winapi", "winapi",
@ -2221,9 +2221,9 @@ dependencies = [
[[package]] [[package]]
name = "libm" name = "libm"
version = "0.2.5" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
[[package]] [[package]]
name = "libsqlite3-sys" name = "libsqlite3-sys"
@ -2266,9 +2266,9 @@ dependencies = [
[[package]] [[package]]
name = "lzma-sys" name = "lzma-sys"
version = "0.1.19" version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e06754c4acf47d49c727d5665ca9fb828851cda315ed3bd51edd148ef78a8772" checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
@ -2292,9 +2292,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]] [[package]]
name = "memmap2" name = "memmap2"
version = "0.5.7" version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@ -2389,9 +2389,9 @@ dependencies = [
[[package]] [[package]]
name = "native-tls" name = "native-tls"
version = "0.2.10" version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"libc", "libc",
@ -2623,9 +2623,9 @@ dependencies = [
[[package]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.13.1" version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi",
"libc", "libc",
@ -2652,15 +2652,6 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "objc" name = "objc"
version = "0.2.7" version = "0.2.7"
@ -2964,14 +2955,14 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]] [[package]]
name = "png" name = "png"
version = "0.17.6" version = "0.17.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f0e7f4c94ec26ff209cee506314212639d6c91b80afb82984819fafce9df01c" checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"crc32fast", "crc32fast",
"flate2", "flate2",
"miniz_oxide 0.5.4", "miniz_oxide 0.6.2",
] ]
[[package]] [[package]]
@ -2991,9 +2982,9 @@ dependencies = [
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.16" version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "proc-macro-crate" name = "proc-macro-crate"
@ -3171,9 +3162,9 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.6.0" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -3182,9 +3173,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.27" version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]] [[package]]
name = "remove_dir_all" name = "remove_dir_all"
@ -3291,7 +3282,7 @@ dependencies = [
"hashlink", "hashlink",
"libsqlite3-sys", "libsqlite3-sys",
"smallvec", "smallvec",
"time 0.3.16", "time 0.3.17",
] ]
[[package]] [[package]]
@ -3378,9 +3369,9 @@ dependencies = [
[[package]] [[package]]
name = "scoped-tls" name = "scoped-tls"
version = "1.0.0" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]] [[package]]
name = "scoped_threadpool" name = "scoped_threadpool"
@ -3647,7 +3638,7 @@ dependencies = [
"num-bigint", "num-bigint",
"num-traits", "num-traits",
"thiserror", "thiserror",
"time 0.3.16", "time 0.3.17",
] ]
[[package]] [[package]]
@ -3911,13 +3902,11 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.16" version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
dependencies = [ dependencies = [
"itoa", "itoa",
"libc",
"num_threads",
"serde", "serde",
"time-core", "time-core",
"time-macros", "time-macros",
@ -3931,9 +3920,9 @@ checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
[[package]] [[package]]
name = "time-macros" name = "time-macros"
version = "0.2.5" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
dependencies = [ dependencies = [
"time-core", "time-core",
] ]
@ -4356,7 +4345,7 @@ dependencies = [
"serde", "serde",
"signature", "signature",
"thiserror", "thiserror",
"time 0.3.16", "time 0.3.17",
"tor-basic-utils", "tor-basic-utils",
"tor-checkable", "tor-checkable",
"tor-circmgr", "tor-circmgr",
@ -4513,7 +4502,7 @@ dependencies = [
"serde_with", "serde_with",
"signature", "signature",
"thiserror", "thiserror",
"time 0.3.16", "time 0.3.17",
"tinystr", "tinystr",
"tor-bytes", "tor-bytes",
"tor-cert", "tor-cert",
@ -5341,7 +5330,7 @@ dependencies = [
"hmac", "hmac",
"pbkdf2", "pbkdf2",
"sha1", "sha1",
"time 0.3.16", "time 0.3.17",
"zstd", "zstd",
] ]

View file

@ -1,7 +1,7 @@
[package] [package]
name = "Gupax" name = "Gupax"
version = "0.1.0" version = "0.2.0"
authors = ["hinto-janaiyo <hinto-janaiyo@protonmail.com>"] authors = ["hinto-janaiyo <hinto.janaiyo@protonmail.com>"]
description = "GUI for P2Pool+XMRig" description = "GUI for P2Pool+XMRig"
documentation = "https://github.com/hinto-janaiyo/gupax" documentation = "https://github.com/hinto-janaiyo/gupax"
edition = "2021" edition = "2021"

View file

@ -88,11 +88,10 @@ https://user-images.githubusercontent.com/101352116/194763334-d8e936c9-a71e-474e
* A Monero node/wallet * A Monero node/wallet
## Build ## Build
Windows/macOS/Linux:
``` ```
cargo build --release cargo build --release
``` ```
On macOS, if you want the binary to have an icon in `Finder`, you must install [`cargo-bundle`](https://github.com/burtonageo/cargo-bundle) and compile uwith: On macOS, if you want the binary to have an icon in `Finder`, you must install [`cargo-bundle`](https://github.com/burtonageo/cargo-bundle) and compile with:
``` ```
cargo bundle --release cargo bundle --release
``` ```

View file

@ -8,13 +8,15 @@
| File/Folder | Purpose | | File/Folder | Purpose |
|----------------|---------| |----------------|---------|
| `constants.rs` | General constants needed in Gupax | `constants.rs` | General constants needed in Gupax
| `gupax.rs` | Impl for `Gupax` tab | `ferris.rs` | Cute crab `--ferris`
| `main.rs` | Struct/enum/impl for `App/Tab/State`, init functions, main function | `gupax.rs` | `Gupax` tab
| `node.rs` | Struct/impl for Community Nodes | `main.rs` | `App/Tab/State` + misc functions
| `p2pool.rs` | Impl for `P2Pool` tab | `node.rs` | Community node feature
| `state.rs` | Struct/impl for `gupax.toml`, the disk state. This holds the structs representing tabs with mutable state (Gupax/P2Pool/XMRig) | `p2pool.rs` | `P2Pool` tab
| `status.rs` | Struct/impl for `Status` tab | `state.rs` | `gupax.toml` config code. This holds the structs representing tabs with mutable state (Gupax/P2Pool/XMRig)
| `xmrig.rs` | Impl for `XMRig` tab | `status.rs` | `Status` tab
| `update.rs` | Update code for the `Gupax` tab
| `xmrig.rs` | `XMRig` tab
## Bootstrap ## Bootstrap
This is how Gupax works internally when starting up, divided into 3 sections. This is how Gupax works internally when starting up, divided into 3 sections.

View file

@ -69,13 +69,19 @@ pub const GUPAX_SAVE_BEFORE_QUIT: &'static str = "Automatically save any changed
pub const GUPAX_PATH_P2POOL: &'static str = "The location of the P2Pool binary, both absolute and relative paths are accepted"; pub const GUPAX_PATH_P2POOL: &'static str = "The location of the P2Pool binary, both absolute and relative paths are accepted";
pub const GUPAX_PATH_XMRIG: &'static str = "The location of the XMRig binary, both absolute and relative paths are accepted"; pub const GUPAX_PATH_XMRIG: &'static str = "The location of the XMRig binary, both absolute and relative paths are accepted";
// P2Pool // P2Pool
pub const P2POOL_MAIN: &'static str = "The P2Pool main-chain. This P2Pool finds shares faster, but has a higher difficulty. Suitable for miners with more than 50kH/s"; pub const P2POOL_MAIN: &'static str = "Use the P2Pool main-chain. This P2Pool finds shares faster, but has a higher difficulty. Suitable for miners with more than 50kH/s";
pub const P2POOL_MINI: &'static str = "The P2Pool mini-chain. This P2Pool finds shares slower, but has a lower difficulty. Suitable for miners with less than 50kH/s"; pub const P2POOL_MINI: &'static str = "Use the P2Pool mini-chain. This P2Pool finds shares slower, but has a lower difficulty. Suitable for miners with less than 50kH/s";
pub const P2POOL_OUT: &'static str = "How many out-bound peers (you connecting to others) to connect to?"; pub const P2POOL_OUT: &'static str = "How many out-bound peers (you connecting to others) to connect to?";
pub const P2POOL_IN: &'static str = "How many in-bound peers (others connecting to you) to connect to?"; pub const P2POOL_IN: &'static str = "How many in-bound peers (others connecting to you) to connect to?";
pub const P2POOL_LOG: &'static str = "Verbosity of the console log"; pub const P2POOL_LOG: &'static str = "Verbosity of the console log";
pub const P2POOL_COMMUNITY: &'static str = "Connect to a community trusted Monero node: This is convenient because you don't have to download the Monero blockchain but it comes at the cost of privacy"; pub const P2POOL_COMMUNITY: &'static str = "Connect to a community trusted Monero node: This is convenient because you don't have to download the Monero blockchain but it comes at the cost of privacy";
pub const P2POOL_MANUAL: &'static str = "Manually specify your own Monero node settings"; pub const P2POOL_MANUAL: &'static str = "Manually specify your own Monero node settings";
pub const P2POOL_AUTO_NODE: &'static str = "Automatically ping the community Monero nodes at Gupax startup";
pub const P2POOL_AUTO_SELECT: &'static str = "Automatically select the fastest community Monero node after pinging";
pub const P2POOL_SELECT_FASTEST: &'static str = "Select the fastest community Monero node";
pub const P2POOL_PING: &'static str = "Ping the built-in community Monero nodes";
pub const P2POOL_ADDRESS: &'static str = "You must use a primary Monero address to mine on P2Pool (starts with a 4). It is highly recommended to create a new wallet for P2Pool mining; wallet addresses are public on P2Pool!";
// XMRig // XMRig
pub const XMRIG_P2POOL: &'static str = "Mine to your own P2Pool instance (localhost:3333)"; pub const XMRIG_P2POOL: &'static str = "Mine to your own P2Pool instance (localhost:3333)";
pub const XMRIG_MANUAL: &'static str = "Manually specify where to mine to"; pub const XMRIG_MANUAL: &'static str = "Manually specify where to mine to";

View file

@ -17,7 +17,8 @@
use std::path::Path; use std::path::Path;
use crate::{App,State}; use crate::{App,State};
use egui::WidgetType::Button; use egui::TextStyle::Monospace;
use egui::RichText;
use crate::constants::*; use crate::constants::*;
use crate::state::{Gupax,Version}; use crate::state::{Gupax,Version};
use crate::update::*; use crate::update::*;
@ -73,7 +74,7 @@ impl Gupax {
ui.set_enabled(updating); ui.set_enabled(updating);
let prog = *update.lock().unwrap().prog.lock().unwrap(); let prog = *update.lock().unwrap().prog.lock().unwrap();
let msg = format!("{}\n{}{}", *update.lock().unwrap().msg.lock().unwrap(), prog, "%"); let msg = format!("{}\n{}{}", *update.lock().unwrap().msg.lock().unwrap(), prog, "%");
ui.add_sized([width, height*1.4], egui::Label::new(msg)); ui.add_sized([width, height*1.4], egui::Label::new(RichText::text_style(RichText::new(msg), Monospace)));
let height = height/2.0; let height = height/2.0;
if updating { if updating {
ui.add_sized([width, height], egui::Spinner::new().size(height)); ui.add_sized([width, height], egui::Spinner::new().size(height));

View file

@ -34,6 +34,9 @@ use eframe::{egui,NativeOptions};
use log::*; use log::*;
use env_logger::{Builder,WriteStyle}; use env_logger::{Builder,WriteStyle};
// Regex
use regex::Regex;
// std // std
use std::io::Write; use std::io::Write;
use std::process::exit; use std::process::exit;
@ -64,9 +67,7 @@ pub struct App {
tab: Tab, // What tab are we on? tab: Tab, // What tab are we on?
quit: bool, // Was the quit button clicked? quit: bool, // Was the quit button clicked?
quit_confirm: bool, // Was the quit confirmed? quit_confirm: bool, // Was the quit confirmed?
ping: bool, // Was the ping button clicked? ping: Arc<Mutex<Ping>>, // Ping data found in [node.rs]
pinging: Arc<Mutex<bool>>, // Is a ping in progress?
node: Arc<Mutex<NodeStruct>>, // Data on community nodes
width: f32, // Top-level width width: f32, // Top-level width
height: f32, // Top-level height height: f32, // Top-level height
// State // State
@ -88,9 +89,10 @@ pub struct App {
dir: String, // Directory [Gupax] binary is in dir: String, // Directory [Gupax] binary is in
resolution: Vec2, // Frame resolution resolution: Vec2, // Frame resolution
os: &'static str, // OS os: &'static str, // OS
version: String, // Gupax version version: &'static str, // Gupax version
name_version: String, // [Gupax vX.X.X] name_version: String, // [Gupax vX.X.X]
banner: RetainedImage, // Gupax banner image banner: RetainedImage, // Gupax banner image
addr_regex: Regex, // [4.*] Monero Address Regex
} }
impl App { impl App {
@ -108,11 +110,9 @@ impl App {
tab: Tab::default(), tab: Tab::default(),
quit: false, quit: false,
quit_confirm: false, quit_confirm: false,
ping: false, ping: Arc::new(Mutex::new(Ping::new())),
pinging: Arc::new(Mutex::new(false)),
width: 1280.0, width: 1280.0,
height: 720.0, height: 720.0,
node: Arc::new(Mutex::new(NodeStruct::default())),
og: Arc::new(Mutex::new(State::default())), og: Arc::new(Mutex::new(State::default())),
state: State::default(), state: State::default(),
update: Arc::new(Mutex::new(Update::new(String::new(), PathBuf::new(), PathBuf::new(), true))), update: Arc::new(Mutex::new(Update::new(String::new(), PathBuf::new(), PathBuf::new(), true))),
@ -126,9 +126,10 @@ impl App {
dir: "".to_string(), dir: "".to_string(),
resolution: Vec2::new(1280.0, 720.0), resolution: Vec2::new(1280.0, 720.0),
os: OS, os: OS,
version: format!("{}", GUPAX_VERSION), version: GUPAX_VERSION,
name_version: format!("Gupax {}", GUPAX_VERSION), name_version: format!("Gupax {}", GUPAX_VERSION),
banner: RetainedImage::from_image_bytes("banner.png", BYTES_BANNER).expect("oops"), banner: RetainedImage::from_image_bytes("banner.png", BYTES_BANNER).unwrap(),
addr_regex: Regex::new("^4[A-Za-z1-9]+$").unwrap(),
}; };
// Apply arg state // Apply arg state
let mut app = parse_args(app); let mut app = parse_args(app);
@ -188,21 +189,15 @@ fn init_text_styles(ctx: &egui::Context, width: f32) {
let scale = width / 26.666; let scale = width / 26.666;
let mut style = (*ctx.style()).clone(); let mut style = (*ctx.style()).clone();
style.text_styles = [ style.text_styles = [
// (Small, FontId::new(10.0, Proportional)),
// (Body, FontId::new(25.0, Proportional)),
// (Button, FontId::new(25.0, Proportional)),
// (Monospace, FontId::new(25.0, Proportional)),
// (Heading, FontId::new(30.0, Proportional)),
// (Name("Tab".into()), FontId::new(50.0, Proportional)),
// (Name("Bottom".into()), FontId::new(25.0, Proportional)),
(Small, FontId::new(scale/3.0, Proportional)), (Small, FontId::new(scale/3.0, Proportional)),
(Body, FontId::new(scale/2.0, Proportional)), (Body, FontId::new(scale/2.0, Proportional)),
(Button, FontId::new(scale/2.0, Proportional)), (Button, FontId::new(scale/2.0, Proportional)),
(Monospace, FontId::new(scale/2.0, Proportional)), (Monospace, FontId::new(scale/2.0, egui::FontFamily::Monospace)),
(Heading, FontId::new(scale/1.5, Proportional)), (Heading, FontId::new(scale/1.5, Proportional)),
(Name("Tab".into()), FontId::new(scale*1.2, Proportional)), (Name("Tab".into()), FontId::new(scale*1.2, Proportional)),
(Name("Bottom".into()), FontId::new(scale/2.0, Proportional)), (Name("Bottom".into()), FontId::new(scale/2.0, Proportional)),
].into(); ].into();
// style.visuals.selection.stroke = Stroke { width: 5.0, color: Color32::from_rgb(255, 255, 255) };
// style.spacing.slider_width = scale; // style.spacing.slider_width = scale;
// style.spacing.text_edit_width = scale; // style.spacing.text_edit_width = scale;
// style.spacing.button_padding = Vec2::new(scale/2.0, scale/2.0); // style.spacing.button_padding = Vec2::new(scale/2.0, scale/2.0);
@ -211,6 +206,14 @@ fn init_text_styles(ctx: &egui::Context, width: f32) {
ctx.request_repaint(); ctx.request_repaint();
} }
//fn init_color(ctx: &egui::Context) {
// let mut style = (*ctx.style()).clone();
// style.visuals.widgets.inactive.fg_stroke.color = Color32::from_rgb(100, 100, 100);
// style.visuals.selection.bg_fill = Color32::from_rgb(255, 125, 50);
// style.visuals.selection.stroke = Stroke { width: 5.0, color: Color32::from_rgb(255, 255, 255) };
// ctx.set_style(style);
//}
fn init_logger() { fn init_logger() {
// #[cfg(debug_assertions)] // #[cfg(debug_assertions)]
let filter = LevelFilter::Info; let filter = LevelFilter::Info;
@ -395,6 +398,9 @@ impl eframe::App for App {
// *-------* // *-------*
// | DEBUG | // | DEBUG |
// *-------* // *-------*
// crate::node::ping();
// std::process::exit(0);
// init_color(ctx);
// This sets the top level Ui dimensions. // This sets the top level Ui dimensions.
// Used as a reference for other uis. // Used as a reference for other uis.
@ -413,6 +419,11 @@ impl eframe::App for App {
// contains Arc<Mutex>'s that cannot be compared easily. // contains Arc<Mutex>'s that cannot be compared easily.
// They don't need to be compared anyway. // They don't need to be compared anyway.
let og = self.og.lock().unwrap().clone(); let og = self.og.lock().unwrap().clone();
// The [P2Pool Node] selection needs to be the same
// for both [State] and [Og] because of [Auto-select]
// Wrapping [node] within an [Arc<Mutex>] is a lot more work
// so sending it into the [Ping] thread is not viable.
self.state.p2pool.node = self.og.lock().unwrap().p2pool.node;
if og.gupax != self.state.gupax || og.p2pool != self.state.p2pool || og.xmrig != self.state.xmrig { if og.gupax != self.state.gupax || og.p2pool != self.state.p2pool || og.xmrig != self.state.xmrig {
self.diff = true; self.diff = true;
} else { } else {
@ -503,10 +514,7 @@ impl eframe::App for App {
ui.style_mut().override_text_style = Some(Name("Tab".into())); ui.style_mut().override_text_style = Some(Name("Tab".into()));
ui.style_mut().visuals.widgets.inactive.fg_stroke.color = Color32::from_rgb(100, 100, 100); ui.style_mut().visuals.widgets.inactive.fg_stroke.color = Color32::from_rgb(100, 100, 100);
ui.style_mut().visuals.selection.bg_fill = Color32::from_rgb(255, 120, 120); ui.style_mut().visuals.selection.bg_fill = Color32::from_rgb(255, 120, 120);
ui.style_mut().visuals.selection.stroke = Stroke { ui.style_mut().visuals.selection.stroke = Stroke { width: 5.0, color: Color32::from_rgb(255, 255, 255) };
width: 5.0,
color: Color32::from_rgb(255, 255, 255),
};
if ui.add_sized([width, height], egui::SelectableLabel::new(self.tab == Tab::About, "About")).clicked() { self.tab = Tab::About; } if ui.add_sized([width, height], egui::SelectableLabel::new(self.tab == Tab::About, "About")).clicked() { self.tab = Tab::About; }
ui.separator(); ui.separator();
if ui.add_sized([width, height], egui::SelectableLabel::new(self.tab == Tab::Status, "Status")).clicked() { self.tab = Tab::Status; } if ui.add_sized([width, height], egui::SelectableLabel::new(self.tab == Tab::Status, "Status")).clicked() { self.tab = Tab::Status; }
@ -523,53 +531,64 @@ impl eframe::App for App {
// Bottom: app info + state/process buttons // Bottom: app info + state/process buttons
egui::TopBottomPanel::bottom("bottom").show(ctx, |ui| { egui::TopBottomPanel::bottom("bottom").show(ctx, |ui| {
let width = self.width/8.0;
let height = self.height/18.0; let height = self.height/18.0;
ui.style_mut().override_text_style = Some(Name("Bottom".into())); ui.style_mut().override_text_style = Some(Name("Bottom".into()));
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.group(|ui| { ui.group(|ui| {
// [Gupax Version] + [OS] + [P2Pool on/off] + [XMRig on/off]
let width = ((self.width/2.0)/4.0)-(SPACE*2.0);
ui.add_sized([width, height], Label::new(&*self.name_version)); ui.add_sized([width, height], Label::new(&*self.name_version));
ui.separator(); ui.separator();
ui.add_sized([width, height], Label::new(self.os)); ui.add_sized([width, height], Label::new(self.os));
ui.separator(); ui.separator();
ui.add_sized([width/1.5, height], Label::new("P2Pool"));
if self.p2pool { if self.p2pool {
ui.add_sized([width/4.0, height], Label::new(RichText::new("").color(Color32::from_rgb(100, 230, 100)))); ui.add_sized([width, height], Label::new(RichText::new("P2Pool ").color(Color32::from_rgb(100, 230, 100))));
} else { } else {
ui.add_sized([width/4.0, height], Label::new(RichText::new("").color(Color32::from_rgb(230, 50, 50)))); ui.add_sized([width, height], Label::new(RichText::new("P2Pool ").color(Color32::from_rgb(230, 50, 50))));
} }
ui.separator(); ui.separator();
ui.add_sized([width/1.5, height], Label::new("XMRig"));
if self.xmrig { if self.xmrig {
ui.add_sized([width/4.0, height], Label::new(RichText::new("").color(Color32::from_rgb(100, 230, 100)))); ui.add_sized([width, height], Label::new(RichText::new("XMRig ").color(Color32::from_rgb(100, 230, 100))));
} else { } else {
ui.add_sized([width/4.0, height], Label::new(RichText::new("").color(Color32::from_rgb(230, 50, 50)))); ui.add_sized([width, height], Label::new(RichText::new("XMRig ").color(Color32::from_rgb(230, 50, 50))));
} }
}); });
ui.with_layout(egui::Layout::right_to_left(egui::Align::RIGHT), |ui| { ui.with_layout(egui::Layout::right_to_left(egui::Align::RIGHT), |ui| {
// [Start/Stop/Restart] + [Simple/Advanced] + [Save/Reset]
let width = (ui.available_width()/3.0)-(SPACE*3.0);
ui.group(|ui| { ui.group(|ui| {
if self.diff == false { if self.diff == false {
ui.set_enabled(false) ui.set_enabled(false)
} }
let width = width / 2.0; let width = width / 2.0;
if ui.add_sized([width, height], egui::Button::new("Reset")).on_hover_text("Reset changes").clicked() {
self.state.gupax = self.og.lock().unwrap().gupax.clone();
self.state.p2pool = self.og.lock().unwrap().p2pool.clone();
self.state.xmrig = self.og.lock().unwrap().xmrig.clone();
}
if ui.add_sized([width, height], egui::Button::new("Save")).on_hover_text("Save changes").clicked() { if ui.add_sized([width, height], egui::Button::new("Save")).on_hover_text("Save changes").clicked() {
self.og.lock().unwrap().gupax = self.state.gupax.clone(); self.og.lock().unwrap().gupax = self.state.gupax.clone();
self.og.lock().unwrap().p2pool = self.state.p2pool.clone(); self.og.lock().unwrap().p2pool = self.state.p2pool.clone();
self.og.lock().unwrap().xmrig = self.state.xmrig.clone(); self.og.lock().unwrap().xmrig = self.state.xmrig.clone();
self.og.lock().unwrap().save(); self.og.lock().unwrap().save();
} }
if ui.add_sized([width, height], egui::Button::new("Reset")).on_hover_text("Reset changes").clicked() {
self.state.gupax = self.og.lock().unwrap().gupax.clone();
self.state.p2pool = self.og.lock().unwrap().p2pool.clone();
self.state.xmrig = self.og.lock().unwrap().xmrig.clone();
}
}); });
let width = (ui.available_width() / 3.0) - 6.2;
match self.tab { match self.tab {
Tab::P2pool => { Tab::P2pool => {
ui.group(|ui| { ui.group(|ui| {
let width = width / 1.5;
if ui.add_sized([width, height], egui::SelectableLabel::new(!self.state.p2pool.simple, "Advanced")).clicked() {
self.state.p2pool.simple = false;
}
ui.separator();
if ui.add_sized([width, height], egui::SelectableLabel::new(self.state.p2pool.simple, "Simple")).clicked() {
self.state.p2pool.simple = true;
}
});
ui.group(|ui| {
let width = (ui.available_width()/3.0)-5.0;
if self.p2pool { if self.p2pool {
if ui.add_sized([width, height], egui::Button::new("")).on_hover_text("Restart P2Pool").clicked() { self.p2pool = false; } if ui.add_sized([width, height], egui::Button::new("")).on_hover_text("Restart P2Pool").clicked() { self.p2pool = false; }
if ui.add_sized([width, height], egui::Button::new("")).on_hover_text("Stop P2Pool").clicked() { self.p2pool = false; } if ui.add_sized([width, height], egui::Button::new("")).on_hover_text("Stop P2Pool").clicked() { self.p2pool = false; }
@ -587,6 +606,17 @@ impl eframe::App for App {
} }
Tab::Xmrig => { Tab::Xmrig => {
ui.group(|ui| { ui.group(|ui| {
let width = width / 1.5;
if ui.add_sized([width, height], egui::SelectableLabel::new(!self.state.xmrig.simple, "Advanced")).clicked() {
self.state.xmrig.simple = false;
}
ui.separator();
if ui.add_sized([width, height], egui::SelectableLabel::new(self.state.xmrig.simple, "Simple")).clicked() {
self.state.xmrig.simple = true;
}
});
ui.group(|ui| {
let width = (ui.available_width()/3.0)-5.0;
if self.xmrig { if self.xmrig {
if ui.add_sized([width, height], egui::Button::new("")).on_hover_text("Restart XMRig").clicked() { self.xmrig = false; } if ui.add_sized([width, height], egui::Button::new("")).on_hover_text("Restart XMRig").clicked() { self.xmrig = false; }
if ui.add_sized([width, height], egui::Button::new("")).on_hover_text("Stop XMRig").clicked() { self.xmrig = false; } if ui.add_sized([width, height], egui::Button::new("")).on_hover_text("Stop XMRig").clicked() { self.xmrig = false; }
@ -608,19 +638,6 @@ impl eframe::App for App {
}); });
}); });
// If ping was pressed, start thread
if self.ping {
self.ping = false;
self.pinging = Arc::new(Mutex::new(true));
let node_clone = Arc::clone(&self.node);
let pinging_clone = Arc::clone(&self.pinging);
thread::spawn(move|| {
let result = NodeStruct::ping();
*node_clone.lock().unwrap() = result.nodes;
*pinging_clone.lock().unwrap() = false;
});
}
// Middle panel, contents of the [Tab] // Middle panel, contents of the [Tab]
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
// This sets the Ui dimensions after Top/Bottom are filled // This sets the Ui dimensions after Top/Bottom are filled
@ -655,7 +672,7 @@ impl eframe::App for App {
Gupax::show(&mut self.state.gupax, &self.og, &self.state.version, &self.update, self.width, self.height, ctx, ui); Gupax::show(&mut self.state.gupax, &self.og, &self.state.version, &self.update, self.width, self.height, ctx, ui);
} }
Tab::P2pool => { Tab::P2pool => {
P2pool::show(&mut self.state.p2pool, self.width, self.height, ctx, ui); P2pool::show(&mut self.state.p2pool, &self.og, self.p2pool, &self.ping, &self.addr_regex, self.width, self.height, ctx, ui);
} }
Tab::Xmrig => { Tab::Xmrig => {
Xmrig::show(&mut self.state.xmrig, self.width, self.height, ctx, ui); Xmrig::show(&mut self.state.xmrig, self.width, self.height, ctx, ui);

View file

@ -20,10 +20,13 @@ use std::time::{Instant,Duration};
use std::collections::HashMap; use std::collections::HashMap;
use std::error::Error; use std::error::Error;
use std::thread; use std::thread;
use std::sync::{Arc,Mutex};
use egui::Color32; use egui::Color32;
use rand::Rng; use rand::Rng;
use log::*; use log::*;
use reqwest::blocking::ClientBuilder;
//---------------------------------------------------------------------------------------------------- Node list
// Community Monerod nodes. All of these have ZMQ on 18083. // Community Monerod nodes. All of these have ZMQ on 18083.
// Adding/removing nodes will need changes to pretty // Adding/removing nodes will need changes to pretty
// much all the code in this file, and the code that // much all the code in this file, and the code that
@ -33,37 +36,27 @@ pub const CAKE: &'static str = "xmr-node.cakewallet.com:18081";
pub const CAKE_EU: &'static str = "xmr-node-eu.cakewallet.com:18081"; pub const CAKE_EU: &'static str = "xmr-node-eu.cakewallet.com:18081";
pub const CAKE_UK: &'static str = "xmr-node-uk.cakewallet.com:18081"; pub const CAKE_UK: &'static str = "xmr-node-uk.cakewallet.com:18081";
pub const CAKE_US: &'static str = "xmr-node-usa-east.cakewallet.com:18081"; pub const CAKE_US: &'static str = "xmr-node-usa-east.cakewallet.com:18081";
pub const MAJESTICBANK_IS: &'static str = "node.majesticbank.is:18089";
pub const MAJESTICBANK_SU: &'static str = "node.majesticbank.su:18089";
pub const MONERUJO: &'static str = "nodex.monerujo.io:18081"; pub const MONERUJO: &'static str = "nodex.monerujo.io:18081";
pub const RINO: &'static str = "node.community.rino.io:18081"; pub const RINO: &'static str = "node.community.rino.io:18081";
pub const SELSTA: &'static str = "selsta1.featherwallet.net:18081"; pub const SELSTA_1: &'static str = "selsta1.featherwallet.net:18081";
pub const SELSTA_2: &'static str = "selsta2.featherwallet.net:18081";
pub const SETH: &'static str = "node.sethforprivacy.com:18089"; pub const SETH: &'static str = "node.sethforprivacy.com:18089";
pub const SUPPORTXMR: &'static str = "node.supportxmr.com:18081"; pub const SUPPORTXMR: &'static str = "node.supportxmr.com:18081";
pub const SUPPORTXMR_IR: &'static str = "node.supportxmr.ir:18081"; pub const SUPPORTXMR_IR: &'static str = "node.supportxmr.ir:18081";
pub const SINGAPORE: &'static str = "singapore.node.xmr.pm:18089";
pub const XMRVSBEAST: &'static str = "p2pmd.xmrvsbeast.com:18081"; pub const XMRVSBEAST: &'static str = "p2pmd.xmrvsbeast.com:18081";
pub const NODE_IPS: [&'static str; 12] = [ pub const NODE_IPS: [&'static str; 16] = [
C3POOL,CAKE,CAKE_EU,CAKE_UK,CAKE_US,MONERUJO,RINO, C3POOL,CAKE,CAKE_EU,CAKE_UK,CAKE_US,MAJESTICBANK_IS,MAJESTICBANK_SU,MONERUJO,
SELSTA,SETH,SUPPORTXMR,SUPPORTXMR_IR,XMRVSBEAST, RINO,SELSTA_1,SELSTA_2,SETH,SUPPORTXMR,SUPPORTXMR_IR,SINGAPORE,XMRVSBEAST,
]; ];
#[derive(Debug)]
pub struct NodeStruct {
c3pool: Data, cake: Data, cake_eu: Data, cake_uk: Data, cake_us: Data, monerujo: Data,
rino: Data, selsta: Data, seth: Data, supportxmr: Data, supportxmr_ir: Data, xmrvsbeast: Data,
}
#[derive(Debug)]
pub struct Data {
pub ms: u128,
pub color: Color32,
pub id: NodeEnum,
pub ip: &'static str,
}
#[derive(Copy,Clone,Eq,PartialEq,Debug,Deserialize,Serialize)] #[derive(Copy,Clone,Eq,PartialEq,Debug,Deserialize,Serialize)]
pub enum NodeEnum { pub enum NodeEnum {
C3pool, Cake, CakeEu, CakeUk, CakeUs, Monerujo, Rino, C3pool,Cake,CakeEu,CakeUk,CakeUs,MajesticBankIs,MajesticBankSu,Monerujo,
Selsta, Seth, SupportXmr, SupportXmrIr, XmrVsBeast, Rino,Selsta1,Selsta2,Seth,SupportXmr,SupportXmrIr,Singapore,XmrVsBeast,
} }
impl std::fmt::Display for NodeEnum { impl std::fmt::Display for NodeEnum {
@ -72,44 +65,145 @@ impl std::fmt::Display for NodeEnum {
} }
} }
//---------------------------------------------------------------------------------------------------- Node data
#[derive(Debug)]
pub struct NodeData {
pub id: NodeEnum,
pub ip: &'static str,
pub ms: u128,
pub color: Color32,
}
impl NodeData {
pub fn new_vec() -> Vec<Self> {
let mut vec = Vec::new();
for ip in NODE_IPS.iter() {
vec.push(Self {
id: ip_to_enum(ip),
ip,
ms: 0,
color: Color32::LIGHT_GRAY,
});
}
vec
}
}
//---------------------------------------------------------------------------------------------------- Ping data
#[derive(Debug)]
pub struct Ping {
pub nodes: Vec<NodeData>,
pub fastest: NodeEnum,
pub pinging: bool,
pub msg: String,
pub prog: f32,
pub pinged: bool,
}
impl Ping {
pub fn new() -> Self {
Self {
nodes: NodeData::new_vec(),
fastest: NodeEnum::C3pool,
pinging: false,
msg: "No ping in progress".to_string(),
prog: 0.0,
pinged: false,
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct PingResult { pub struct PingResult {
pub nodes: NodeStruct, pub nodes: Vec<NodeData>,
pub fastest: NodeEnum, pub fastest: NodeEnum,
} }
use crate::NodeEnum::*; //---------------------------------------------------------------------------------------------------- IP <-> Enum functions
impl NodeStruct { // Function for returning IP/Enum
pub fn default() -> Self { pub fn ip_to_enum(ip: &'static str) -> NodeEnum {
let ms = 0; match ip {
let color = Color32::GRAY; C3POOL => C3pool,
Self { CAKE => Cake,
c3pool: Data { ms, color, id: C3pool, ip: C3POOL, }, CAKE_EU => CakeEu,
cake: Data { ms, color, id: Cake, ip: CAKE, }, CAKE_UK => CakeUk,
cake_eu: Data { ms, color, id: CakeEu, ip: CAKE_EU, }, CAKE_US => CakeUs,
cake_uk: Data { ms, color, id: CakeUk, ip: CAKE_UK, }, MAJESTICBANK_IS => MajesticBankIs,
cake_us: Data { ms, color, id: CakeUs, ip: CAKE_US, }, MAJESTICBANK_SU => MajesticBankSu,
monerujo: Data { ms, color, id: Monerujo, ip: MONERUJO, }, MONERUJO => Monerujo,
rino: Data { ms, color, id: Rino, ip: RINO, }, RINO => Rino,
selsta: Data { ms, color, id: Selsta, ip: SELSTA, }, SELSTA_1 => Selsta1,
seth: Data { ms, color, id: Seth, ip: SETH, }, SELSTA_2 => Selsta2,
supportxmr: Data { ms, color, id: SupportXmr, ip: SUPPORTXMR, }, SETH => Seth,
supportxmr_ir: Data { ms, color, id: SupportXmrIr, ip: SUPPORTXMR_IR, }, SINGAPORE => Singapore,
xmrvsbeast: Data { ms, color, id: XmrVsBeast, ip: XMRVSBEAST, }, SUPPORTXMR => SupportXmr,
SUPPORTXMR_IR => SupportXmrIr,
_ => XmrVsBeast,
} }
} }
pub fn enum_to_ip(node: NodeEnum) -> &'static str {
match node {
C3pool => C3POOL,
Cake => CAKE,
CakeEu => CAKE_EU,
CakeUk => CAKE_UK,
CakeUs => CAKE_US,
MajesticBankIs => MAJESTICBANK_IS,
MajesticBankSu => MAJESTICBANK_SU,
Monerujo => MONERUJO,
Rino => RINO,
Selsta1 => SELSTA_1,
Selsta2 => SELSTA_2,
Seth => SETH,
Singapore => SINGAPORE,
SupportXmr => SUPPORTXMR,
SupportXmrIr => SUPPORTXMR_IR,
_ => XMRVSBEAST
}
}
// 5000 = 4 max length
pub fn format_ms(ms: u128) -> String {
match ms.to_string().len() {
1 => format!("{}ms ", ms),
2 => format!("{}ms ", ms),
3 => format!("{}ms ", ms),
_ => format!("{}ms", ms),
}
}
// MajesticBankIs = 14 max length
pub fn format_enum(id: NodeEnum) -> String {
match id.to_string().len() {
1 => format!("{} ", id),
2 => format!("{} ", id),
3 => format!("{} ", id),
4 => format!("{} ", id),
5 => format!("{} ", id),
6 => format!("{} ", id),
7 => format!("{} ", id),
8 => format!("{} ", id),
9 => format!("{} ", id),
10 => format!("{} ", id),
11 => format!("{} ", id),
12 => format!("{} ", id),
13 => format!("{} ", id),
_ => format!("{}", id),
}
}
//---------------------------------------------------------------------------------------------------- Main Ping function
// This is for pinging the community nodes to // This is for pinging the community nodes to
// find the fastest/slowest one for the user. // find the fastest/slowest one for the user.
// The process: // The process:
// - Send [get_info] JSON-RPC requests over HTTP // - Send 3 [get_info] JSON-RPC requests over HTTP
// - To prevent fingerprinting, randomly send [2-4] calls
// - Measure each request in milliseconds as [u128] // - Measure each request in milliseconds as [u128]
// - Timeout on requests over 5 seconds // - Timeout on requests over 5 seconds
// - Calculate average time // - Calculate average time
// - Add data to appropriate struct // - Add data to appropriate struct
// - Sort fastest to lowest // - Sort fastest to lowest
// - Return [PingResult(NodeStruct, NodeEnum)] (data and fastest node) // - Return [PingResult] (data and fastest node)
// //
// This is done linearly since per IP since // This is done linearly since per IP since
// multi-threading might affect performance. // multi-threading might affect performance.
@ -119,10 +213,18 @@ impl NodeStruct {
// >1000ms = RED // >1000ms = RED
// timeout = BLACK // timeout = BLACK
// default = GRAY // default = GRAY
pub fn ping() -> PingResult { use crate::NodeEnum::*;
info!("Starting community node pings..."); pub fn ping(ping: Arc<Mutex<Ping>>) -> PingResult {
// Get node list // Start ping
let mut nodes = NodeStruct::default(); ping.lock().unwrap().pinging = true;
ping.lock().unwrap().prog = 0.0;
let info = format!("{}", "Creating HTTPS Client");
info!("Ping | {}", info);
ping.lock().unwrap().msg = info;
let percent = (100 / (NODE_IPS.len() - 1)) as f32 / 3.0;
// Create Node vector
let mut nodes = Vec::new();
// Create JSON request // Create JSON request
let mut get_info = HashMap::new(); let mut get_info = HashMap::new();
@ -131,13 +233,13 @@ impl NodeStruct {
get_info.insert("method", "get_info"); get_info.insert("method", "get_info");
// Misc Settings // Misc Settings
let mut vec: Vec<(u128, NodeEnum)> = Vec::new(); let mut vec: Vec<(NodeEnum, u128)> = Vec::new();
// Create HTTP Client // Create HTTP Client
let timeout_sec = Duration::from_millis(5000); let timeout_sec = Duration::from_millis(5000);
let client = reqwest::blocking::ClientBuilder::new(); let client = ClientBuilder::new();
let client = reqwest::blocking::ClientBuilder::timeout(client, timeout_sec); let client = ClientBuilder::timeout(client, timeout_sec);
let client = reqwest::blocking::ClientBuilder::build(client).unwrap(); let client = ClientBuilder::build(client).unwrap();
for ip in NODE_IPS.iter() { for ip in NODE_IPS.iter() {
// Match IP // Match IP
@ -147,77 +249,81 @@ impl NodeStruct {
CAKE_EU => CakeEu, CAKE_EU => CakeEu,
CAKE_UK => CakeUk, CAKE_UK => CakeUk,
CAKE_US => CakeUs, CAKE_US => CakeUs,
MAJESTICBANK_IS => MajesticBankIs,
MAJESTICBANK_SU => MajesticBankSu,
MONERUJO => Monerujo, MONERUJO => Monerujo,
RINO => Rino, RINO => Rino,
SELSTA => Selsta, SELSTA_1 => Selsta1,
SELSTA_2 => Selsta2,
SETH => Seth, SETH => Seth,
SINGAPORE => Singapore,
SUPPORTXMR => SupportXmr, SUPPORTXMR => SupportXmr,
SUPPORTXMR_IR => SupportXmrIr, SUPPORTXMR_IR => SupportXmrIr,
_ => XmrVsBeast, _ => XmrVsBeast,
}; };
// Misc // Misc
let mut timeout = false; let mut timeout = 0;
let mut mid = Duration::new(0, 0); let mut mid = Duration::new(0, 0);
let max = rand::thread_rng().gen_range(2..4);
// Start JSON-RPC request // Start JSON-RPC request
for i in 1..=max { for i in 1..=3 {
ping.lock().unwrap().msg = format!("{}: {} [{}/3]", id, ip, i);
let now = Instant::now(); let now = Instant::now();
let http = "http://".to_owned() + &**ip + "/json_rpc"; let http = "http://".to_string() + &**ip + "/json_rpc";
match client.post(http).json(&get_info).send() { match client.post(http).json(&get_info).send() {
Ok(_) => mid += now.elapsed(), Ok(_) => mid += now.elapsed(),
Err(err) => { Err(err) => {
error!("Timeout on [{:#?}: {}] (over 5 seconds) | {}", id, ip, err);
mid += timeout_sec; mid += timeout_sec;
timeout = true; timeout += 1;
let error = format!("Timeout [{}/3] ... {:#?} ... {}", timeout, id, ip);
error!("Ping | {}", error);
ping.lock().unwrap().msg = error;
}, },
}; };
ping.lock().unwrap().prog += percent;
} }
// Calculate average // Calculate average
let ms = mid.as_millis() / 3; let ms = mid.as_millis() / 3;
vec.push((ms, id)); vec.push((id, ms));
info!("{}ms ... {} calls ... {}", ms, max, ip); let info = format!("{}ms ... {}: {}", ms, id, ip);
info!("Ping | {}", info);
ping.lock().unwrap().msg = format!("{}", info);
let color: Color32; let color: Color32;
if timeout == true { if timeout == 3 {
color = Color32::BLACK color = Color32::BLACK;
} else if ms >= 1000 { } else if ms >= 1000 {
color = Color32::LIGHT_RED // RED
color = Color32::from_rgb(230, 50, 50);
} else if ms >= 300 { } else if ms >= 300 {
color = Color32::LIGHT_YELLOW // YELLOW
color = Color32::from_rgb(230, 230, 100);
} else { } else {
color = Color32::LIGHT_GREEN // GREEN
} color = Color32::from_rgb(100, 230, 100);
match id {
C3pool => { nodes.c3pool.ms = ms; nodes.c3pool.color = color; },
Cake => { nodes.cake.ms = ms; nodes.cake.color = color; },
CakeEu => { nodes.cake_eu.ms = ms; nodes.cake_eu.color = color; },
CakeUk => { nodes.cake_uk.ms = ms; nodes.cake_uk.color = color; },
CakeUs => { nodes.cake_us.ms = ms; nodes.cake_us.color = color; },
Monerujo => { nodes.monerujo.ms = ms; nodes.monerujo.color = color; },
Rino => { nodes.rino.ms = ms; nodes.rino.color = color; },
Selsta => { nodes.selsta.ms = ms; nodes.selsta.color = color; },
Seth => { nodes.seth.ms = ms; nodes.seth.color = color; },
SupportXmr => { nodes.supportxmr.ms = ms; nodes.supportxmr.color = color; },
SupportXmrIr => { nodes.supportxmr_ir.ms = ms; nodes.supportxmr_ir.color = color; },
XmrVsBeast => { nodes.xmrvsbeast.ms = ms; nodes.xmrvsbeast.color = color; },
} }
nodes.push(NodeData { id, ip, ms, color })
} }
let percent = (100.0 - ping.lock().unwrap().prog) / 2.0;
ping.lock().unwrap().prog += percent;
ping.lock().unwrap().msg = "Calculating fastest node".to_string();
// Calculate fastest out of all nodes // Calculate fastest out of all nodes
let mut best_ms: u128 = vec[0].0; let mut fastest: NodeEnum = vec[0].0;
let mut fastest: NodeEnum = vec[0].1; let mut best_ms: u128 = vec[0].1;
for (ms, id) in vec.iter() { for (id, ms) in vec.iter() {
if ms < &best_ms { if ms < &best_ms {
fastest = *id; fastest = *id;
best_ms = *ms; best_ms = *ms;
} }
} }
// These values have weird behavior. let info = format!("Fastest node: {}ms ... {} @ {}", best_ms, fastest, enum_to_ip(fastest));
// The values don't update if not printed beforehand, let percent = (100.0 - ping.lock().unwrap().prog) / 2.0;
// so the match below on [fastest] gets funky. info!("Ping | {}", info);
info!("Fastest node ... {:#?} @ {:#?}ms", fastest, best_ms); ping.lock().unwrap().prog = 100.0;
info!("Community node ping ... OK"); ping.lock().unwrap().msg = info;
PingResult { nodes, fastest, } ping.lock().unwrap().pinging = false;
} ping.lock().unwrap().pinged = true;
info!("Ping ... OK");
PingResult { nodes, fastest }
} }

View file

@ -17,26 +17,163 @@
use crate::App; use crate::App;
use crate::constants::*; use crate::constants::*;
use crate::state::P2pool; use crate::state::*;
use crate::node::NodeEnum; use crate::node::*;
use crate::node::{RINO,SETH,SELSTA}; use crate::node::NodeEnum::*;
use std::sync::{Arc,Mutex};
// pub simple: bool, use std::thread;
// pub mini: bool, use log::*;
// pub out_peers: u8, use egui::{TextEdit,SelectableLabel,ComboBox,Label};
// pub in_peers: u8, use egui::TextStyle::*;
// pub log_level: u8, use egui::FontFamily::Proportional;
// pub node: crate::node::NodeEnum, use egui::{FontId,Button,Color32,RichText};
// pub monerod: String, use regex::Regex;
// pub rpc: u16,
// pub zmq: u16,
// pub address: String,
impl P2pool { impl P2pool {
pub fn show(&mut self, width: f32, height: f32, ctx: &egui::Context, ui: &mut egui::Ui) { pub fn show(&mut self, og: &Arc<Mutex<State>>, online: bool, ping: &Arc<Mutex<Ping>>, addr_regex: &Regex, width: f32, height: f32, ctx: &egui::Context, ui: &mut egui::Ui) {
let text_edit = height / 20.0;
// Console
ui.group(|ui| {
let height = height / SPACE;
let width = width - SPACE;
ui.add_sized([width, height*3.0], TextEdit::multiline(&mut "".to_string()));
ui.add_sized([width, text_edit], TextEdit::hint_text(TextEdit::singleline(&mut "".to_string()), r#"Type a command (e.g "help" or "status") and press Enter"#));
});
let height = ui.available_height();
// [Simple]
if self.simple {
// [Node]
let height = height / 6.0;
ui.spacing_mut().slider_width = width - 8.0;
ui.spacing_mut().icon_width = width / 25.0;
ui.vertical(|ui| {
ui.horizontal(|ui| {
// [Ping List]
let id = og.lock().unwrap().p2pool.node;
let ip = enum_to_ip(id);
let mut ms = 0;
let mut color = Color32::LIGHT_GRAY;
for data in ping.lock().unwrap().nodes.iter() {
if data.id == id {
ms = data.ms;
color = data.color;
break
}
}
let text = RichText::new(format!("{}ms | {} | {}", ms, id, ip)).color(color);
ComboBox::from_id_source("nodes").selected_text(RichText::text_style(text, Monospace)).show_ui(ui, |ui| {
for data in ping.lock().unwrap().nodes.iter() {
let ms = crate::node::format_ms(data.ms);
let id = crate::node::format_enum(data.id);
let text = RichText::text_style(RichText::new(format!("{} | {} | {}", ms, id, data.ip)).color(data.color), Monospace);
ui.selectable_value(&mut og.lock().unwrap().p2pool.node, data.id, text);
}
});
});
ui.add_space(5.0);
ui.horizontal(|ui| {
let width = (width/2.0)-4.0;
// [Select fastest node]
if ui.add_sized([width, height], Button::new("Select fastest node")).on_hover_text(P2POOL_SELECT_FASTEST).clicked() {
let pinged = ping.lock().unwrap().pinged;
let fastest = ping.lock().unwrap().fastest;
if pinged && og.lock().unwrap().p2pool.node != fastest {
og.lock().unwrap().p2pool.node = ping.lock().unwrap().fastest;
og.lock().unwrap().save();
}
}
// [Ping Button]
ui.set_enabled(!ping.lock().unwrap().pinging);
if ui.add_sized([width, height], Button::new("Ping community nodes")).on_hover_text(P2POOL_PING).clicked() {
let ping = Arc::clone(&ping);
let og_clone = Arc::clone(og);
ping.lock().unwrap().pinging = true;
thread::spawn(move|| {
info!("Spawning ping thread...");
let ping_result = crate::node::ping(ping.clone());
ping.lock().unwrap().nodes = ping_result.nodes;
ping.lock().unwrap().fastest = ping_result.fastest;
if og_clone.lock().unwrap().p2pool.auto_select {
og_clone.lock().unwrap().p2pool.node = ping_result.fastest;
og_clone.lock().unwrap().save();
}
});
}});
ui.vertical(|ui| {
let height = height / 2.0;
let pinging = ping.lock().unwrap().pinging;
ui.set_enabled(pinging);
let prog = ping.lock().unwrap().prog.round();
let msg = RichText::text_style(RichText::new(format!("{} ... {}%", ping.lock().unwrap().msg, prog)), Monospace);
let height = height / 1.25;
ui.add_space(5.0);
ui.add_sized([width, height], Label::new(msg));
ui.add_space(5.0);
if pinging {
ui.add_sized([width, height], egui::Spinner::new().size(height));
} else {
ui.add_sized([width, height], egui::Label::new("..."));
}
ui.add_sized([width, height], egui::ProgressBar::new(prog.round()/100.0));
ui.add_space(5.0);
});
});
ui.group(|ui| {
ui.horizontal(|ui| {
let width = (width/2.0)-(SPACE*1.5);
// [Auto-node] + [Auto-select]
let mut style = (*ctx.style()).clone();
style.spacing.icon_width_inner = height/1.5;
style.spacing.icon_width = height;
style.spacing.icon_spacing = 20.0;
ctx.set_style(style);
ui.add_sized([width, height], egui::Checkbox::new(&mut self.auto_select, "Auto-select")).on_hover_text(P2POOL_AUTO_SELECT);
ui.separator();
ui.add_sized([width, height], egui::Checkbox::new(&mut self.auto_node, "Auto-node")).on_hover_text(P2POOL_AUTO_NODE);
})});
// [Address]
let height = ui.available_height();
ui.horizontal(|ui| {
let width = width / 100.0;
ui.add_sized([width*6.0, height], Label::new("Address"));
if self.address.is_empty() {
ui.add_sized([width, height], Label::new(RichText::new("").color(Color32::LIGHT_GRAY)));
} else if self.address.len() == 95 && Regex::is_match(addr_regex, &self.address) {
ui.add_sized([width, height], Label::new(RichText::new("").color(Color32::from_rgb(100, 230, 100))));
} else {
ui.add_sized([width, height], Label::new(RichText::new("").color(Color32::from_rgb(230, 50, 50))));
}
ui.spacing_mut().text_edit_width = (width*9.0)-(SPACE*2.5);
ui.style_mut().override_text_style = Some(Monospace);
ui.add_sized([ui.available_width(), text_edit], TextEdit::hint_text(TextEdit::singleline(&mut self.address), "4...")).on_hover_text(P2POOL_ADDRESS);
});
// ui.horizontal(|ui| {
// ui.add_sized([width, height/2.0], Label::new("Address:"));
// ui.add_sized([width, height], TextEdit::multiline(&mut self.address));
// })});
// [Advanced]
} else {
// TODO: // TODO:
// ping code // ping code
// If ping was pressed, start thread
// if self.ping {
// self.ping = false;
// self.pinging = Arc::new(Mutex::new(true));
// let node_clone = Arc::clone(&self.node);
// let pinging_clone = Arc::clone(&self.pinging);
// thread::spawn(move|| {
// let result = NodeStruct::ping();
// *node_clone.lock().unwrap() = result.nodes;
// *pinging_clone.lock().unwrap() = false;
// });
// }
// If ping-ING, display stats // If ping-ING, display stats
// if *self.pinging.lock().unwrap() { // if *self.pinging.lock().unwrap() {
// egui::CentralPanel::default().show(ctx, |ui| { // egui::CentralPanel::default().show(ctx, |ui| {
@ -58,14 +195,7 @@ impl P2pool {
// return // return
// } // }
let height = ui.available_height() / 10.0; let width = width - 30.0;
let mut width = ui.available_width() - 50.0;
ui.group(|ui| {
ui.add_sized([width, height*4.0], egui::TextEdit::multiline(&mut "".to_owned()));
ui.add_sized([width, 30.0], egui::TextEdit::singleline(&mut "".to_owned()));
});
width = width - 30.0;
let mut style = (*ctx.style()).clone(); let mut style = (*ctx.style()).clone();
let height = ui.available_height()/1.2; let height = ui.available_height()/1.2;
ui.horizontal(|ui| { ui.horizontal(|ui| {
@ -105,7 +235,7 @@ impl P2pool {
egui::ComboBox::from_label(self.node.to_string()).selected_text(RINO).show_ui(ui, |ui| { egui::ComboBox::from_label(self.node.to_string()).selected_text(RINO).show_ui(ui, |ui| {
ui.selectable_value(&mut self.node, NodeEnum::Rino, RINO); ui.selectable_value(&mut self.node, NodeEnum::Rino, RINO);
ui.selectable_value(&mut self.node, NodeEnum::Seth, SETH); ui.selectable_value(&mut self.node, NodeEnum::Seth, SETH);
ui.selectable_value(&mut self.node, NodeEnum::Selsta, SELSTA); ui.selectable_value(&mut self.node, NodeEnum::Selsta1, SELSTA_1);
}); });
// ); // );
}); });
@ -139,3 +269,4 @@ impl P2pool {
})}); })});
} }
} }
}

View file

@ -61,6 +61,8 @@ impl State {
p2pool: P2pool { p2pool: P2pool {
simple: true, simple: true,
mini: true, mini: true,
auto_node: true,
auto_select: true,
out_peers: 10, out_peers: 10,
in_peers: 10, in_peers: 10,
log_level: 3, log_level: 3,
@ -311,6 +313,8 @@ pub struct Gupax {
pub struct P2pool { pub struct P2pool {
pub simple: bool, pub simple: bool,
pub mini: bool, pub mini: bool,
pub auto_node: bool,
pub auto_select: bool,
pub out_peers: u16, pub out_peers: u16,
pub in_peers: u16, pub in_peers: u16,
pub log_level: u8, pub log_level: u8,