11use std:: sync:: { Arc , Mutex } ;
22
3- #[ cfg( feature = "_danger-local-https" ) ]
4- use anyhow:: Result ;
5- #[ cfg( not( feature = "_danger-local-https" ) ) ]
63use anyhow:: { anyhow, Result } ;
74
85use super :: Config ;
96
107#[ derive( Debug , Clone ) ]
118pub struct RelayManager {
129 selected_relay : Option < payjoin:: Url > ,
13- #[ cfg( not( feature = "_danger-local-https" ) ) ]
1410 failed_relays : Vec < payjoin:: Url > ,
1511}
1612
1713impl RelayManager {
18- #[ cfg( feature = "_danger-local-https" ) ]
19- pub fn new ( ) -> Self { RelayManager { selected_relay : None } }
20- #[ cfg( not( feature = "_danger-local-https" ) ) ]
2114 pub fn new ( ) -> Self { RelayManager { selected_relay : None , failed_relays : Vec :: new ( ) } }
2215
23- #[ cfg( not( feature = "_danger-local-https" ) ) ]
2416 pub fn set_selected_relay ( & mut self , relay : payjoin:: Url ) { self . selected_relay = Some ( relay) ; }
2517
2618 pub fn get_selected_relay ( & self ) -> Option < payjoin:: Url > { self . selected_relay . clone ( ) }
2719
28- #[ cfg( not( feature = "_danger-local-https" ) ) ]
2920 pub fn add_failed_relay ( & mut self , relay : payjoin:: Url ) { self . failed_relays . push ( relay) ; }
3021
31- #[ cfg( not( feature = "_danger-local-https" ) ) ]
3222 pub fn get_failed_relays ( & self ) -> Vec < payjoin:: Url > { self . failed_relays . clone ( ) }
3323}
3424
25+ pub ( crate ) struct ValidatedOhttpKeys {
26+ pub ( crate ) ohttp_keys : payjoin:: OhttpKeys ,
27+ pub ( crate ) relay_url : payjoin:: Url ,
28+ }
29+
3530pub ( crate ) async fn unwrap_ohttp_keys_or_else_fetch (
3631 config : & Config ,
32+ directory : Option < payjoin:: Url > ,
3733 relay_manager : Arc < Mutex < RelayManager > > ,
38- ) -> Result < payjoin :: OhttpKeys > {
39- if let Some ( keys ) = config. v2 ( ) ?. ohttp_keys . clone ( ) {
34+ ) -> Result < ValidatedOhttpKeys > {
35+ if let Some ( ohttp_keys ) = config. v2 ( ) ?. ohttp_keys . clone ( ) {
4036 println ! ( "Using OHTTP Keys from config" ) ;
41- Ok ( keys)
37+ return Ok ( ValidatedOhttpKeys {
38+ ohttp_keys,
39+ relay_url : config. v2 ( ) ?. ohttp_relays [ 0 ] . clone ( ) ,
40+ } ) ;
4241 } else {
4342 println ! ( "Bootstrapping private network transport over Oblivious HTTP" ) ;
43+ let fetched_keys = fetch_ohttp_keys ( config, directory, relay_manager) . await ?;
4444
45- fetch_keys ( config, relay_manager. clone ( ) )
46- . await
47- . and_then ( |keys| keys. ok_or_else ( || anyhow:: anyhow!( "No OHTTP keys found" ) ) )
45+ Ok ( fetched_keys)
4846 }
4947}
5048
51- #[ cfg( not( feature = "_danger-local-https" ) ) ]
52- async fn fetch_keys (
49+ async fn fetch_ohttp_keys (
5350 config : & Config ,
51+ directory : Option < payjoin:: Url > ,
5452 relay_manager : Arc < Mutex < RelayManager > > ,
55- ) -> Result < Option < payjoin :: OhttpKeys > > {
53+ ) -> Result < ValidatedOhttpKeys > {
5654 use payjoin:: bitcoin:: secp256k1:: rand:: prelude:: SliceRandom ;
57- let payjoin_directory = config. v2 ( ) ?. pj_directory . clone ( ) ;
55+ let payjoin_directory = directory . unwrap_or ( config. v2 ( ) ?. pj_directory . clone ( ) ) ;
5856 let relays = config. v2 ( ) ?. ohttp_relays . clone ( ) ;
5957
6058 loop {
@@ -80,72 +78,25 @@ async fn fetch_keys(
8078 . set_selected_relay ( selected_relay. clone ( ) ) ;
8179
8280 let ohttp_keys = {
83- payjoin:: io:: fetch_ohttp_keys ( selected_relay. clone ( ) , payjoin_directory. clone ( ) ) . await
84- } ;
85-
86- match ohttp_keys {
87- Ok ( keys) => return Ok ( Some ( keys) ) ,
88- Err ( payjoin:: io:: Error :: UnexpectedStatusCode ( e) ) => {
89- return Err ( payjoin:: io:: Error :: UnexpectedStatusCode ( e) . into ( ) ) ;
81+ #[ cfg( feature = "_danger-local-https" ) ]
82+ {
83+ let cert_der = crate :: app:: read_local_cert ( ) ?;
84+ payjoin:: io:: fetch_ohttp_keys_with_cert (
85+ & selected_relay,
86+ & payjoin_directory,
87+ cert_der,
88+ )
89+ . await
9090 }
91- Err ( e) => {
92- log:: debug!( "Failed to connect to relay: {selected_relay}, {e:?}" ) ;
93- relay_manager
94- . lock ( )
95- . expect ( "Lock should not be poisoned" )
96- . add_failed_relay ( selected_relay) ;
91+ #[ cfg( not( feature = "_danger-local-https" ) ) ]
92+ {
93+ payjoin:: io:: fetch_ohttp_keys ( & selected_relay, & payjoin_directory) . await
9794 }
98- }
99- }
100- }
101-
102- ///Local relays are incapable of acting as proxies so we must opportunistically fetch keys from the config
103- #[ cfg( feature = "_danger-local-https" ) ]
104- async fn fetch_keys (
105- config : & Config ,
106- _relay_manager : Arc < Mutex < RelayManager > > ,
107- ) -> Result < Option < payjoin:: OhttpKeys > > {
108- let keys = config. v2 ( ) ?. ohttp_keys . clone ( ) . expect ( "No OHTTP keys set" ) ;
109-
110- Ok ( Some ( keys) )
111- }
112-
113- #[ cfg( not( feature = "_danger-local-https" ) ) ]
114- pub ( crate ) async fn validate_relay (
115- config : & Config ,
116- relay_manager : Arc < Mutex < RelayManager > > ,
117- ) -> Result < payjoin:: Url > {
118- use payjoin:: bitcoin:: secp256k1:: rand:: prelude:: SliceRandom ;
119- let payjoin_directory = config. v2 ( ) ?. pj_directory . clone ( ) ;
120- let relays = config. v2 ( ) ?. ohttp_relays . clone ( ) ;
121-
122- loop {
123- let failed_relays =
124- relay_manager. lock ( ) . expect ( "Lock should not be poisoned" ) . get_failed_relays ( ) ;
125-
126- let remaining_relays: Vec < _ > =
127- relays. iter ( ) . filter ( |r| !failed_relays. contains ( r) ) . cloned ( ) . collect ( ) ;
128-
129- if remaining_relays. is_empty ( ) {
130- return Err ( anyhow ! ( "No valid relays available" ) ) ;
131- }
132-
133- let selected_relay =
134- match remaining_relays. choose ( & mut payjoin:: bitcoin:: key:: rand:: thread_rng ( ) ) {
135- Some ( relay) => relay. clone ( ) ,
136- None => return Err ( anyhow ! ( "Failed to select from remaining relays" ) ) ,
137- } ;
138-
139- relay_manager
140- . lock ( )
141- . expect ( "Lock should not be poisoned" )
142- . set_selected_relay ( selected_relay. clone ( ) ) ;
143-
144- let ohttp_keys =
145- payjoin:: io:: fetch_ohttp_keys ( selected_relay. clone ( ) , payjoin_directory. clone ( ) ) . await ;
95+ } ;
14696
14797 match ohttp_keys {
148- Ok ( _) => return Ok ( selected_relay) ,
98+ Ok ( keys) =>
99+ return Ok ( ValidatedOhttpKeys { ohttp_keys : keys, relay_url : selected_relay } ) ,
149100 Err ( payjoin:: io:: Error :: UnexpectedStatusCode ( e) ) => {
150101 return Err ( payjoin:: io:: Error :: UnexpectedStatusCode ( e) . into ( ) ) ;
151102 }
@@ -159,13 +110,3 @@ pub(crate) async fn validate_relay(
159110 }
160111 }
161112}
162-
163- #[ cfg( feature = "_danger-local-https" ) ]
164- pub ( crate ) async fn validate_relay (
165- config : & Config ,
166- _relay_manager : Arc < Mutex < RelayManager > > ,
167- ) -> Result < payjoin:: Url > {
168- let relay = config. v2 ( ) ?. ohttp_relays . first ( ) . expect ( "no OHTTP relay set" ) . clone ( ) ;
169-
170- Ok ( relay)
171- }
0 commit comments