fix: check wallet state from node, build: update common deps, tor: optimize running service check, p2p: async peer saving, update seeds

- Update common dependencies
- Optimize check of running Tor service
- Async peer saving
- Add mainnet and testnet seeds
- Remove grinnode.live from default external connections

Reviewed-on: https://code.gri.mw/GUI/grim/pulls/43
This commit is contained in:
ardocrat
2026-02-10 11:54:59 +00:00
parent 86d4fde77d
commit 3a23438e17
10 changed files with 1487 additions and 1174 deletions
Generated
+1343 -1043
View File
File diff suppressed because it is too large Load Diff
+33 -66
View File
@@ -27,27 +27,7 @@ panic = "abort"
[dependencies]
log = "0.4.27"
## grin node
#grin_api = "5.3.3"
#grin_chain = "5.3.3"
#grin_config = "5.3.3"
#grin_core = "5.3.3"
#grin_p2p = "5.3.3"
#grin_servers = "5.3.3"
#grin_keychain = "5.3.3"
#grin_util = "5.3.3"
# test
#grin_api = { git = "https://code.gri.mw/ardocrat/node", rev = "a3ee15a8b27216cd2ff4b3b99894cd98dd33fa7e" }
#grin_chain = { git = "https://code.gri.mw/ardocrat/node", rev = "a3ee15a8b27216cd2ff4b3b99894cd98dd33fa7e" }
#grin_config = { git = "https://code.gri.mw/ardocrat/node", rev = "a3ee15a8b27216cd2ff4b3b99894cd98dd33fa7e" }
#grin_core = { git = "https://code.gri.mw/ardocrat/node", rev = "a3ee15a8b27216cd2ff4b3b99894cd98dd33fa7e" }
#grin_p2p = { git = "https://code.gri.mw/ardocrat/node", rev = "a3ee15a8b27216cd2ff4b3b99894cd98dd33fa7e" }
#grin_servers = { git = "https://code.gri.mw/ardocrat/node", rev = "a3ee15a8b27216cd2ff4b3b99894cd98dd33fa7e" }
#grin_keychain = { git = "https://code.gri.mw/ardocrat/node", rev = "a3ee15a8b27216cd2ff4b3b99894cd98dd33fa7e" }
#grin_util = { git = "https://code.gri.mw/ardocrat/node", rev = "a3ee15a8b27216cd2ff4b3b99894cd98dd33fa7e" }
# local
# node
grin_api = { path = "node/api" }
grin_chain = { path = "node/chain" }
grin_config = { path = "node/config" }
@@ -57,21 +37,7 @@ grin_servers = { path = "node/servers" }
grin_keychain = { path = "node/keychain" }
grin_util = { path = "node/util" }
## grin wallet
#grin_wallet_impls = "5.3.3"
#grin_wallet_api = "5.3.3"
#grin_wallet_libwallet = "5.3.3"
#grin_wallet_util = "5.3.3"
#grin_wallet_controller = "5.3.3"
# test
#grin_wallet_impls = { git = "https://code.gri.mw/ardocrat/wallet", rev = "8c9171e640f4a95bec7e22d9acb1725ebb2e30a1" }
#grin_wallet_api = { git = "https://code.gri.mw/ardocrat/wallet", rev = "8c9171e640f4a95bec7e22d9acb1725ebb2e30a1" }
#grin_wallet_libwallet = { git = "https://code.gri.mw/ardocrat/wallet", rev = "8c9171e640f4a95bec7e22d9acb1725ebb2e30a1" }
#grin_wallet_util = { git = "https://code.gri.mw/ardocrat/wallet", rev = "8c9171e640f4a95bec7e22d9acb1725ebb2e30a1" }
#grin_wallet_controller = { git = "https://code.gri.mw/ardocrat/wallet", rev = "8c9171e640f4a95bec7e22d9acb1725ebb2e30a1" }
# local
# wallet
grin_wallet_impls = { path = "wallet/impls" }
grin_wallet_api = { path = "wallet/api"}
grin_wallet_libwallet = { path = "wallet/libwallet" }
@@ -79,58 +45,59 @@ grin_wallet_util = { path = "wallet/util" }
grin_wallet_controller = { path = "wallet/controller" }
## ui
egui = { version = "0.33.0", default-features = false }
egui_extras = { version = "0.33.0", features = ["image", "svg"] }
egui = { version = "0.33.3", default-features = false }
egui_extras = { version = "0.33.3", features = ["image", "svg"] }
egui-async = "0.3.4"
rust-i18n = "2.3.1"
## other
anyhow = "1.0.97"
pin-project = "1.1.10"
backtrace = "0.3.74"
thiserror = "1.0.64"
backtrace = "0.3.76"
thiserror = "2.0.18"
futures = "0.3.31"
dirs = "6.0.0"
sys-locale = "0.3.1"
chrono = "0.4.38"
sys-locale = "0.3.2"
chrono = "0.4.43"
parking_lot = "0.12.3"
lazy_static = "1.5.0"
toml = "0.8.19"
serde = "1.0.210"
local-ip-address = "0.6.3"
url = "2.5.2"
rand = "0.9.0"
serde_derive = "1.0.219"
serde_json = "1.0.140"
tokio = { version = "1.44.1", features = ["full"] }
image = "0.25.6"
rqrr = "0.8.0"
toml = "0.9.11+spec-1.1.0"
serde = "1.0.228"
local-ip-address = "0.6.9"
url = "2.5.8"
rand = "0.9.2"
serde_derive = "1.0.228"
serde_json = "1.0.149"
tokio = { version = "1.49.0", features = ["full"] }
image = "0.25.9"
rqrr = "0.10.1"
qrcodegen = "1.8.0"
qrcode = "0.14.1"
ur = "0.4.1"
gif = "0.13.1"
gif = "0.14.1"
rkv = { version = "0.19.0", features = ["lmdb"] }
usvg = "0.45.1"
ring = "0.16.20"
hyper = { version = "1.6.0", features = ["full"], package = "hyper" }
hyper-util = { version = "0.1.11", features = ["http1", "client", "client-legacy"] }
hyper-util = { version = "0.1.19", features = ["http1", "client", "client-legacy"] }
http-body-util = "0.1.3"
bytes = "1.10.1"
bytes = "1.11.0"
hyper-socks2 = "0.9.1"
hyper-proxy2 = "0.1.0"
hyper-tls = "0.6.0"
async-std = "1.13.2"
## tor
arti-client = { version = "0.36.0", features = ["pt-client", "static", "onion-service-service", "onion-service-client"] }
tor-rtcompat = { version = "0.36.0", features = ["static"] }
tor-config = "0.36.0"
fs-mistrust = "0.13.0"
tor-hsservice = "0.36.0"
tor-hsrproxy = "0.36.0"
tor-keymgr = "0.36.0"
tor-llcrypto = "0.36.0"
tor-hscrypto = "0.36.0"
tor-error = "0.36.0"
arti-client = { version = "0.38.0", features = ["pt-client", "static", "onion-service-service", "onion-service-client"] }
tor-rtcompat = { version = "0.38.0", features = ["static"] }
tor-config = "0.38.0"
fs-mistrust = "0.13.1"
tor-hsservice = "0.38.0"
tor-hsrproxy = "0.38.0"
tor-keymgr = "0.38.0"
tor-llcrypto = "0.38.0"
tor-hscrypto = "0.38.0"
tor-error = "0.38.0"
sha2 = "0.10.8"
ed25519-dalek = "2.1.1"
curve25519-dalek = "4.1.3"
@@ -158,7 +125,7 @@ winit = { version = "0.30.12" }
wgpu = { version = "27.0.1" }
eframe = { version = "0.33.2", features = ["wgpu"] }
arboard = "3.2.0"
rfd = "0.15.0"
rfd = "0.17.2"
interprocess = { version = "2.2.1", features = ["tokio"] }
[target.'cfg(target_os = "android")'.dependencies]
+1
View File
@@ -399,6 +399,7 @@ impl<Platform: PlatformCallbacks> App<Platform> {
/// To draw with egui`s eframe (for wgpu, glow backends and wasm target).
impl<Platform: PlatformCallbacks> eframe::App for App<Platform> {
fn update(&mut self, ctx: &Context, _: &mut eframe::Frame) {
ctx.plugin_or_default::<egui_async::EguiAsyncPlugin>();
self.ui(ctx);
}
+50 -31
View File
@@ -13,6 +13,7 @@
// limitations under the License.
use egui::{Align, Id, Layout, RichText, StrokeKind};
use egui_async::Bind;
use grin_core::global::ChainTypes;
use crate::AppConfig;
@@ -44,8 +45,10 @@ pub struct P2PSetup {
/// Flag to check if p2p port from saved config value is available.
is_port_available: bool,
/// Flag to check if entered peer address is correct and/or available.
is_correct_address_edit: bool,
/// Async check entered peer address.
address_check: Bind<bool, String>,
/// Flag to check if peer is correct and/or available.
address_available: Option<bool>,
/// Peer edit value for modal.
peer_edit: String,
@@ -92,14 +95,15 @@ impl Default for P2PSetup {
.iter()
.map(|s| s.to_string())
.collect();
let default_test_seeds = grin_servers::TESTNET_DNS_SEEDS
let default_test_seeds = Node::TESTNET_DNS_SEEDS
.into_iter()
.map(|s| s.to_string())
.collect();
Self {
port_edit: port,
port_available_edit: is_port_available,
is_correct_address_edit: true,
address_check: Bind::new(false),
address_available: Some(true),
is_port_available,
peer_edit: "".to_string(),
default_main_seeds,
@@ -192,7 +196,6 @@ impl ContentContainer for P2PSetup {
// Show preferred peers setup.
self.peer_list_ui(ui, &PeerType::Preferred);
ui.add_space(6.0);
View::horizontal_line(ui, Colors::item_stroke());
ui.add_space(6.0);
@@ -377,7 +380,8 @@ impl P2PSetup {
};
View::button(ui, add_text, Colors::white_or_black(false), || {
// Setup values for modal.
self.is_correct_address_edit = true;
self.address_check = Bind::new(false);
self.address_available = Some(true);
self.peer_edit = "".to_string();
// Select modal id.
let modal_id = match peer_type {
@@ -405,26 +409,34 @@ impl P2PSetup {
/// Draw peer creation [`Modal`] content.
fn peer_modal(&mut self, ui: &mut egui::Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
let on_save = |c: &mut P2PSetup| {
// Check if peer is correct and/or available.
let peer = c.peer_edit.clone();
let is_correct_address = PeersConfig::peer_to_addr(peer.clone()).is_some();
c.is_correct_address_edit = is_correct_address;
// Save peer at config.
if is_correct_address {
match modal.id {
CUSTOM_SEED_MODAL => NodeConfig::save_custom_seed(peer),
ALLOW_PEER_MODAL => NodeConfig::allow_peer(peer),
DENY_PEER_MODAL => NodeConfig::deny_peer(peer),
PREFER_PEER_MODAL => NodeConfig::prefer_peer(peer),
&_ => {}
if self.address_available.is_none() {
let peer = self.peer_edit.clone();
if let Some(res) = self.address_check.read_or_request(|| async {
let available = PeersConfig::peer_to_addr(peer).is_some();
Ok(available)
}) {
match res {
Ok(available) => {
self.address_available = Some(*available);
// Save peer at config.
if *available {
let peer = self.peer_edit.clone();
match modal.id {
CUSTOM_SEED_MODAL => NodeConfig::save_custom_seed(peer),
ALLOW_PEER_MODAL => NodeConfig::allow_peer(peer),
DENY_PEER_MODAL => NodeConfig::deny_peer(peer),
PREFER_PEER_MODAL => NodeConfig::prefer_peer(peer),
&_ => {}
}
Modal::close();
}
}
Err(_) => {
self.address_available = Some(false);
}
}
c.is_port_available = true;
Modal::close();
}
};
}
ui.add_space(6.0);
ui.vertical_centered(|ui| {
@@ -437,17 +449,22 @@ impl P2PSetup {
// Draw peer address text edit.
let mut edit = TextEdit::new(Id::from(modal.id)).paste();
if self.address_available.is_none() {
edit = edit.disable();
}
edit.ui(ui, &mut self.peer_edit, cb);
if edit.enter_pressed {
on_save(self);
self.address_available = None;
}
// Show error when specified address is incorrect.
if !self.is_correct_address_edit {
ui.add_space(10.0);
ui.label(RichText::new(t!("network_settings.peer_address_error"))
.size(16.0)
.color(Colors::red()));
if let Some(available) = self.address_available {
if !available {
ui.add_space(10.0);
ui.label(RichText::new(t!("network_settings.peer_address_error"))
.size(16.0)
.color(Colors::red()));
}
}
ui.add_space(12.0);
@@ -465,7 +482,9 @@ impl P2PSetup {
});
columns[1].vertical_centered_justified(|ui| {
View::button(ui, t!("modal.save"), Colors::white_or_black(false), || {
on_save(self);
if self.address_available.is_some() {
self.address_available = None;
}
});
});
});
+1 -1
View File
@@ -179,7 +179,7 @@ impl WalletTransactionsContent {
});
}
if !tx.cancelled() && !tx.cancelling() && !tx.posting() {
if wallet.synced_from_node() && !tx.cancelled() && !tx.cancelling() && !tx.posting() {
let resend = tx.broadcasting_timed_out(wallet);
// Draw button to cancel transaction.
+1 -1
View File
@@ -248,7 +248,7 @@ impl WalletTransactionContent {
return;
}
if !tx.cancelled() && !tx.cancelling() && !tx.posting() {
if wallet.synced_from_node() && !tx.cancelled() && !tx.cancelling() && !tx.posting() {
let rebroadcast = tx.broadcasting_timed_out(&wallet);
// Draw button to cancel transaction.
+13 -2
View File
@@ -87,12 +87,23 @@ impl Node {
/// Default Mainnet DNS Seeds
pub const MAINNET_DNS_SEEDS: &'static[&'static str] = &[
"main.gri.mw",
"grincoin.org",
"mainnet.seed.grin.lesceller.com",
"grinseed.revcore.net",
"mainnet-seed.grinnode.live",
"mainnet.grin.punksec.de",
"grinnode.30-r.com",
"grincoin.org"
"grinnode.30-r.com"
];
/// Default Testnet DNS Seeds
pub const TESTNET_DNS_SEEDS: &'static[&'static str] = &[
"test.gri.mw",
"testnet.grincoin.org",
"floonet.seed.grin.lesceller.com",
"grintestseed.revcore.net",
"testnet.grin.punksec.de",
"testnet.grinnode.30-r.com"
];
/// Stop the [`Server`] and setup exit flag after if needed.
+38 -25
View File
@@ -275,26 +275,26 @@ impl Tor {
.nickname(hs_nickname.clone())
.build()
.unwrap();
if let Ok((service, request)) =
client_thread.launch_onion_service(service_config)
{
// Launch service proxy.
let addr = SocketAddr::new(IpAddr::from(Ipv4Addr::LOCALHOST), port);
tokio::spawn(Self::run_service_proxy(
addr,
client_thread.clone(),
service.clone(),
request,
hs_nickname.clone(),
)).await.unwrap();
// Check service availability.
let addr = service.onion_address()
.unwrap()
.display_unredacted()
.to_string();
let url = format!("http://{}/", addr);
Self::check_service(service_id, client_thread, url, port, key);
return;
if let Ok(res) = client_thread.launch_onion_service(service_config) {
if let Some((service, request)) = res {
// Launch service proxy.
let addr = SocketAddr::new(IpAddr::from(Ipv4Addr::LOCALHOST), port);
tokio::spawn(Self::run_service_proxy(
addr,
client_thread.clone(),
service.clone(),
request,
hs_nickname.clone(),
)).await.unwrap();
// Check service availability.
let addr = service.onion_address()
.unwrap()
.display_unredacted()
.to_string();
let url = format!("http://{}/", addr);
Self::check_service(service_id, client_thread, url, port, key);
return;
}
}
on_error(service_id);
})
@@ -333,11 +333,18 @@ impl Tor {
const MAX_ERRORS: i32 = 3;
let mut errors_count = 0;
loop {
if !Self::is_service_running(&service_id) {
// Remove service from checking.
let mut w_services =
TOR_SERVER_STATE.checking_services.write();
w_services.remove(&service_id);
// Check if service is running.
fn is_running(service_id: &String) -> bool {
let running = Tor::is_service_running(service_id);
if !running {
// Remove service from checking.
let mut w_services =
TOR_SERVER_STATE.checking_services.write();
w_services.remove(service_id);
}
running
}
if !is_running(&service_id) {
break;
}
// Send request.
@@ -354,10 +361,16 @@ impl Tor {
let mut w_services =
TOR_SERVER_STATE.failed_services.write();
w_services.remove(&service_id);
if !is_running(&service_id) {
break;
}
// Check again after 50 seconds.
Duration::from_millis(50000)
}
Err(_) => {
if !is_running(&service_id) {
break;
}
// Restart service on 3rd error.
errors_count += 1;
if errors_count == MAX_ERRORS {
+2 -3
View File
@@ -35,10 +35,9 @@ pub struct ExternalConnection {
}
/// Default external node URL for main network.
const DEFAULT_MAIN_URLS: [&'static str; 3] = [
const DEFAULT_MAIN_URLS: [&'static str; 2] = [
"https://main.gri.mw",
"https://grincoin.org",
"https://grinnode.live:3413"
"https://grincoin.org"
];
/// Default external node URL for main network.
+5 -2
View File
@@ -533,6 +533,7 @@ impl Wallet {
let mut w_conn = conn.write();
*w_conn = wallet_close.get_config().connection();
}
wallet_close.from_node.store(false, Ordering::Relaxed);
// Start sync to exit from thread.
wallet_close.sync();
});
@@ -570,7 +571,7 @@ impl Wallet {
self.sync_error.store(error, Ordering::Relaxed);
}
/// Check if last synchronization finished from node.
/// Check if wallet was synced from node after opening.
pub fn synced_from_node(&self) -> bool {
self.from_node.load(Ordering::Relaxed)
}
@@ -1573,7 +1574,9 @@ fn sync_wallet_data(wallet: &Wallet, from_node: bool) {
// Update wallet transactions.
if update_txs(wallet, instance.clone(), info).is_ok() {
wallet.from_node.store(from_node, Ordering::Relaxed);
if !wallet.from_node.load(Ordering::Relaxed) {
wallet.from_node.store(from_node, Ordering::Relaxed);
}
wallet.reset_sync_attempts();
return;
}