mirror of
https://code.gri.mw/GUI/grim.git
synced 2026-07-04 05:57:29 +00:00
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:
Generated
+1343
-1043
File diff suppressed because it is too large
Load Diff
+33
-66
@@ -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]
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user