@@ -2,19 +2,17 @@ use bdk_kyoto::bip157::lookup_host;
22use bdk_kyoto:: bip157:: tokio;
33use bdk_kyoto:: bip157:: AddrV2 ;
44use bdk_kyoto:: bip157:: Network ;
5- use bdk_kyoto:: bip157:: Node ;
65use bdk_kyoto:: bip157:: ServiceFlags ;
76use bdk_kyoto:: builder:: Builder as BDKCbfBuilder ;
87use bdk_kyoto:: builder:: BuilderExt ;
9- use bdk_kyoto:: HeaderCheckpoint ;
10- use bdk_kyoto:: LightClient as BDKLightClient ;
118use bdk_kyoto:: Receiver ;
129use bdk_kyoto:: RejectReason ;
1310use bdk_kyoto:: Requester ;
1411use bdk_kyoto:: TrustedPeer ;
1512use bdk_kyoto:: UnboundedReceiver ;
1613use bdk_kyoto:: UpdateSubscriber ;
1714use bdk_kyoto:: Warning as Warn ;
15+ use bdk_kyoto:: { HeaderCheckpoint , Idle , LightClient } ;
1816
1917use std:: net:: { IpAddr , Ipv4Addr , Ipv6Addr } ;
2018use std:: path:: PathBuf ;
@@ -37,51 +35,37 @@ const CWD_PATH: &str = ".";
3735const TCP_HANDSHAKE_TIMEOUT : Duration = Duration :: from_secs ( 2 ) ;
3836const MESSAGE_RESPONSE_TIMEOUT : Duration = Duration :: from_secs ( 5 ) ;
3937
40- /// Receive a [`CbfClient`] and [`CbfNode`].
41- #[ derive( Debug , uniffi:: Record ) ]
42- pub struct CbfComponents {
43- /// Publish events to the node, like broadcasting transactions or adding scripts.
44- pub client : Arc < CbfClient > ,
45- /// The node to run and fetch transactions for a [`Wallet`].
46- pub node : Arc < CbfNode > ,
38+ /// A compact block filters node that has been configured but not yet started.
39+ ///
40+ /// Built via [`CbfBuilder`]. Call [`CbfNode::start`] to prepare and spawn the node, receiving a
41+ /// [`CbfClient`] to interact with the running node.
42+ ///
43+ /// `CbfNode::start` may only be called once. Calling it a second time returns
44+ /// [`CbfError::AlreadyStarted`].
45+ #[ derive( uniffi:: Object ) ]
46+ pub struct CbfNode {
47+ client : std:: sync:: Mutex < Option < LightClient < Idle > > > ,
4748}
4849
49- /// A [`CbfClient`] handles wallet updates from a [`CbfNode`].
50- #[ derive( Debug , uniffi:: Object ) ]
50+ /// Interact with a running compact block filters node.
51+ ///
52+ /// Obtained by calling [`CbfNode::start`]. Provides access to three independent
53+ /// channels — each message is consumed by exactly one caller, so dedicate a single
54+ /// task or thread to draining each channel:
55+ ///
56+ /// * [`CbfClient::next_info`] — progress and connection events.
57+ /// * [`CbfClient::next_warning`] — non-fatal issues the node encountered.
58+ /// * [`CbfClient::update`] — wallet updates ready to be applied to a [`Wallet`].
59+ ///
60+ /// Transactions can be broadcast and peers added at any time via the remaining methods.
61+ #[ derive( uniffi:: Object ) ]
5162pub struct CbfClient {
52- sender : Arc < Requester > ,
63+ sender : Requester ,
5364 info_rx : Mutex < Receiver < bdk_kyoto:: Info > > ,
5465 warning_rx : Mutex < UnboundedReceiver < bdk_kyoto:: Warning > > ,
5566 update_rx : Mutex < UpdateSubscriber > ,
5667}
5768
58- /// A [`CbfNode`] gathers transactions for a [`Wallet`].
59- /// To receive [`Update`] for [`Wallet`], refer to the
60- /// [`CbfClient`]. The [`CbfNode`] will run until instructed
61- /// to stop.
62- #[ derive( Debug , uniffi:: Object ) ]
63- pub struct CbfNode {
64- node : std:: sync:: Mutex < Option < Node > > ,
65- }
66-
67- #[ uniffi:: export]
68- impl CbfNode {
69- /// Start the node on a detached OS thread and immediately return.
70- pub fn run ( self : Arc < Self > ) {
71- let mut lock = self . node . lock ( ) . unwrap ( ) ;
72- let node = lock. take ( ) . expect ( "cannot call run more than once" ) ;
73- std:: thread:: spawn ( || {
74- tokio:: runtime:: Builder :: new_multi_thread ( )
75- . enable_all ( )
76- . build ( )
77- . unwrap ( )
78- . block_on ( async move {
79- let _ = node. run ( ) . await ;
80- } )
81- } ) ;
82- }
83- }
84-
8569/// Build a BIP 157/158 light client to fetch transactions for a `Wallet`.
8670///
8771/// Options:
@@ -178,7 +162,7 @@ impl CbfBuilder {
178162 }
179163
180164 /// Construct a [`CbfComponents`] for a [`Wallet`].
181- pub fn build ( & self , wallet : & Wallet ) -> CbfComponents {
165+ pub fn build ( & self , wallet : & Wallet ) -> CbfNode {
182166 let wallet = wallet. get_wallet ( ) ;
183167
184168 let mut trusted_peers = Vec :: new ( ) ;
@@ -241,31 +225,51 @@ impl CbfBuilder {
241225 builder = builder. socks5_proxy ( ( addr, port) ) ;
242226 }
243227
244- let BDKLightClient {
245- requester,
246- info_subscriber,
247- warning_subscriber,
248- update_subscriber,
249- node,
250- } = builder
228+ let light_client_idle = builder
251229 . build_with_wallet ( & wallet, scan_type)
252230 . expect ( "networks match by definition" ) ;
253231
254- let node = CbfNode {
255- node : std:: sync:: Mutex :: new ( Some ( node) ) ,
256- } ;
232+ CbfNode {
233+ client : std:: sync:: Mutex :: new ( Some ( light_client_idle) ) ,
234+ }
235+ }
236+ }
257237
258- let client = CbfClient {
259- sender : Arc :: new ( requester) ,
260- info_rx : Mutex :: new ( info_subscriber) ,
261- warning_rx : Mutex :: new ( warning_subscriber) ,
262- update_rx : Mutex :: new ( update_subscriber) ,
263- } ;
238+ #[ uniffi:: export]
239+ impl CbfNode {
240+ /// Subscribe to log and update channels, then spawn the node on a background thread.
241+ ///
242+ /// Returns a [`CbfClient`] that can be used to receive wallet updates, info and warning
243+ /// messages, and to broadcast transactions.
244+ ///
245+ /// This method may only be called once. A second call returns [`CbfError::AlreadyStarted`].
246+ pub fn start ( & self ) -> Result < Arc < CbfClient > , CbfError > {
247+ let light_client = self
248+ . client
249+ . lock ( )
250+ . unwrap ( )
251+ . take ( )
252+ . ok_or ( CbfError :: AlreadyStarted ) ?;
264253
265- CbfComponents {
266- client : Arc :: new ( client) ,
267- node : Arc :: new ( node) ,
268- }
254+ let ( subscribed, logging, updates) = light_client. subscribe ( ) ;
255+ let ( active, node) = subscribed. managed_start ( ) ;
256+
257+ std:: thread:: spawn ( || {
258+ tokio:: runtime:: Builder :: new_multi_thread ( )
259+ . enable_all ( )
260+ . build ( )
261+ . unwrap ( )
262+ . block_on ( async move {
263+ let _ = node. run ( ) . await ;
264+ } )
265+ } ) ;
266+
267+ Ok ( Arc :: new ( CbfClient {
268+ sender : active. requester ( ) ,
269+ info_rx : Mutex :: new ( logging. info_subscriber ) ,
270+ warning_rx : Mutex :: new ( logging. warning_subscriber ) ,
271+ update_rx : Mutex :: new ( updates) ,
272+ } ) )
269273 }
270274}
271275
@@ -340,7 +344,7 @@ impl CbfClient {
340344 /// Add another [`Peer`] to attempt a connection with.
341345 pub fn connect ( & self , peer : Peer ) -> Result < ( ) , CbfError > {
342346 self . sender
343- . add_peer ( peer)
347+ . add_peer ( TrustedPeer :: from ( peer) )
344348 . map_err ( |_| CbfError :: NodeStopped )
345349 }
346350
0 commit comments