diff --git a/Cargo.lock b/Cargo.lock index 24f0631a..13d399bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -740,6 +740,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "async-socks5" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da2537846e16b96d2972ee52a3b355663872a1a687ce6d57a3b6f6b6a181c89" +dependencies = [ + "thiserror 1.0.69", + "tokio 1.45.1", +] + [[package]] name = "async-task" version = "4.7.1" @@ -943,6 +953,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "base64" version = "0.22.1" @@ -2820,12 +2836,6 @@ dependencies = [ "zune-inflate", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "fallible-iterator" version = "0.3.0" @@ -3513,6 +3523,7 @@ dependencies = [ "arboard", "arti-client", "backtrace", + "bytes 1.10.1", "chrono", "curve25519-dalek 4.1.3", "dirs 6.0.0", @@ -3537,8 +3548,13 @@ dependencies = [ "grin_wallet_impls", "grin_wallet_libwallet", "grin_wallet_util", + "http-body-util", "hyper 0.14.32", - "hyper-tls 0.5.0", + "hyper 1.6.0", + "hyper-proxy2", + "hyper-socks2", + "hyper-tls 0.6.0", + "hyper-util", "image", "interprocess", "jni", @@ -3839,9 +3855,8 @@ dependencies = [ [[package]] name = "grin_wallet_api" -version = "5.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e91d09af566e34c045dc398a862ae947446acf05274193f75511db2972b1ae" +version = "5.4.0-alpha.1" +source = "git+https://github.com/ardocrat/grin-wallet?branch=wallet_node_client_proxy#bb85ffff7f4f2b129ede72e0423449e924a528c0" dependencies = [ "base64 0.12.3", "chrono", @@ -3865,9 +3880,8 @@ dependencies = [ [[package]] name = "grin_wallet_config" -version = "5.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9ba1884188e89acfdb1896e929b1327c77a8c04c9294b5b2cc784fbb207c8e8" +version = "5.4.0-alpha.1" +source = "git+https://github.com/ardocrat/grin-wallet?branch=wallet_node_client_proxy#bb85ffff7f4f2b129ede72e0423449e924a528c0" dependencies = [ "dirs 2.0.2", "grin_core", @@ -3881,9 +3895,8 @@ dependencies = [ [[package]] name = "grin_wallet_controller" -version = "5.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac2140d873e1c86cc984aac4b01ca001ee62ce71d48ffb62d5820147082db6d" +version = "5.4.0-alpha.1" +source = "git+https://github.com/ardocrat/grin-wallet?branch=wallet_node_client_proxy#bb85ffff7f4f2b129ede72e0423449e924a528c0" dependencies = [ "chrono", "easy-jsonrpc-mw", @@ -3916,9 +3929,8 @@ dependencies = [ [[package]] name = "grin_wallet_impls" -version = "5.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c40acf16a81fe60fb2a4bb6630b85d28e6904f87ddb512749d2e2124f6352" +version = "5.4.0-alpha.1" +source = "git+https://github.com/ardocrat/grin-wallet?branch=wallet_node_client_proxy#bb85ffff7f4f2b129ede72e0423449e924a528c0" dependencies = [ "base64 0.12.3", "blake2-rfc", @@ -3956,9 +3968,8 @@ dependencies = [ [[package]] name = "grin_wallet_libwallet" -version = "5.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dfcdeb1b13dfca419d930b83357d72b2b76dfa9b41f3942b13646f57c57b9b" +version = "5.4.0-alpha.1" +source = "git+https://github.com/ardocrat/grin-wallet?branch=wallet_node_client_proxy#bb85ffff7f4f2b129ede72e0423449e924a528c0" dependencies = [ "age", "base64 0.9.3", @@ -3966,6 +3977,7 @@ dependencies = [ "blake2-rfc", "bs58", "byteorder", + "chacha20", "chrono", "curve25519-dalek 2.1.3", "ed25519-dalek 1.0.1", @@ -3975,6 +3987,7 @@ dependencies = [ "grin_util", "grin_wallet_config", "grin_wallet_util", + "hmac 0.12.1", "lazy_static", "log", "num-bigint 0.2.6", @@ -3984,7 +3997,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "sha2 0.8.2", + "sha2 0.10.9", "strum 0.18.0", "strum_macros 0.18.0", "thiserror 1.0.69", @@ -3994,9 +4007,8 @@ dependencies = [ [[package]] name = "grin_wallet_util" -version = "5.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d253707c5cb3ee35b06f4b688a81e9916a0e37302cf3f7d855e109696cdf0d7c" +version = "5.4.0-alpha.1" +source = "git+https://github.com/ardocrat/grin-wallet?branch=wallet_node_client_proxy#bb85ffff7f4f2b129ede72e0423449e924a528c0" dependencies = [ "data-encoding", "ed25519-dalek 1.0.1", @@ -4070,6 +4082,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" +dependencies = [ + "atomic-waker", + "bytes 1.10.1", + "fnv", + "futures-core", + "futures-sink", + "http 1.3.1", + "indexmap 2.9.0", + "slab", + "tokio 1.45.1", + "tokio-util 0.7.15", + "tracing", +] + [[package]] name = "half" version = "2.6.0" @@ -4116,6 +4147,30 @@ dependencies = [ "hashbrown 0.14.5", ] +[[package]] +name = "headers" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" +dependencies = [ + "base64 0.21.7", + "bytes 1.10.1", + "headers-core", + "http 1.3.1", + "httpdate 1.0.3", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http 1.3.1", +] + [[package]] name = "heck" version = "0.3.3" @@ -4251,6 +4306,29 @@ dependencies = [ "pin-project-lite 0.2.16", ] +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes 1.10.1", + "http 1.3.1", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes 1.10.1", + "futures-core", + "http 1.3.1", + "http-body 1.0.1", + "pin-project-lite 0.2.16", +] + [[package]] name = "httparse" version = "1.10.1" @@ -4333,6 +4411,47 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes 1.10.1", + "futures-channel", + "futures-util", + "h2 0.4.10", + "http 1.3.1", + "http-body 1.0.1", + "httparse", + "httpdate 1.0.3", + "itoa 1.0.15", + "pin-project-lite 0.2.16", + "smallvec", + "tokio 1.45.1", + "want", +] + +[[package]] +name = "hyper-proxy2" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9043b7b23fb0bc4a1c7014c27b50a4fc42cc76206f71d34fc0dfe5b28ddc3faf" +dependencies = [ + "bytes 1.10.1", + "futures-util", + "headers", + "http 1.3.1", + "hyper 1.6.0", + "hyper-tls 0.6.0", + "hyper-util", + "native-tls", + "pin-project-lite 0.2.16", + "tokio 1.45.1", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-rustls" version = "0.20.0" @@ -4367,6 +4486,22 @@ dependencies = [ "webpki", ] +[[package]] +name = "hyper-socks2" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51c227614c208f7e7c2e040526912604a1a957fe467c9c2f5b06c5d032337dab" +dependencies = [ + "async-socks5", + "http 1.3.1", + "hyper 1.6.0", + "hyper-tls 0.6.0", + "hyper-util", + "thiserror 1.0.69", + "tokio 1.45.1", + "tower-service", +] + [[package]] name = "hyper-timeout" version = "0.3.1" @@ -4394,15 +4529,39 @@ dependencies = [ [[package]] name = "hyper-tls" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes 1.10.1", - "hyper 0.14.32", + "http-body-util", + "hyper 1.6.0", + "hyper-util", "native-tls", "tokio 1.45.1", "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" +dependencies = [ + "bytes 1.10.1", + "futures-channel", + "futures-core", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.6.0", + "libc", + "pin-project-lite 0.2.16", + "socket2 0.5.10", + "tokio 1.45.1", + "tower-service", + "tracing", ] [[package]] @@ -8287,18 +8446,6 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "sha2" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - [[package]] name = "sha2" version = "0.9.9" diff --git a/Cargo.toml b/Cargo.toml index 66163b0e..f30f1452 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ panic = "abort" [dependencies] log = "0.4.27" -## node +## grin grin_api = "5.3.3" grin_chain = "5.3.3" grin_config = "5.3.3" @@ -37,12 +37,34 @@ grin_servers = "5.3.3" grin_keychain = "5.3.3" grin_util = "5.3.3" -## 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" +#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" + +# local +#grin_api = { path = "../grin/api" } +#grin_chain = { path = "../grin/chain" } +#grin_config = { path = "../grin/config" } +#grin_core = { path = "../grin/core" } +#grin_p2p = { path = "../grin/p2p" } +#grin_servers = { path = "../grin/servers" } +#grin_keychain = { path = "../grin/keychain" } +#grin_util = { path = "../grin/util" } + +#grin_wallet_impls = { path = "../grin-wallet/impls" } +#grin_wallet_api = { path = "../grin-wallet/api"} +#grin_wallet_libwallet = { path = "../grin-wallet/libwallet" } +#grin_wallet_util = { path = "../grin-wallet/util" } +#grin_wallet_controller = { path = "../grin-wallet/controller" } + +# test +grin_wallet_impls = { git = "https://github.com/ardocrat/grin-wallet", branch = "wallet_node_client_proxy" } +grin_wallet_api = { git = "https://github.com/ardocrat/grin-wallet", branch = "wallet_node_client_proxy" } +grin_wallet_libwallet = { git = "https://github.com/ardocrat/grin-wallet", branch = "wallet_node_client_proxy" } +grin_wallet_util = { git = "https://github.com/ardocrat/grin-wallet", branch = "wallet_node_client_proxy" } +grin_wallet_controller = { git = "https://github.com/ardocrat/grin-wallet", branch = "wallet_node_client_proxy" } ## ui egui = { version = "0.31.1", default-features = false } @@ -77,6 +99,13 @@ gif = "0.13.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"] } +http-body-util = "0.1.3" +bytes = "1.10.1" +hyper-socks2 = "0.9.1" +hyper-proxy2 = "0.1.0" +hyper-tls = "0.6.0" ## tor arti-client = { version = "0.30.0", features = ["pt-client", "static", "onion-service-service", "onion-service-client"] } @@ -93,7 +122,6 @@ sha2 = "0.10.8" ed25519-dalek = "2.1.1" curve25519-dalek = "4.1.3" hyper-tor = { version = "0.14.32", features = ["full"], package = "hyper" } -hyper-tls = "0.5.0" tls-api = "0.12.0" tls-api-native-tls = "0.12.1" diff --git a/src/http/client.rs b/src/http/client.rs new file mode 100644 index 00000000..6f9a189f --- /dev/null +++ b/src/http/client.rs @@ -0,0 +1,64 @@ +// Copyright 2025 The Grim Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use bytes::Bytes; +use http_body_util::Full; +use hyper::body::Incoming; +use hyper::{Request, Response}; +use hyper_proxy2::{Intercept, Proxy, ProxyConnector}; +use hyper_tls::HttpsConnector; +use hyper_util::client::legacy::{Client, Error}; +use hyper_util::client::legacy::connect::HttpConnector; +use hyper_util::rt::TokioExecutor; + +use crate::AppConfig; + +/// Handles http requests. +pub struct HttpClient { +} + +impl HttpClient { + /// Send request. + pub async fn send(req: Request>) -> Result, Error> { + let res = if AppConfig::use_proxy() { + if let Some(url) = AppConfig::socks_proxy_url() { + let mut connector = HttpConnector::new(); + connector.enforce_http(false); + let uri = url.parse().unwrap(); + let proxy = hyper_socks2::SocksConnector { + proxy_addr: uri, + auth: None, + connector, + }; + let client = Client::builder(TokioExecutor::new()) + .build::<_, Full>(proxy); + client.request(req).await + } else { + let url = AppConfig::http_proxy_url().unwrap(); + let uri = url.parse().unwrap(); + let proxy = Proxy::new(Intercept::All, uri); + let connector = HttpConnector::new(); + let proxy_connector = ProxyConnector::from_proxy(connector, proxy).unwrap(); + let client = Client::builder(TokioExecutor::new()) + .build::<_, Full>(proxy_connector); + client.request(req).await + } + } else { + let client = Client::builder(TokioExecutor::new()) + .build::<_, Full>(HttpsConnector::new()); + client.request(req).await + }; + res + } +} \ No newline at end of file diff --git a/src/http/mod.rs b/src/http/mod.rs new file mode 100644 index 00000000..f9f1e7f7 --- /dev/null +++ b/src/http/mod.rs @@ -0,0 +1,16 @@ +// Copyright 2025 The Grim Developers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +mod client; +pub use client::*; \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 4cccb4a9..7f7e1088 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,6 +38,7 @@ mod node; mod wallet; mod tor; mod settings; +mod http; pub mod gui; pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/src/wallet/connections/external.rs b/src/wallet/connections/external.rs index 9b6da896..d7797929 100644 --- a/src/wallet/connections/external.rs +++ b/src/wallet/connections/external.rs @@ -16,6 +16,7 @@ use grin_core::global::ChainTypes; use grin_util::to_base64; use serde_derive::{Deserialize, Serialize}; +use crate::http::HttpClient; use crate::wallet::ConnectionsConfig; /// External connection for the wallet. @@ -34,13 +35,15 @@ pub struct ExternalConnection { } /// Default external node URL for main network. -const DEFAULT_MAIN_URLS: [&'static str; 2] = [ +const DEFAULT_MAIN_URLS: [&'static str; 3] = [ + "https://main.gri.mw", "https://grincoin.org", "https://grinnode.live:3413" ]; /// Default external node URL for main network. -const DEFAULT_TEST_URLS: [&'static str; 1] = [ +const DEFAULT_TEST_URLS: [&'static str; 2] = [ + "https://test.gri.mw", "https://testnet.grincoin.org" ]; @@ -101,11 +104,8 @@ fn check_ext_conn(conn: &ExternalConnection, ui_ctx: &egui::Context) { let url = url::Url::parse(conn.url.as_str()).unwrap(); if let Ok(_) = url.socket_addrs(|| None) { let addr = format!("{}v2/foreign", url.to_string()); - // Setup http client. - let client = hyper_tor::Client::builder() - .build::<_, hyper_tor::Body>(hyper_tls::HttpsConnector::new()); - let mut req_setup = hyper_tor::Request::builder() - .method(hyper_tor::Method::POST) + let mut req_setup = hyper::Request::builder() + .method(hyper::Method::POST) .uri(addr.clone()); // Setup secret key auth. if let Some(key) = conn.secret { @@ -114,13 +114,13 @@ fn check_ext_conn(conn: &ExternalConnection, ui_ctx: &egui::Context) { to_base64(&format!("grin:{}", key)) ); req_setup = req_setup - .header(hyper_tor::header::AUTHORIZATION, basic_auth.clone()); + .header(hyper::header::AUTHORIZATION, basic_auth.clone()); } - let req = req_setup.body(hyper_tor::Body::from( + let req = req_setup.body(http_body_util::Full::from( r#"{"id":1,"jsonrpc":"2.0","method":"get_version","params":{} }"#) ).unwrap(); // Send request. - match client.request(req).await { + match HttpClient::send(req).await { Ok(res) => { let status = res.status().as_u16(); // Available on 200 HTTP status code. diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index a5482e6e..421ed72a 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -187,7 +187,28 @@ impl Wallet { } else { integrated() }; - Ok(HTTPNodeClient::new(&node_api_url, node_secret)?) + let client = if AppConfig::use_proxy() { + let socks = AppConfig::use_socks_proxy(); + let url = if socks { + AppConfig::socks_proxy_url() + } else { + AppConfig::http_proxy_url() + }.unwrap_or("".to_string()); + let res = url.replace("http://", "").replace("socks5://", "").parse(); + if let Ok(addr) = res { + let scheme = if socks { + "socks5://" + } else { + "http://" + }; + HTTPNodeClient::new_proxy(&node_api_url, node_secret, Some((addr, scheme)))? + } else { + HTTPNodeClient::new_proxy(&node_api_url, node_secret, None)? + } + } else { + HTTPNodeClient::new_proxy(&node_api_url, node_secret, None)? + }; + Ok(client) } /// Create [`WalletInstance`] from provided [`WalletConfig`].