@@ -6,6 +6,7 @@ use lightning::chain::chaininterface::{
66 BroadcasterInterface , ConfirmationTarget , FeeEstimator , FEERATE_FLOOR_SATS_PER_KW ,
77} ;
88
9+ use lightning:: events:: bump_transaction:: { Utxo , WalletSource } ;
910use lightning:: ln:: msgs:: { DecodeError , UnsignedGossipMessage } ;
1011use lightning:: ln:: script:: ShutdownScript ;
1112use lightning:: sign:: {
@@ -21,10 +22,13 @@ use bdk::wallet::AddressIndex;
2122use bdk:: { FeeRate , SignOptions , SyncOptions } ;
2223
2324use bitcoin:: bech32:: u5;
25+ use bitcoin:: hashes:: Hash ;
2426use bitcoin:: secp256k1:: ecdh:: SharedSecret ;
2527use bitcoin:: secp256k1:: ecdsa:: { RecoverableSignature , Signature } ;
2628use bitcoin:: secp256k1:: { PublicKey , Scalar , Secp256k1 , Signing } ;
27- use bitcoin:: { LockTime , PackedLockTime , Script , Transaction , TxOut , Txid } ;
29+ use bitcoin:: util:: address:: WitnessVersion ;
30+ use bitcoin:: util:: psbt:: PartiallySignedTransaction ;
31+ use bitcoin:: { LockTime , PackedLockTime , Script , Transaction , TxOut , Txid , WPubkeyHash } ;
2832
2933use std:: collections:: HashMap ;
3034use std:: ops:: Deref ;
@@ -344,6 +348,100 @@ where
344348 }
345349}
346350
351+ impl < D , L : Deref > WalletSource for Wallet < D , L >
352+ where
353+ D : BatchDatabase ,
354+ L :: Target : Logger ,
355+ {
356+ fn list_confirmed_utxos ( & self ) -> Result < Vec < Utxo > , ( ) > {
357+ let locked_wallet = self . inner . lock ( ) . unwrap ( ) ;
358+ let mut utxos = Vec :: new ( ) ;
359+ let txs = locked_wallet. list_transactions ( true ) . map_err ( |e| {
360+ log_error ! ( self . logger, "Failed to retrieve transactions from wallet: {}" , e) ;
361+ } ) ?;
362+ let unspent = locked_wallet. list_unspent ( ) . map_err ( |e| {
363+ log_error ! ( self . logger, "Failed to retrieve unspent transactions from wallet: {}" , e) ;
364+ } ) ?;
365+
366+ for u in unspent {
367+ for t in & txs {
368+ if u. outpoint . txid == t. txid && t. confirmation_time . is_some ( ) {
369+ let payload =
370+ bitcoin:: util:: address:: Payload :: from_script ( & u. txout . script_pubkey )
371+ . map_err ( |e| {
372+ log_error ! ( self . logger, "Failed to retrieve script payload: {}" , e) ;
373+ } ) ?;
374+
375+ match payload {
376+ bitcoin:: util:: address:: Payload :: WitnessProgram { version, program } => {
377+ if version == WitnessVersion :: V0 && program. len ( ) == 20 {
378+ let wpkh = WPubkeyHash :: from_slice ( & program) . map_err ( |e| {
379+ log_error ! (
380+ self . logger,
381+ "Failed to retrieve script payload: {}" ,
382+ e
383+ ) ;
384+ } ) ?;
385+ let utxo = Utxo :: new_v0_p2wpkh ( u. outpoint , u. txout . value , & wpkh) ;
386+ utxos. push ( utxo) ;
387+ } else {
388+ log_error ! (
389+ self . logger,
390+ "Unexpected program length: {}" ,
391+ program. len( )
392+ ) ;
393+ }
394+ }
395+ _ => {
396+ log_error ! (
397+ self . logger,
398+ "Tried to use a non-witness script. This must never happen."
399+ ) ;
400+ panic ! ( "Tried to use a non-witness script. This must never happen." ) ;
401+ }
402+ }
403+ }
404+ }
405+ }
406+
407+ Ok ( utxos)
408+ }
409+
410+ fn get_change_script ( & self ) -> Result < Script , ( ) > {
411+ let locked_wallet = self . inner . lock ( ) . unwrap ( ) ;
412+ let address_info = locked_wallet. get_address ( AddressIndex :: New ) . map_err ( |e| {
413+ log_error ! ( self . logger, "Failed to retrieve new address from wallet: {}" , e) ;
414+ } ) ?;
415+
416+ Ok ( address_info. address . script_pubkey ( ) )
417+ }
418+
419+ fn sign_tx ( & self , tx : & mut Transaction ) -> Result < ( ) , ( ) > {
420+ let locked_wallet = self . inner . lock ( ) . unwrap ( ) ;
421+
422+ let mut psbt = PartiallySignedTransaction :: from_unsigned_tx ( tx. clone ( ) ) . map_err ( |e| {
423+ log_error ! ( self . logger, "Failed to create PSBT: {}" , e) ;
424+ } ) ?;
425+
426+ match locked_wallet. sign ( & mut psbt, SignOptions :: default ( ) ) {
427+ Ok ( finalized) => {
428+ if !finalized {
429+ log_error ! ( self . logger, "Failed to finalize PSBT." ) ;
430+ return Err ( ( ) ) ;
431+ }
432+ }
433+ Err ( err) => {
434+ log_error ! ( self . logger, "Failed to sign transaction: {}" , err) ;
435+ return Err ( ( ) ) ;
436+ }
437+ }
438+
439+ * tx = psbt. extract_tx ( ) ;
440+
441+ Ok ( ( ) )
442+ }
443+ }
444+
347445/// Similar to [`KeysManager`], but overrides the destination and shutdown scripts so they are
348446/// directly spendable by the BDK wallet.
349447pub struct WalletKeysManager < D , L : Deref >
0 commit comments