@@ -46,7 +46,7 @@ use vss_client::headers::VssHeaderProvider;
4646use crate :: chain:: ChainSource ;
4747use crate :: config:: {
4848 default_user_config, may_announce_channel, AnnounceError , AsyncPaymentsRole ,
49- BitcoindRestClientConfig , Config , ElectrumSyncConfig , EsploraSyncConfig ,
49+ BitcoindRestClientConfig , Config , ElectrumSyncConfig , EsploraSyncConfig , TorConfig ,
5050 DEFAULT_ESPLORA_SERVER_URL , DEFAULT_LOG_FILENAME , DEFAULT_LOG_LEVEL ,
5151 DEFAULT_MAX_PROBE_AMOUNT_MSAT , DEFAULT_MAX_PROBE_LOCKED_MSAT , DEFAULT_PROBING_INTERVAL_SECS ,
5252 MIN_PROBE_AMOUNT_MSAT ,
@@ -201,6 +201,8 @@ pub enum BuildError {
201201 InvalidListeningAddresses ,
202202 /// The given announcement addresses are invalid, e.g. too many were passed.
203203 InvalidAnnouncementAddresses ,
204+ /// The given tor proxy address is invalid, e.g. an onion address was passed.
205+ InvalidTorProxyAddress ,
204206 /// The provided alias is invalid.
205207 InvalidNodeAlias ,
206208 /// An attempt to setup a runtime has failed.
@@ -242,6 +244,7 @@ impl fmt::Display for BuildError {
242244 Self :: InvalidAnnouncementAddresses => {
243245 write ! ( f, "Given announcement addresses are invalid." )
244246 } ,
247+ Self :: InvalidTorProxyAddress => write ! ( f, "Given Tor proxy address is invalid." ) ,
245248 Self :: RuntimeSetupFailed => write ! ( f, "Failed to setup a runtime." ) ,
246249 Self :: ReadFailed => write ! ( f, "Failed to read from store." ) ,
247250 Self :: WriteFailed => write ! ( f, "Failed to write to store." ) ,
@@ -269,9 +272,40 @@ impl std::error::Error for BuildError {}
269272/// the getgo.
270273///
271274/// ### Defaults
272- /// - Wallet entropy is sourced from a `keys_seed` file located under [`Config::storage_dir_path`]
275+ /// - See [`Config`] for the default values of all configuration options.
273276/// - Chain data is sourced from the Esplora endpoint `https://blockstream.info/api`
274277/// - Gossip data is sourced via the peer-to-peer network
278+ /// - Logs are written to the filesystem (see [Logging] below)
279+ ///
280+ /// ### Storage
281+ ///
282+ /// Several `build` methods are available depending on the desired storage backend:
283+ /// - [`build`] uses an SQLite database (recommended default).
284+ /// - [`build_with_fs_store`] uses a filesystem-based store.
285+ /// - [`build_with_vss_store`] and variants use a [VSS] remote store (**experimental**).
286+ /// - [`build_with_store`] allows providing a custom [`KVStore`] implementation.
287+ ///
288+ /// ### Logging
289+ ///
290+ /// By default, logs are written to the filesystem via an internal file logger at
291+ /// [`DEFAULT_LOG_LEVEL`]. The log file path and level can be customized via
292+ /// [`set_filesystem_logger`].
293+ ///
294+ /// Alternatively, logs can be written to the [`log`] facade via [`set_log_facade_logger`], or to
295+ /// a custom [`LogWriter`] via [`set_custom_logger`].
296+ ///
297+ /// [`build`]: Self::build
298+ /// [`build_with_fs_store`]: Self::build_with_fs_store
299+ /// [`build_with_vss_store`]: Self::build_with_vss_store
300+ /// [`build_with_store`]: Self::build_with_store
301+ /// [VSS]: https://github.com/lightningdevkit/vss-server/blob/main/README.md
302+ /// [`KVStore`]: lightning::util::persist::KVStore
303+ /// [`DEFAULT_LOG_LEVEL`]: crate::config::DEFAULT_LOG_LEVEL
304+ /// [`set_filesystem_logger`]: Self::set_filesystem_logger
305+ /// [`set_log_facade_logger`]: Self::set_log_facade_logger
306+ /// [`set_custom_logger`]: Self::set_custom_logger
307+ /// [`log`]: https://crates.io/crates/log
308+ /// [Logging]: #logging
275309#[ derive( Debug ) ]
276310pub struct NodeBuilder {
277311 config : Config ,
@@ -512,6 +546,10 @@ impl NodeBuilder {
512546 /// If set, the `max_log_level` sets the maximum log level. Otherwise, the latter defaults to
513547 /// [`DEFAULT_LOG_LEVEL`].
514548 ///
549+ /// **Note:** Log rotation and pruning are the responsibility of the user and are not handled
550+ /// internally. For example, UNIX system tooling such as `logrotate` and `cron` can be used to
551+ /// manage log file sizes and retention.
552+ ///
515553 /// [`DEFAULT_LOG_FILENAME`]: crate::config::DEFAULT_LOG_FILENAME
516554 pub fn set_filesystem_logger (
517555 & mut self , log_file_path : Option < String > , max_log_level : Option < LogLevel > ,
@@ -566,6 +604,23 @@ impl NodeBuilder {
566604 Ok ( self )
567605 }
568606
607+ /// Configures the [`Node`] instance to use a Tor SOCKS proxy for outbound connections to peers with OnionV3 addresses.
608+ /// Connections to clearnet addresses are not affected, and are not made over Tor.
609+ /// The proxy address must not itself be an onion address.
610+ ///
611+ /// **Note**: If unset, connecting to peer OnionV3 addresses will fail.
612+ pub fn set_tor_config ( & mut self , tor_config : TorConfig ) -> Result < & mut Self , BuildError > {
613+ match tor_config. proxy_address {
614+ SocketAddress :: OnionV2 { .. } | SocketAddress :: OnionV3 { .. } => {
615+ return Err ( BuildError :: InvalidTorProxyAddress ) ;
616+ } ,
617+ _ => { } ,
618+ }
619+
620+ self . config . tor_config = Some ( tor_config) ;
621+ Ok ( self )
622+ }
623+
569624 /// Sets the node alias that will be used when broadcasting announcements to the gossip
570625 /// network.
571626 ///
@@ -870,9 +925,41 @@ impl NodeBuilder {
870925/// the getgo.
871926///
872927/// ### Defaults
873- /// - Wallet entropy is sourced from a `keys_seed` file located under [`Config::storage_dir_path`]
928+ /// - See [`Config`] for the default values of all configuration options.
874929/// - Chain data is sourced from the Esplora endpoint `https://blockstream.info/api`
875930/// - Gossip data is sourced via the peer-to-peer network
931+ /// - Logs are written to the filesystem (see [Logging] below)
932+ ///
933+ /// ### Storage
934+ ///
935+ /// Several `build` methods are available depending on the desired storage backend:
936+ /// - [`build`] uses an SQLite database (recommended default).
937+ /// - [`build_with_fs_store`] uses a filesystem-based store.
938+ /// - [`build_with_vss_store`] and variants use a [VSS] remote store (**experimental**).
939+ /// - [`build_with_store`] allows providing a custom [`KVStore`] implementation.
940+ ///
941+ /// ### Logging
942+ ///
943+ /// By default, logs are written to the filesystem via an internal file logger at
944+ /// [`DEFAULT_LOG_LEVEL`]. The log file path and level can be customized via
945+ /// [`set_filesystem_logger`].
946+ ///
947+ /// Alternatively, logs can be written to the [`log`] facade via [`set_log_facade_logger`], or to
948+ /// a custom [`LogWriter`] via [`set_custom_logger`].
949+ ///
950+ /// [`build`]: Self::build
951+ /// [`build_with_fs_store`]: Self::build_with_fs_store
952+ /// [`build_with_vss_store`]: Self::build_with_vss_store
953+ /// [`build_with_store`]: Self::build_with_store
954+ /// [VSS]: https://github.com/lightningdevkit/vss-server/blob/main/README.md
955+ /// [`KVStore`]: lightning::util::persist::KVStore
956+ /// [`DEFAULT_LOG_LEVEL`]: crate::config::DEFAULT_LOG_LEVEL
957+ /// [`set_filesystem_logger`]: Self::set_filesystem_logger
958+ /// [`set_log_facade_logger`]: Self::set_log_facade_logger
959+ /// [`set_custom_logger`]: Self::set_custom_logger
960+ /// [`log`]: https://crates.io/crates/log
961+ /// [Logging]: #logging
962+ /// [Storage]: #storage
876963#[ derive( Debug ) ]
877964#[ cfg( feature = "uniffi" ) ]
878965pub struct ArcedNodeBuilder {
@@ -1043,6 +1130,10 @@ impl ArcedNodeBuilder {
10431130 /// If set, the `max_log_level` sets the maximum log level. Otherwise, the latter defaults to
10441131 /// [`DEFAULT_LOG_LEVEL`].
10451132 ///
1133+ /// **Note:** Log rotation and pruning are the responsibility of the user and are not handled
1134+ /// internally. For example, UNIX system tooling such as `logrotate` and `cron` can be used to
1135+ /// manage log file sizes and retention.
1136+ ///
10461137 /// [`DEFAULT_LOG_FILENAME`]: crate::config::DEFAULT_LOG_FILENAME
10471138 pub fn set_filesystem_logger (
10481139 & self , log_file_path : Option < String > , log_level : Option < LogLevel > ,
@@ -1083,6 +1174,15 @@ impl ArcedNodeBuilder {
10831174 self . inner . write ( ) . unwrap ( ) . set_announcement_addresses ( announcement_addresses) . map ( |_| ( ) )
10841175 }
10851176
1177+ /// Configures the [`Node`] instance to use a Tor SOCKS proxy for outbound connections to peers with OnionV3 addresses.
1178+ /// Connections to clearnet addresses are not affected, and are not made over Tor.
1179+ /// The proxy address must not itself be an onion address.
1180+ ///
1181+ /// **Note**: If unset, connecting to peer OnionV3 addresses will fail.
1182+ pub fn set_tor_config ( & self , tor_config : TorConfig ) -> Result < ( ) , BuildError > {
1183+ self . inner . write ( ) . unwrap ( ) . set_tor_config ( tor_config) . map ( |_| ( ) )
1184+ }
1185+
10861186 /// Sets the node alias that will be used when broadcasting announcements to the gossip
10871187 /// network.
10881188 ///
@@ -1278,6 +1378,15 @@ fn build_with_store_internal(
12781378 }
12791379 }
12801380
1381+ if let Some ( tor_config) = & config. tor_config {
1382+ match tor_config. proxy_address {
1383+ SocketAddress :: OnionV2 { .. } | SocketAddress :: OnionV3 { .. } => {
1384+ return Err ( BuildError :: InvalidTorProxyAddress ) ;
1385+ } ,
1386+ _ => { } ,
1387+ }
1388+ }
1389+
12811390 let tx_broadcaster = Arc :: new ( TransactionBroadcaster :: new ( Arc :: clone ( & logger) ) ) ;
12821391 let fee_estimator = Arc :: new ( OnchainFeeEstimator :: new ( ) ) ;
12831392
@@ -1822,7 +1931,6 @@ fn build_with_store_internal(
18221931 Arc :: clone ( & wallet) ,
18231932 Arc :: clone ( & channel_manager) ,
18241933 Arc :: clone ( & keys_manager) ,
1825- Arc :: clone ( & chain_source) ,
18261934 Arc :: clone ( & tx_broadcaster) ,
18271935 Arc :: clone ( & kv_store) ,
18281936 Arc :: clone ( & config) ,
@@ -1914,8 +2022,12 @@ fn build_with_store_internal(
19142022
19152023 liquidity_source. as_ref ( ) . map ( |l| l. set_peer_manager ( Arc :: downgrade ( & peer_manager) ) ) ;
19162024
1917- let connection_manager =
1918- Arc :: new ( ConnectionManager :: new ( Arc :: clone ( & peer_manager) , Arc :: clone ( & logger) ) ) ;
2025+ let connection_manager = Arc :: new ( ConnectionManager :: new (
2026+ Arc :: clone ( & peer_manager) ,
2027+ config. tor_config . clone ( ) ,
2028+ Arc :: clone ( & keys_manager) ,
2029+ Arc :: clone ( & logger) ,
2030+ ) ) ;
19192031
19202032 let output_sweeper = match sweeper_bytes_res {
19212033 Ok ( output_sweeper) => Arc :: new ( output_sweeper) ,
0 commit comments