@@ -60,6 +60,7 @@ pub struct Config {
6060 pub log_level : LevelFilter ,
6161 pub log_file_path : Option < String > ,
6262 pub pathfinding_scores_source_url : Option < String > ,
63+ pub tor_config : Option < TorConfig > ,
6364}
6465
6566#[ derive( Debug , Clone , PartialEq , Eq ) ]
@@ -83,6 +84,11 @@ pub enum ChainSource {
8384 Esplora { server_url : String } ,
8485}
8586
87+ #[ derive( Debug , PartialEq , Eq ) ]
88+ pub struct TorConfig {
89+ pub proxy_address : SocketAddress ,
90+ }
91+
8692/// A builder for `Config`.
8793#[ derive( Default ) ]
8894struct ConfigBuilder {
@@ -105,6 +111,7 @@ struct ConfigBuilder {
105111 log_level : Option < String > ,
106112 log_file_path : Option < String > ,
107113 pathfinding_scores_source_url : Option < String > ,
114+ tor_proxy_address : Option < String > ,
108115}
109116
110117impl ConfigBuilder {
@@ -164,6 +171,10 @@ impl ConfigBuilder {
164171 hosts : tls. hosts . unwrap_or_default ( ) ,
165172 } ) ;
166173 }
174+
175+ if let Some ( tor) = toml. tor {
176+ self . tor_proxy_address = Some ( tor. proxy_address )
177+ }
167178 }
168179
169180 fn merge_args ( & mut self , args : & ArgsConfig ) {
@@ -206,6 +217,10 @@ impl ConfigBuilder {
206217 if let Some ( pathfinding_scores_source_url) = & args. pathfinding_scores_source_url {
207218 self . pathfinding_scores_source_url = Some ( pathfinding_scores_source_url. clone ( ) ) ;
208219 }
220+
221+ if let Some ( tor_proxy_address) = & args. tor_proxy_address {
222+ self . tor_proxy_address = Some ( tor_proxy_address. clone ( ) ) ;
223+ }
209224 }
210225
211226 fn build ( self ) -> io:: Result < Config > {
@@ -364,6 +379,18 @@ impl ConfigBuilder {
364379
365380 let pathfinding_scores_source_url = self . pathfinding_scores_source_url ;
366381
382+ let tor_proxy_address: Option < SocketAddress > = self
383+ . tor_proxy_address
384+ . map ( |addrs| {
385+ SocketAddress :: from_str ( & addrs) . map_err ( |e| {
386+ io:: Error :: new (
387+ io:: ErrorKind :: InvalidInput ,
388+ format ! ( "Invalid proxy address configured: {}" , e) ,
389+ )
390+ } )
391+ } )
392+ . transpose ( ) ?;
393+
367394 Ok ( Config {
368395 network,
369396 listening_addrs,
@@ -381,6 +408,7 @@ impl ConfigBuilder {
381408 log_level,
382409 log_file_path : self . log_file_path ,
383410 pathfinding_scores_source_url,
411+ tor_config : tor_proxy_address. map ( |proxy_address| TorConfig { proxy_address } ) ,
384412 } )
385413 }
386414}
@@ -397,6 +425,7 @@ pub struct TomlConfig {
397425 liquidity : Option < LiquidityConfig > ,
398426 log : Option < LogConfig > ,
399427 tls : Option < TomlTlsConfig > ,
428+ tor : Option < TomlTorConfig > ,
400429}
401430
402431#[ derive( Deserialize , Serialize ) ]
@@ -456,6 +485,11 @@ struct TomlTlsConfig {
456485 hosts : Option < Vec < String > > ,
457486}
458487
488+ #[ derive( Deserialize , Serialize ) ]
489+ struct TomlTorConfig {
490+ proxy_address : String ,
491+ }
492+
459493#[ derive( Deserialize , Serialize ) ]
460494struct LiquidityConfig {
461495 lsps2_client : Option < LSPSClientTomlConfig > ,
@@ -614,6 +648,13 @@ pub struct ArgsConfig {
614648 help = "The external scores source that is merged into the local scoring system to improve routing."
615649 ) ]
616650 pathfinding_scores_source_url : Option < String > ,
651+
652+ #[ arg(
653+ long,
654+ env = "LDK_SERVER_TOR_PROXY_ADDRESS" ,
655+ help = "Tor daemon SOCKS proxy address. Only connections to OnionV3 peers will be made via this proxy; other connections (IPv4 peers, Electrum server) will not be routed over Tor."
656+ ) ]
657+ tor_proxy_address : Option < String > ,
617658}
618659
619660pub fn load_config ( args : & ArgsConfig ) -> io:: Result < Config > {
@@ -732,6 +773,9 @@ mod tests {
732773 min_payment_size_msat = 10000000 # 10,000 satoshis
733774 max_payment_size_msat = 25000000000 # 0.25 BTC
734775 client_trusts_lsp = true
776+
777+ [tor]
778+ proxy_address = "vww6ybal4bd7szmgncyruucpgfkqahzddi37ktce36gpflljhvevubid.onion:9735"
735779 "# ;
736780
737781 fn default_args_config ( ) -> ArgsConfig {
@@ -747,6 +791,7 @@ mod tests {
747791 storage_dir_path : Some ( String :: from ( "/tmp_cli" ) ) ,
748792 node_alias : Some ( String :: from ( "LDK Server CLI" ) ) ,
749793 pathfinding_scores_source_url : Some ( String :: from ( "https://example.com/" ) ) ,
794+ tor_proxy_address : None ,
750795 }
751796 }
752797
@@ -763,6 +808,7 @@ mod tests {
763808 bitcoind_rpc_password : None ,
764809 storage_dir_path : None ,
765810 pathfinding_scores_source_url : None ,
811+ tor_proxy_address : None ,
766812 }
767813 }
768814
@@ -839,6 +885,12 @@ mod tests {
839885 log_level : LevelFilter :: Trace ,
840886 log_file_path : Some ( "/var/log/ldk-server.log" . to_string ( ) ) ,
841887 pathfinding_scores_source_url : None ,
888+ tor_config : Some ( TorConfig {
889+ proxy_address : SocketAddress :: from_str (
890+ "vww6ybal4bd7szmgncyruucpgfkqahzddi37ktce36gpflljhvevubid.onion:9735" ,
891+ )
892+ . unwrap ( ) ,
893+ } ) ,
842894 } ;
843895
844896 assert_eq ! ( config. listening_addrs, expected. listening_addrs) ;
@@ -857,6 +909,7 @@ mod tests {
857909 assert_eq ! ( config. log_level, expected. log_level) ;
858910 assert_eq ! ( config. log_file_path, expected. log_file_path) ;
859911 assert_eq ! ( config. pathfinding_scores_source_url, expected. pathfinding_scores_source_url) ;
912+ assert_eq ! ( config. tor_config, expected. tor_config) ;
860913
861914 // Test case where only electrum is set
862915
@@ -1162,6 +1215,7 @@ mod tests {
11621215 log_level : LevelFilter :: Trace ,
11631216 log_file_path : Some ( "/var/log/ldk-server.log" . to_string ( ) ) ,
11641217 pathfinding_scores_source_url : Some ( "https://example.com/" . to_string ( ) ) ,
1218+ tor_config : None ,
11651219 } ;
11661220
11671221 assert_eq ! ( config. listening_addrs, expected. listening_addrs) ;
@@ -1175,6 +1229,7 @@ mod tests {
11751229 assert_eq ! ( config. rabbitmq_exchange_name, expected. rabbitmq_exchange_name) ;
11761230 assert ! ( config. lsps2_service_config. is_none( ) ) ;
11771231 assert_eq ! ( config. pathfinding_scores_source_url, expected. pathfinding_scores_source_url) ;
1232+ assert_eq ! ( config. tor_config, expected. tor_config) ;
11781233 }
11791234
11801235 #[ test]
@@ -1273,6 +1328,12 @@ mod tests {
12731328 log_level : LevelFilter :: Trace ,
12741329 log_file_path : Some ( "/var/log/ldk-server.log" . to_string ( ) ) ,
12751330 pathfinding_scores_source_url : Some ( "https://example.com/" . to_string ( ) ) ,
1331+ tor_config : Some ( TorConfig {
1332+ proxy_address : SocketAddress :: from_str (
1333+ "vww6ybal4bd7szmgncyruucpgfkqahzddi37ktce36gpflljhvevubid.onion:9735" ,
1334+ )
1335+ . unwrap ( ) ,
1336+ } ) ,
12761337 } ;
12771338
12781339 assert_eq ! ( config. listening_addrs, expected. listening_addrs) ;
@@ -1288,6 +1349,7 @@ mod tests {
12881349 #[ cfg( feature = "experimental-lsps2-support" ) ]
12891350 assert_eq ! ( config. lsps2_service_config. is_some( ) , expected. lsps2_service_config. is_some( ) ) ;
12901351 assert_eq ! ( config. pathfinding_scores_source_url, expected. pathfinding_scores_source_url) ;
1352+ assert_eq ! ( config. tor_config, expected. tor_config) ;
12911353 }
12921354
12931355 #[ test]
0 commit comments