@@ -28,6 +28,7 @@ use crate::liquidity::{
2828use crate :: logger:: { log_error, log_info, LdkLogger , LogLevel , LogWriter , Logger } ;
2929use crate :: message_handler:: NodeCustomMessageHandler ;
3030use crate :: peer_store:: PeerStore ;
31+ use crate :: runtime:: Runtime ;
3132use crate :: tx_broadcaster:: TransactionBroadcaster ;
3233use crate :: types:: {
3334 ChainMonitor , ChannelManager , DynStore , GossipSync , Graph , KeysManager , MessageRouter ,
@@ -167,6 +168,8 @@ pub enum BuildError {
167168 InvalidAnnouncementAddresses ,
168169 /// The provided alias is invalid.
169170 InvalidNodeAlias ,
171+ /// An attempt to setup a runtime has failed.
172+ RuntimeSetupFailed ,
170173 /// We failed to read data from the [`KVStore`].
171174 ///
172175 /// [`KVStore`]: lightning::util::persist::KVStore
@@ -204,6 +207,7 @@ impl fmt::Display for BuildError {
204207 Self :: InvalidAnnouncementAddresses => {
205208 write ! ( f, "Given announcement addresses are invalid." )
206209 } ,
210+ Self :: RuntimeSetupFailed => write ! ( f, "Failed to setup a runtime." ) ,
207211 Self :: ReadFailed => write ! ( f, "Failed to read from store." ) ,
208212 Self :: WriteFailed => write ! ( f, "Failed to write to store." ) ,
209213 Self :: StoragePathAccessFailed => write ! ( f, "Failed to access the given storage path." ) ,
@@ -235,6 +239,7 @@ pub struct NodeBuilder {
235239 gossip_source_config : Option < GossipSourceConfig > ,
236240 liquidity_source_config : Option < LiquiditySourceConfig > ,
237241 log_writer_config : Option < LogWriterConfig > ,
242+ runtime_handle : Option < tokio:: runtime:: Handle > ,
238243}
239244
240245impl NodeBuilder {
@@ -251,16 +256,28 @@ impl NodeBuilder {
251256 let gossip_source_config = None ;
252257 let liquidity_source_config = None ;
253258 let log_writer_config = None ;
259+ let runtime_handle = None ;
254260 Self {
255261 config,
256262 entropy_source_config,
257263 chain_data_source_config,
258264 gossip_source_config,
259265 liquidity_source_config,
260266 log_writer_config,
267+ runtime_handle,
261268 }
262269 }
263270
271+ /// Configures the [`Node`] instance to (re-)use a specific `tokio` runtime.
272+ ///
273+ /// If not provided, the node will spawn its own runtime or reuse any outer runtime context it
274+ /// can detect.
275+ #[ cfg_attr( feature = "uniffi" , allow( dead_code) ) ]
276+ pub fn set_runtime ( & mut self , runtime_handle : tokio:: runtime:: Handle ) -> & mut Self {
277+ self . runtime_handle = Some ( runtime_handle) ;
278+ self
279+ }
280+
264281 /// Configures the [`Node`] instance to source its wallet entropy from a seed file on disk.
265282 ///
266283 /// If the given file does not exist a new random seed file will be generated and
@@ -630,6 +647,15 @@ impl NodeBuilder {
630647 ) -> Result < Node , BuildError > {
631648 let logger = setup_logger ( & self . log_writer_config , & self . config ) ?;
632649
650+ let runtime = if let Some ( handle) = self . runtime_handle . as_ref ( ) {
651+ Arc :: new ( Runtime :: with_handle ( handle. clone ( ) ) )
652+ } else {
653+ Arc :: new ( Runtime :: new ( ) . map_err ( |e| {
654+ log_error ! ( logger, "Failed to setup tokio runtime: {}" , e) ;
655+ BuildError :: RuntimeSetupFailed
656+ } ) ?)
657+ } ;
658+
633659 let seed_bytes = seed_bytes_from_config (
634660 & self . config ,
635661 self . entropy_source_config . as_ref ( ) ,
@@ -658,6 +684,7 @@ impl NodeBuilder {
658684 self . gossip_source_config . as_ref ( ) ,
659685 self . liquidity_source_config . as_ref ( ) ,
660686 seed_bytes,
687+ runtime,
661688 logger,
662689 Arc :: new ( vss_store) ,
663690 )
@@ -667,6 +694,15 @@ impl NodeBuilder {
667694 pub fn build_with_store ( & self , kv_store : Arc < DynStore > ) -> Result < Node , BuildError > {
668695 let logger = setup_logger ( & self . log_writer_config , & self . config ) ?;
669696
697+ let runtime = if let Some ( handle) = self . runtime_handle . as_ref ( ) {
698+ Arc :: new ( Runtime :: with_handle ( handle. clone ( ) ) )
699+ } else {
700+ Arc :: new ( Runtime :: new ( ) . map_err ( |e| {
701+ log_error ! ( logger, "Failed to setup tokio runtime: {}" , e) ;
702+ BuildError :: RuntimeSetupFailed
703+ } ) ?)
704+ } ;
705+
670706 let seed_bytes = seed_bytes_from_config (
671707 & self . config ,
672708 self . entropy_source_config . as_ref ( ) ,
@@ -680,6 +716,7 @@ impl NodeBuilder {
680716 self . gossip_source_config . as_ref ( ) ,
681717 self . liquidity_source_config . as_ref ( ) ,
682718 seed_bytes,
719+ runtime,
683720 logger,
684721 kv_store,
685722 )
@@ -1011,7 +1048,7 @@ fn build_with_store_internal(
10111048 config : Arc < Config > , chain_data_source_config : Option < & ChainDataSourceConfig > ,
10121049 gossip_source_config : Option < & GossipSourceConfig > ,
10131050 liquidity_source_config : Option < & LiquiditySourceConfig > , seed_bytes : [ u8 ; 64 ] ,
1014- logger : Arc < Logger > , kv_store : Arc < DynStore > ,
1051+ runtime : Arc < Runtime > , logger : Arc < Logger > , kv_store : Arc < DynStore > ,
10151052) -> Result < Node , BuildError > {
10161053 if let Err ( err) = may_announce_channel ( & config) {
10171054 if config. announcement_addresses . is_some ( ) {
@@ -1199,8 +1236,6 @@ fn build_with_store_internal(
11991236 } ,
12001237 } ;
12011238
1202- let runtime = Arc :: new ( RwLock :: new ( None ) ) ;
1203-
12041239 // Initialize the ChainMonitor
12051240 let chain_monitor: Arc < ChainMonitor > = Arc :: new ( chainmonitor:: ChainMonitor :: new (
12061241 Some ( Arc :: clone ( & chain_source) ) ,
@@ -1593,6 +1628,8 @@ fn build_with_store_internal(
15931628 let ( stop_sender, _) = tokio:: sync:: watch:: channel ( ( ) ) ;
15941629 let ( event_handling_stopped_sender, _) = tokio:: sync:: watch:: channel ( ( ) ) ;
15951630
1631+ let is_running = Arc :: new ( RwLock :: new ( false ) ) ;
1632+
15961633 Ok ( Node {
15971634 runtime,
15981635 stop_sender,
@@ -1618,6 +1655,7 @@ fn build_with_store_internal(
16181655 scorer,
16191656 peer_store,
16201657 payment_store,
1658+ is_running,
16211659 is_listening,
16221660 node_metrics,
16231661 } )
0 commit comments