@@ -6,7 +6,8 @@ use bdk_bitcoind_rpc::{
66use bdk_wallet:: rusqlite:: Connection ;
77use bdk_wallet:: {
88 bitcoin:: { Block , Network } ,
9- KeychainKind , Wallet ,
9+ keyring:: KeyRing ,
10+ KeychainKind , LoadParams , Wallet ,
1011} ;
1112use clap:: { self , Parser } ;
1213use std:: {
@@ -85,125 +86,140 @@ enum Emission {
8586}
8687
8788fn main ( ) -> anyhow:: Result < ( ) > {
88- // let args = Args::parse();
89-
90- // let rpc_client = Arc::new(args.client()?);
91- // println!(
92- // "Connected to Bitcoin Core RPC at {:?}",
93- // rpc_client.get_blockchain_info().unwrap()
94- // );
95-
96- // let start_load_wallet = Instant::now();
97- // let mut db = Connection::open(args.db_path)?;
98- // let wallet_opt = Wallet::load()
99- // .descriptor(KeychainKind::External, Some(args.descriptor.clone()))
100- // .descriptor(KeychainKind::Internal, args.change_descriptor.clone())
101- // .extract_keys()
102- // .check_network(args.network)
103- // .load_wallet(&mut db)?;
104- // let mut wallet = match wallet_opt {
105- // Some(wallet) => wallet,
106- // None => match &args.change_descriptor {
107- // Some(change_desc) => Wallet::create(args.descriptor.clone(), change_desc.clone())
108- // .network(args.network)
109- // .create_wallet(&mut db)?,
110- // None => Wallet::create_single(args.descriptor.clone())
111- // .network(args.network)
112- // .create_wallet(&mut db)?,
113- // },
114- // };
115- // println!(
116- // "Loaded wallet in {}s",
117- // start_load_wallet.elapsed().as_secs_f32()
118- // );
119-
120- // let address = wallet.reveal_next_address(KeychainKind::External).address;
121- // println!("Wallet address: {address}");
122-
123- // let balance = wallet.balance();
124- // println!("Wallet balance before syncing: {}", balance.total());
125-
126- // let wallet_tip = wallet.latest_checkpoint();
127- // println!(
128- // "Wallet tip: {} at height {}",
129- // wallet_tip.hash(),
130- // wallet_tip.height()
131- // );
132-
133- // let (sender, receiver) = sync_channel::<Emission>(21);
134-
135- // let signal_sender = sender.clone();
136- // let _ = ctrlc::set_handler(move || {
137- // signal_sender
138- // .send(Emission::SigTerm)
139- // .expect("failed to send sigterm")
140- // });
141-
142- // let mut emitter = Emitter::new(
143- // rpc_client,
144- // wallet_tip,
145- // args.start_height,
146- // wallet
147- // .transactions()
148- // .filter(|tx| tx.chain_position.is_unconfirmed()),
149- // );
150- // spawn(move || -> Result<(), anyhow::Error> {
151- // while let Some(emission) = emitter.next_block()? {
152- // sender.send(Emission::Block(emission))?;
153- // }
154- // sender.send(Emission::Mempool(emitter.mempool()?))?;
155- // Ok(())
156- // });
157-
158- // let mut blocks_received = 0_usize;
159- // for emission in receiver {
160- // match emission {
161- // Emission::SigTerm => {
162- // println!("Sigterm received, exiting...");
163- // break;
164- // }
165- // Emission::Block(block_emission) => {
166- // blocks_received += 1;
167- // let height = block_emission.block_height();
168- // let hash = block_emission.block_hash();
169- // let connected_to = block_emission.connected_to();
170- // let start_apply_block = Instant::now();
171- // wallet.apply_block_connected_to(&block_emission.block, height, connected_to)?;
172- // wallet.persist(&mut db)?;
173- // let elapsed = start_apply_block.elapsed().as_secs_f32();
174- // println!("Applied block {hash} at height {height} in {elapsed}s");
175- // }
176- // Emission::Mempool(event) => {
177- // let start_apply_mempool = Instant::now();
178- // wallet.apply_evicted_txs(event.evicted);
179- // wallet.apply_unconfirmed_txs(event.update);
180- // wallet.persist(&mut db)?;
181- // println!(
182- // "Applied unconfirmed transactions in {}s",
183- // start_apply_mempool.elapsed().as_secs_f32()
184- // );
185- // break;
186- // }
187- // }
188- // }
189- // let wallet_tip_end = wallet.latest_checkpoint();
190- // let balance = wallet.balance();
191- // println!(
192- // "Synced {} blocks in {}s",
193- // blocks_received,
194- // start_load_wallet.elapsed().as_secs_f32(),
195- // );
196- // println!(
197- // "Wallet tip is '{}:{}'",
198- // wallet_tip_end.height(),
199- // wallet_tip_end.hash()
200- // );
201- // println!("Wallet balance is {}", balance.total());
202- // println!(
203- // "Wallet has {} transactions and {} utxos",
204- // wallet.transactions().count(),
205- // wallet.list_unspent().count()
206- // );
89+ let args = Args :: parse ( ) ;
90+
91+ let rpc_client = Arc :: new ( args. client ( ) ?) ;
92+ println ! (
93+ "Connected to Bitcoin Core RPC at {:?}" ,
94+ rpc_client. get_blockchain_info( ) . unwrap( )
95+ ) ;
96+
97+ let start_load_wallet = Instant :: now ( ) ;
98+ let mut db = Connection :: open ( args. db_path ) ?;
99+
100+ let mut params = LoadParams :: new ( )
101+ . check_default ( KeychainKind :: External )
102+ . check_descriptor ( KeychainKind :: External , Some ( args. descriptor . clone ( ) ) )
103+ . check_genesis_hash ( bitcoin:: constants:: genesis_block ( args. network ) . block_hash ( ) )
104+ . check_network ( args. network ) ;
105+
106+ if let Some ( desc) = & args. change_descriptor {
107+ params = params. check_descriptor ( KeychainKind :: Internal , Some ( desc. clone ( ) ) ) ;
108+ }
109+
110+ let mut wallet = match Wallet :: < KeychainKind > :: from_sqlite ( & mut db, params) . unwrap ( ) {
111+ Some ( wallet) => wallet,
112+ None => {
113+ let mut keyring: KeyRing < KeychainKind > = KeyRing :: new (
114+ args. network ,
115+ KeychainKind :: External ,
116+ args. descriptor . clone ( ) ,
117+ )
118+ . unwrap ( ) ;
119+ if let Some ( desc) = & args. change_descriptor {
120+ keyring
121+ . add_descriptor ( KeychainKind :: Internal , desc. clone ( ) , false )
122+ . unwrap ( ) ;
123+ }
124+ Wallet :: new ( keyring)
125+ }
126+ } ;
127+
128+ println ! (
129+ "Loaded wallet in {}s" ,
130+ start_load_wallet. elapsed( ) . as_secs_f32( )
131+ ) ;
132+
133+ let address = wallet
134+ . next_unused_address ( KeychainKind :: External )
135+ . unwrap ( )
136+ . address ;
137+ println ! ( "Wallet address: {address}" ) ;
138+
139+ let balance = wallet. balance ( ) ;
140+ println ! ( "Wallet balance before syncing: {}" , balance. total( ) ) ;
141+
142+ let wallet_tip = wallet. latest_checkpoint ( ) ;
143+ println ! (
144+ "Wallet tip: {} at height {}" ,
145+ wallet_tip. hash( ) ,
146+ wallet_tip. height( )
147+ ) ;
148+
149+ let ( sender, receiver) = sync_channel :: < Emission > ( 21 ) ;
150+
151+ let signal_sender = sender. clone ( ) ;
152+ let _ = ctrlc:: set_handler ( move || {
153+ signal_sender
154+ . send ( Emission :: SigTerm )
155+ . expect ( "failed to send sigterm" )
156+ } ) ;
157+
158+ let mut emitter = Emitter :: new (
159+ rpc_client,
160+ wallet_tip,
161+ args. start_height ,
162+ wallet
163+ . transactions ( )
164+ . filter ( |tx| tx. chain_position . is_unconfirmed ( ) ) ,
165+ ) ;
166+ spawn ( move || -> Result < ( ) , anyhow:: Error > {
167+ while let Some ( emission) = emitter. next_block ( ) ? {
168+ sender. send ( Emission :: Block ( emission) ) ?;
169+ }
170+ sender. send ( Emission :: Mempool ( emitter. mempool ( ) ?) ) ?;
171+ Ok ( ( ) )
172+ } ) ;
173+
174+ let mut blocks_received = 0_usize ;
175+ for emission in receiver {
176+ match emission {
177+ Emission :: SigTerm => {
178+ println ! ( "Sigterm received, exiting..." ) ;
179+ break ;
180+ }
181+ Emission :: Block ( block_emission) => {
182+ blocks_received += 1 ;
183+ let height = block_emission. block_height ( ) ;
184+ let hash = block_emission. block_hash ( ) ;
185+ let connected_to = block_emission. connected_to ( ) ;
186+ let start_apply_block = Instant :: now ( ) ;
187+ wallet. apply_block_connected_to ( & block_emission. block , height, connected_to) ?;
188+ wallet. persist_to_sqlite ( & mut db) ?;
189+ let elapsed = start_apply_block. elapsed ( ) . as_secs_f32 ( ) ;
190+ println ! ( "Applied block {hash} at height {height} in {elapsed}s" ) ;
191+ }
192+ Emission :: Mempool ( event) => {
193+ let start_apply_mempool = Instant :: now ( ) ;
194+ wallet. apply_evicted_txs ( event. evicted ) ;
195+ wallet. apply_unconfirmed_txs ( event. update ) ;
196+ wallet. persist_to_sqlite ( & mut db) ?;
197+ println ! (
198+ "Applied unconfirmed transactions in {}s" ,
199+ start_apply_mempool. elapsed( ) . as_secs_f32( )
200+ ) ;
201+ break ;
202+ }
203+ }
204+ }
205+ let wallet_tip_end = wallet. latest_checkpoint ( ) ;
206+ let balance = wallet. balance ( ) ;
207+ println ! (
208+ "Synced {} blocks in {}s" ,
209+ blocks_received,
210+ start_load_wallet. elapsed( ) . as_secs_f32( ) ,
211+ ) ;
212+ println ! (
213+ "Wallet tip is '{}:{}'" ,
214+ wallet_tip_end. height( ) ,
215+ wallet_tip_end. hash( )
216+ ) ;
217+ println ! ( "Wallet balance is {}" , balance. total( ) ) ;
218+ println ! (
219+ "Wallet has {} transactions and {} utxos" ,
220+ wallet. transactions( ) . count( ) ,
221+ wallet. list_unspent( ) . count( )
222+ ) ;
207223
208224 Ok ( ( ) )
209225}
0 commit comments