build: update grin 5.3.3, arti 0.23.0 (fork arti-hyper crate) and non-egui dependencies

This commit is contained in:
ardocrat 2024-10-09 12:58:59 +03:00
parent ec7e795ba9
commit 92e5d38755
6 changed files with 1506 additions and 1061 deletions

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
*.iml *.iml
android/.idea
android/.gradle android/.gradle
android/local.properties android/local.properties
android/keystore android/keystore

2201
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -25,25 +25,25 @@ codegen-units = 1
panic = "abort" panic = "abort"
[dependencies] [dependencies]
log = "0.4" log = "0.4.22"
## node ## node
openssl-sys = { version = "0.9.82", features = ["vendored"] } openssl-sys = { version = "0.9.103", features = ["vendored"] }
grin_api = "5.3.1" grin_api = "5.3.3"
grin_chain = "5.3.1" grin_chain = "5.3.3"
grin_config = "5.3.1" grin_config = "5.3.3"
grin_core = "5.3.1" grin_core = "5.3.3"
grin_p2p = "5.3.1" grin_p2p = "5.3.3"
grin_servers = "5.3.1" grin_servers = "5.3.3"
grin_keychain = "5.3.1" grin_keychain = "5.3.3"
grin_util = "5.3.1" grin_util = "5.3.3"
## wallet ## wallet
grin_wallet_impls = "5.3.1" grin_wallet_impls = "5.3.3"
grin_wallet_api = "5.3.1" grin_wallet_api = "5.3.3"
grin_wallet_libwallet = "5.3.1" grin_wallet_libwallet = "5.3.3"
grin_wallet_util = "5.3.1" grin_wallet_util = "5.3.3"
grin_wallet_controller = "5.3.1" grin_wallet_controller = "5.3.3"
## ui ## ui
egui = { version = "0.28.1", default-features = false } egui = { version = "0.28.1", default-features = false }
@ -51,45 +51,47 @@ egui_extras = { version = "0.28.1", features = ["image", "svg"] }
rust-i18n = "2.3.1" rust-i18n = "2.3.1"
## other ## other
backtrace = "0.3" anyhow = "1.0.89"
thiserror = "1.0.58" pin-project = "1.1.6"
futures = "0.3" backtrace = "0.3.74"
thiserror = "1.0.64"
futures = "0.3.31"
dirs = "5.0.1" dirs = "5.0.1"
sys-locale = "0.3.0" sys-locale = "0.3.1"
chrono = "0.4.31" chrono = "0.4.38"
parking_lot = "0.12.1" parking_lot = "0.12.3"
lazy_static = "1.4.0" lazy_static = "1.5.0"
toml = "0.8.2" toml = "0.8.19"
serde = "1.0.170" serde = "1.0.210"
local-ip-address = "0.6.1" local-ip-address = "0.6.3"
url = "2.4.0" url = "2.5.2"
rand = "0.8.5" rand = "0.8.5"
serde_derive = "1.0.197" serde_derive = "1.0.210"
serde_json = "1.0.115" serde_json = "1.0.128"
tokio = { version = "1.37.0", features = ["full"] } tokio = { version = "1.40.0", features = ["full"] }
image = "0.25.1" image = "0.25.2"
rqrr = "0.7.1" rqrr = "0.8.0"
qrcodegen = "1.8.0" qrcodegen = "1.8.0"
qrcode = "0.14.0" qrcode = "0.14.1"
ur = "0.4.1" ur = "0.4.1"
gif = "0.13.1" gif = "0.13.1"
rkv = { version = "0.19.0", features = ["lmdb"] } rkv = { version = "0.19.0", features = ["lmdb"] }
## tor ## tor
arti-client = { version = "0.19.0", features = ["pt-client", "static", "onion-service-service", "onion-service-client"] } arti-client = { version = "0.23.0", features = ["pt-client", "static", "onion-service-service", "onion-service-client"] }
tor-rtcompat = { version = "0.19.0", features = ["static"] } tor-rtcompat = { version = "0.23.0", features = ["static"] }
tor-config = "0.19.0" tor-config = "0.23.0"
fs-mistrust = "0.7.9" fs-mistrust = "0.8.0"
tor-hsservice = "0.19.0" tor-hsservice = "0.23.0"
tor-hsrproxy = "0.19.0" tor-hsrproxy = "0.23.0"
tor-keymgr = "0.19.0" tor-keymgr = "0.23.0"
tor-llcrypto = "0.19.0" tor-llcrypto = "0.23.0"
tor-hscrypto = "0.19.0" tor-hscrypto = "0.23.0"
arti-hyper = "0.19.0" tor-error = "0.23.0"
sha2 = "0.10.0" sha2 = "0.10.8"
ed25519-dalek = "2.1.1" ed25519-dalek = "2.1.1"
curve25519-dalek = "4.1.2" curve25519-dalek = "4.1.3"
hyper = { version = "0.14.28", features = ["full"] } hyper = { version = "0.14.29", features = ["full"] }
hyper-tls = "0.5.0" hyper-tls = "0.5.0"
tls-api = "0.9.0" tls-api = "0.9.0"
tls-api-native-tls = "0.9.0" tls-api-native-tls = "0.9.0"
@ -113,18 +115,18 @@ env_logger = "0.11.3"
winit = { version = "0.29.15" } winit = { version = "0.29.15" }
eframe = { version = "0.28.1", features = ["wgpu", "glow"] } eframe = { version = "0.28.1", features = ["wgpu", "glow"] }
arboard = "3.2.0" arboard = "3.2.0"
rfd = "0.14.1" rfd = "0.15.0"
dark-light = "1.1.1" dark-light = "1.1.1"
interprocess = { version = "2.2.1", features = ["tokio"] } interprocess = { version = "2.2.1", features = ["tokio"] }
[target.'cfg(target_os = "android")'.dependencies] [target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.13.1" android_logger = "0.14.1"
jni = "0.21.1" jni = "0.21.1"
android-activity = { version = "0.6.0", features = ["game-activity"] } android-activity = { version = "0.6.0", features = ["game-activity"] }
wgpu = "0.20.1" wgpu = "0.20.1"
winit = { version = "0.29.15", features = ["android-game-activity"] } winit = { version = "0.29.15", features = ["android-game-activity"] }
eframe = { version = "0.28.1", features = ["wgpu", "android-game-activity"] } eframe = { version = "0.28.1", features = ["wgpu", "android-game-activity"] }
[patch.crates-io] #[patch.crates-io]
### patch grin store ### patch grin store
#grin_store = { path = "../grin-store" } #grin_store = { path = "../grin-store" }

244
src/tor/http.rs Normal file
View file

@ -0,0 +1,244 @@
use std::future::Future;
use std::io::Error;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
use arti_client::{DataStream, IntoTorAddr, TorClient};
use hyper::client::connect::{Connected, Connection};
use hyper::http::uri::Scheme;
use hyper::http::Uri;
use hyper::service::Service;
use pin_project::pin_project;
use thiserror::Error;
use tls_api::TlsConnector as TlsConn; // This is different from tor_rtcompat::TlsConnector
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tor_config::deps::educe::Educe;
use tor_rtcompat::Runtime;
/// Error making or using http connection
///
/// This error ends up being passed to hyper and bundled up into a [`hyper::Error`]
#[derive(Error, Clone, Debug)]
#[non_exhaustive]
pub enum ConnectionError {
/// Unsupported URI scheme
#[error("unsupported URI scheme in {uri:?}")]
UnsupportedUriScheme {
/// URI
uri: Uri,
},
/// Missing hostname
#[error("Missing hostname in {uri:?}")]
MissingHostname {
/// URI
uri: Uri,
},
/// Tor connection failed
#[error("Tor connection failed")]
Arti(#[from] arti_client::Error),
/// TLS connection failed
#[error("TLS connection failed")]
TLS(#[source] Arc<anyhow::Error>),
}
/// We implement this for form's sake
impl tor_error::HasKind for ConnectionError {
#[rustfmt::skip]
fn kind(&self) -> tor_error::ErrorKind {
use ConnectionError as CE;
use tor_error::ErrorKind as EK;
match self {
CE::UnsupportedUriScheme{..} => EK::NotImplemented,
CE::MissingHostname{..} => EK::BadApiUsage,
CE::Arti(e) => e.kind(),
CE::TLS(_) => EK::RemoteProtocolViolation,
}
}
}
/// **Main entrypoint**: `hyper` connector to make HTTP\[S] connections via Tor, using Arti.
///
/// An `ArtiHttpConnector` combines an Arti Tor client, and a TLS implementation,
/// in a form that can be provided to hyper
/// (e.g. to [`hyper::client::Builder`]'s `build` method)
/// so that hyper can speak HTTP and HTTPS to origin servers via Tor.
///
/// TC is the TLS to used *across* Tor to connect to the origin server.
/// For example, it could be a [`tls_api_native_tls::TlsConnector`].
/// This is a different Rust type to the TLS used *by* Tor to connect to relays etc.
/// It might even be a different underlying TLS implementation
/// (although that is usually not a particularly good idea).
#[derive(Educe)]
#[educe(Clone)] // #[derive(Debug)] infers an unwanted bound TC: Clone
pub struct ArtiHttpConnector<R: Runtime, TC: TlsConn> {
/// The client
client: TorClient<R>,
/// TLS for using across Tor.
tls_conn: Arc<TC>,
}
// #[derive(Clone)] infers a TC: Clone bound
impl<R: Runtime, TC: TlsConn> ArtiHttpConnector<R, TC> {
/// Make a new `ArtiHttpConnector` using an Arti `TorClient` object.
pub fn new(client: TorClient<R>, tls_conn: TC) -> Self {
let tls_conn = tls_conn.into();
Self { client, tls_conn }
}
}
/// Wrapper type that makes an Arti `DataStream` implement necessary traits to be used as
/// a `hyper` connection object (mainly `Connection`).
///
/// This might represent a bare HTTP connection across Tor,
/// or it might represent an HTTPS connection through Tor to an origin server,
/// `TC::TlsStream` as the TLS layer.
///
/// An `ArtiHttpConnection` is constructed by hyper's use of the [`ArtiHttpConnector`]
/// implementation of [`hyper::service::Service`],
/// and then used by hyper as the transport for hyper's HTTP implementation.
#[pin_project]
pub struct ArtiHttpConnection<TC: TlsConn> {
/// The stream
#[pin]
inner: MaybeHttpsStream<TC>,
}
/// The actual stream; might be TLS, might not
#[pin_project(project = MaybeHttpsStreamProj)]
enum MaybeHttpsStream<TC: TlsConn> {
/// http
Http(Pin<Box<DataStream>>), // Tc:TlsStream is generally boxed; box this one too
/// https
Https(#[pin] TC::TlsStream),
}
impl<TC: TlsConn> Connection for ArtiHttpConnection<TC> {
fn connected(&self) -> Connected {
Connected::new()
}
}
// These trait implementations just defer to the inner `DataStream`; the wrapper type is just
// there to implement the `Connection` trait.
impl<TC: TlsConn> AsyncRead for ArtiHttpConnection<TC> {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<Result<(), std::io::Error>> {
match self.project().inner.project() {
MaybeHttpsStreamProj::Http(ds) => ds.as_mut().poll_read(cx, buf),
MaybeHttpsStreamProj::Https(t) => t.poll_read(cx, buf),
}
}
}
impl<TC: TlsConn> AsyncWrite for ArtiHttpConnection<TC> {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize, Error>> {
match self.project().inner.project() {
MaybeHttpsStreamProj::Http(ds) => ds.as_mut().poll_write(cx, buf),
MaybeHttpsStreamProj::Https(t) => t.poll_write(cx, buf),
}
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
match self.project().inner.project() {
MaybeHttpsStreamProj::Http(ds) => ds.as_mut().poll_flush(cx),
MaybeHttpsStreamProj::Https(t) => t.poll_flush(cx),
}
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
match self.project().inner.project() {
MaybeHttpsStreamProj::Http(ds) => ds.as_mut().poll_shutdown(cx),
MaybeHttpsStreamProj::Https(t) => t.poll_shutdown(cx),
}
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
/// Are we doing TLS?
enum UseTls {
/// No
Bare,
/// Yes
Tls,
}
/// Convert uri to http\[s\] host and port, and whether to do tls
fn uri_to_host_port_tls(uri: Uri) -> Result<(String, u16, UseTls), ConnectionError> {
let use_tls = {
// Scheme doesn't derive PartialEq so can't be matched on
let scheme = uri.scheme();
if scheme == Some(&Scheme::HTTP) {
UseTls::Bare
} else if scheme == Some(&Scheme::HTTPS) {
UseTls::Tls
} else {
return Err(ConnectionError::UnsupportedUriScheme { uri });
}
};
let host = match uri.host() {
Some(h) => h,
_ => return Err(ConnectionError::MissingHostname { uri }),
};
let port = uri.port().map(|x| x.as_u16()).unwrap_or(match use_tls {
UseTls::Tls => 443,
UseTls::Bare => 80,
});
Ok((host.to_owned(), port, use_tls))
}
impl<R: Runtime, TC: TlsConn> Service<Uri> for ArtiHttpConnector<R, TC> {
type Response = ArtiHttpConnection<TC>;
type Error = ConnectionError;
#[allow(clippy::type_complexity)]
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: Uri) -> Self::Future {
// `TorClient` objects can be cloned cheaply (the cloned objects refer to the same
// underlying handles required to make Tor connections internally).
// We use this to avoid the returned future having to borrow `self`.
let client = self.client.clone();
let tls_conn = self.tls_conn.clone();
Box::pin(async move {
// Extract the host and port to connect to from the URI.
let (host, port, use_tls) = uri_to_host_port_tls(req)?;
// Initiate a new Tor connection, producing a `DataStream` if successful.
let addr = (&host as &str, port)
.into_tor_addr()
.map_err(arti_client::Error::from)?;
let ds = client.connect(addr).await?;
let inner = match use_tls {
UseTls::Tls => {
let conn = tls_conn
.connect_impl_tls_stream(&host, ds)
.await
.map_err(|e| ConnectionError::TLS(e.into()))?;
MaybeHttpsStream::Https(conn)
}
UseTls::Bare => MaybeHttpsStream::Http(Box::new(ds).into()),
};
Ok(ArtiHttpConnection { inner })
})
}
}

View file

@ -19,4 +19,6 @@ mod tor;
pub use tor::Tor; pub use tor::Tor;
mod types; mod types;
pub use types::*; pub use types::*;
mod http;

View file

@ -24,7 +24,6 @@ use std::time::Duration;
use arti_client::config::{CfgPath, TorClientConfigBuilder}; use arti_client::config::{CfgPath, TorClientConfigBuilder};
use arti_client::{TorClient, TorClientConfig}; use arti_client::{TorClient, TorClientConfig};
use arti_hyper::ArtiHttpConnector;
use curve25519_dalek::digest::Digest; use curve25519_dalek::digest::Digest;
use ed25519_dalek::hazmat::ExpandedSecretKey; use ed25519_dalek::hazmat::ExpandedSecretKey;
use fs_mistrust::Mistrust; use fs_mistrust::Mistrust;
@ -56,7 +55,7 @@ use tor_rtcompat::Runtime;
use tls_api_native_tls::TlsConnector; use tls_api_native_tls::TlsConnector;
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))] #[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
use tls_api_openssl::TlsConnector; use tls_api_openssl::TlsConnector;
use crate::tor::http::ArtiHttpConnector;
use crate::tor::TorConfig; use crate::tor::TorConfig;
lazy_static! { lazy_static! {
@ -314,8 +313,8 @@ impl Tor {
let mut w_services = let mut w_services =
TOR_SERVER_STATE.starting_services.write(); TOR_SERVER_STATE.starting_services.write();
w_services.remove(&service_id); w_services.remove(&service_id);
// Check again after 15 seconds. // Check again after 50 seconds.
Duration::from_millis(15000) Duration::from_millis(50000)
} }
Err(_) => { Err(_) => {
// Restart service on 3rd error. // Restart service on 3rd error.
@ -409,10 +408,10 @@ impl Tor {
hs_nickname: &HsNickname, hs_nickname: &HsNickname,
) -> tor_keymgr::Result<()> { ) -> tor_keymgr::Result<()> {
let arti_store = let arti_store =
ArtiNativeKeystore::from_path_and_mistrust(TorConfig::keystore_path(), &mistrust)?; ArtiNativeKeystore::from_path_and_mistrust(TorConfig::keystore_path(), mistrust)?;
let key_manager = KeyMgrBuilder::default() let key_manager = KeyMgrBuilder::default()
.default_store(Box::new(arti_store)) .primary_store(Box::new(arti_store))
.build() .build()
.unwrap(); .unwrap();
@ -427,13 +426,15 @@ impl Tor {
key_manager.insert( key_manager.insert(
HsIdKey::from(expanded_kp.public().clone()), HsIdKey::from(expanded_kp.public().clone()),
&HsIdPublicKeySpecifier::new(hs_nickname.clone()), &HsIdPublicKeySpecifier::new(hs_nickname.clone()),
KeystoreSelector::Default, KeystoreSelector::Primary,
true
)?; )?;
key_manager.insert( key_manager.insert(
HsIdKeypair::from(expanded_kp), HsIdKeypair::from(expanded_kp),
&HsIdKeypairSpecifier::new(hs_nickname.clone()), &HsIdKeypairSpecifier::new(hs_nickname.clone()),
KeystoreSelector::Default, KeystoreSelector::Primary,
true
)?; )?;
Ok(()) Ok(())
} }
@ -444,7 +445,7 @@ impl Tor {
builder.bridges().bridges().push(bridge); builder.bridges().bridges().push(bridge);
} }
// Now configure an snowflake transport. (Requires the "pt-client" feature) // Now configure a snowflake transport. (Requires the "pt-client" feature)
let mut transport = TransportConfigBuilder::default(); let mut transport = TransportConfigBuilder::default();
transport transport
.protocols(vec!["snowflake".parse().unwrap()]) .protocols(vec!["snowflake".parse().unwrap()])