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