Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,882 changes: 310 additions & 3,572 deletions Cargo.lock

Large diffs are not rendered by default.

13 changes: 0 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,10 @@ tokio = { version = "1", default-features = false, features = [

# Optional dependencies
rusqlite = { version = "0.31.0", features = ["bundled"], optional = true }
arti-client = { version = "0.21.0", features = [
"rustls",
"tokio",
"onion-service-client",
"experimental-api",
], default-features = false, optional = true }
tor-rtcompat = { version = "0.21.0", features = ["tokio"], optional = true }

[features]
default = ["database"]
database = ["rusqlite"]
tor = ["arti-client", "tor-rtcompat"]
filter-control = []

[dev-dependencies]
Expand Down Expand Up @@ -73,11 +65,6 @@ path = "example/testnet4.rs"
name = "rescan"
path = "example/rescan.rs"

[[example]]
name = "tor"
path = "example/tor.rs"
required-features = ["tor"]

[[example]]
name = "managed"
path = "example/managed.rs"
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ async fn main() {

The `kyoto` core library with default features supports an MSRV of Rust 1.63.

While connections over the Tor protocol are supported by the feature `tor`, the dependencies required cannot support the MSRV. As such, no MSRV guarantees will be made when using Tor, and the feature should be considered experimental.

## Integration Testing

The preferred workflow is by using `just`. If you do not have `just` installed, check out the [installation page](https://just.systems/man/en/chapter_4.html).
Expand Down
111 changes: 0 additions & 111 deletions example/tor.rs

This file was deleted.

18 changes: 11 additions & 7 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ use crate::db::error::SqlInitializationError;
#[cfg(feature = "database")]
use crate::db::sqlite::{headers::SqliteHeaderDb, peers::SqlitePeerDb};
use crate::network::dns::{DnsResolver, DNS_RESOLVER_PORT};
use crate::network::ConnectionType;
use crate::{
chain::checkpoints::HeaderCheckpoint,
db::traits::{HeaderStore, PeerStore},
};
use crate::{ConnectionType, FilterSyncPolicy, LogLevel, PeerStoreSizeConfig, TrustedPeer};
use crate::{FilterSyncPolicy, LogLevel, PeerStoreSizeConfig, TrustedPeer};

#[cfg(feature = "database")]
/// The default node returned from the [`NodeBuilder`](crate::core).
Expand Down Expand Up @@ -149,12 +150,6 @@ impl NodeBuilder {
self
}

/// Set the desired communication channel. Either directly over TCP or over the Tor network.
pub fn connection_type(mut self, connection_type: ConnectionType) -> Self {
self.config.connection_type = connection_type;
self
}

/// Set the time duration a peer has to respond to a message from the local node.
///
/// ## Note
Expand Down Expand Up @@ -193,6 +188,15 @@ impl NodeBuilder {
self
}

/// Route network traffic through a Tor daemon using a Socks5 proxy. Currently, proxies
/// must be reachable by IP address.
pub fn socks5_proxy(mut self, proxy: impl Into<SocketAddr>) -> Self {
let ip_addr = proxy.into();
let connection = ConnectionType::Socks5Proxy(ip_addr);
self.config.connection_type = connection;
self
}

/// Stop the node from downloading and checking compact block filters until an explicit command by the client is made.
/// This is only useful if the scripts to check for may not be known do to some expensive computation, like in a silent
/// payments context.
Expand Down
3 changes: 2 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use std::{collections::HashSet, path::PathBuf, time::Duration};
use bitcoin::ScriptBuf;

use crate::{
chain::checkpoints::HeaderCheckpoint, network::dns::DnsResolver, ConnectionType,
chain::checkpoints::HeaderCheckpoint,
network::{dns::DnsResolver, ConnectionType},
FilterSyncPolicy, LogLevel, PeerStoreSizeConfig, TrustedPeer,
};

Expand Down
45 changes: 0 additions & 45 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@
//! `database`: use the default `rusqlite` database implementations. Default and recommend feature.
//!
//! `filter-control`: check filters and request blocks directly. Recommended for silent payments or strict chain ordering implementations.
//!
//! `tor` *No MSRV guarantees*: connect to nodes over the Tor network.

#![warn(missing_docs)]
pub mod chain;
Expand Down Expand Up @@ -116,11 +114,6 @@ use std::collections::HashSet;

use std::net::{IpAddr, SocketAddr};

#[cfg(feature = "tor")]
pub use arti_client::{TorClient, TorClientConfig};
#[cfg(feature = "tor")]
use tor_rtcompat::PreferredRuntime;

// Re-exports
#[doc(inline)]
pub use chain::checkpoints::{
Expand Down Expand Up @@ -320,21 +313,6 @@ impl TrustedPeer {
}
}

/// Create a new peer from a TorV3 service and port.
#[cfg(feature = "tor")]
pub fn new_from_tor_v3(
public_key: [u8; 32],
port: Option<u16>,
services: ServiceFlags,
) -> Self {
let address = AddrV2::TorV3(public_key);
Self {
address,
port,
known_services: services,
}
}

/// Create a new trusted peer using the default port for the network.
pub fn from_ip(ip_addr: impl Into<IpAddr>) -> Self {
let address = match ip_addr.into() {
Expand Down Expand Up @@ -362,17 +340,6 @@ impl TrustedPeer {
}
}

/// Create a new peer from a TorV3 service.
#[cfg(feature = "tor")]
pub fn from_tor_v3(public_key: [u8; 32]) -> Self {
let address = AddrV2::TorV3(public_key);
Self {
address,
port: None,
known_services: ServiceFlags::NONE,
}
}

/// The IP address of the trusted peer.
pub fn address(&self) -> AddrV2 {
self.address.clone()
Expand Down Expand Up @@ -422,18 +389,6 @@ impl From<SocketAddr> for TrustedPeer {
}
}

/// How to connect to peers on the peer-to-peer network
#[derive(Default, Clone)]
#[non_exhaustive]
pub enum ConnectionType {
/// Version one peer-to-peer connections
#[default]
ClearNet,
/// Connect to peers over Tor
#[cfg(feature = "tor")]
Tor(TorClient<PreferredRuntime>),
}

/// Configure how many peers will be stored.
#[derive(Debug, Default, Clone)]
pub enum PeerStoreSizeConfig {
Expand Down
41 changes: 40 additions & 1 deletion src/network/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl_sourceless_error!(PeerReadError);

// TODO: (@leonardo) Should the error variants wrap inner errors for richer information ?
#[derive(Debug)]
pub enum PeerError {
pub(crate) enum PeerError {
ConnectionFailed,
MessageEncryption,
MessageSerialization,
Expand All @@ -39,6 +39,7 @@ pub enum PeerError {
DisconnectCommand,
Reader,
UnreachableSocketAddr,
Socks5(Socks5Error),
}

impl core::fmt::Display for PeerError {
Expand Down Expand Up @@ -68,12 +69,50 @@ impl core::fmt::Display for PeerError {
PeerError::MessageEncryption => {
write!(f, "encrypting a serialized message failed.")
}
PeerError::Socks5(err) => {
write!(f, "could not connect via Socks5 proxy: {err}")
}
}
}
}

impl_sourceless_error!(PeerError);

#[derive(Debug, Clone)]
pub(crate) enum Socks5Error {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More org bike shedding, but I find it strange to have the Socks5Error type defined outside of the socks module.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, another all-or-nothing change though since I have the DNS errors here as well. I typically prefer anything that is an error just be thrown into the error module. I would consider it mostly a stylistic choice so I don't think I'll touch it for now

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I don't think it is mentioned explicitly in the official style guide. Just reminds me of OG java when we would put things in models and what not.

WrongVersion,
AuthRequired,
ConnectionTimeout,
ConnectionFailed,
IO,
}

impl core::fmt::Display for Socks5Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Socks5Error::WrongVersion => write!(f, "server responded with an unsupported version."),
Socks5Error::AuthRequired => write!(f, "server requires authentication."),
Socks5Error::ConnectionTimeout => write!(f, "connection to server timed out."),
Socks5Error::ConnectionFailed => write!(
f,
"the server could not connect to the requested destination."
),
Socks5Error::IO => write!(
f,
"reading or writing to the TCP stream failed unexpectedly."
),
}
}
}

impl_sourceless_error!(Socks5Error);

impl From<std::io::Error> for Socks5Error {
fn from(_value: std::io::Error) -> Self {
Socks5Error::IO
}
}

#[derive(Debug)]
pub(crate) enum DnsBootstrapError {
NotEnoughPeersError,
Expand Down
Loading