@@ -4,6 +4,7 @@ use crate::Error;
44
55use lightning:: chain:: chaininterface:: { BroadcasterInterface , ConfirmationTarget , FeeEstimator } ;
66
7+ use lightning:: events:: bump_transaction:: { Utxo , WalletSource } ;
78use lightning:: ln:: msgs:: { DecodeError , UnsignedGossipMessage } ;
89use lightning:: ln:: script:: ShutdownScript ;
910use lightning:: sign:: {
@@ -19,8 +20,12 @@ use bdk::wallet::AddressIndex;
1920use bdk:: FeeRate ;
2021use bdk:: { SignOptions , SyncOptions } ;
2122
23+ use bitcoin:: address:: { Payload , WitnessVersion } ;
2224use bitcoin:: bech32:: u5;
2325use bitcoin:: blockdata:: locktime:: absolute:: LockTime ;
26+ use bitcoin:: hash_types:: WPubkeyHash ;
27+ use bitcoin:: hashes:: Hash ;
28+ use bitcoin:: psbt:: PartiallySignedTransaction ;
2429use bitcoin:: secp256k1:: ecdh:: SharedSecret ;
2530use bitcoin:: secp256k1:: ecdsa:: { RecoverableSignature , Signature } ;
2631use bitcoin:: secp256k1:: { PublicKey , Scalar , Secp256k1 , Signing } ;
@@ -245,6 +250,97 @@ where
245250 }
246251}
247252
253+ impl < D , B : Deref , E : Deref , L : Deref > WalletSource for Wallet < D , B , E , L >
254+ where
255+ D : BatchDatabase ,
256+ B :: Target : BroadcasterInterface ,
257+ E :: Target : FeeEstimator ,
258+ L :: Target : Logger ,
259+ {
260+ fn list_confirmed_utxos ( & self ) -> Result < Vec < Utxo > , ( ) > {
261+ let locked_wallet = self . inner . lock ( ) . unwrap ( ) ;
262+ let mut utxos = Vec :: new ( ) ;
263+ let txs = locked_wallet. list_transactions ( true ) . map_err ( |e| {
264+ log_error ! ( self . logger, "Failed to retrieve transactions from wallet: {}" , e) ;
265+ } ) ?;
266+ let unspent = locked_wallet. list_unspent ( ) . map_err ( |e| {
267+ log_error ! ( self . logger, "Failed to retrieve unspent transactions from wallet: {}" , e) ;
268+ } ) ?;
269+
270+ for u in unspent {
271+ for t in & txs {
272+ if u. outpoint . txid == t. txid && t. confirmation_time . is_some ( ) {
273+ let payload = Payload :: from_script ( & u. txout . script_pubkey ) . map_err ( |e| {
274+ log_error ! ( self . logger, "Failed to retrieve script payload: {}" , e) ;
275+ } ) ?;
276+
277+ match payload {
278+ Payload :: WitnessProgram ( program) => {
279+ if program. version ( ) == WitnessVersion :: V0
280+ && program. program ( ) . len ( ) == 20
281+ {
282+ let wpkh = WPubkeyHash :: from_slice ( program. program ( ) . as_bytes ( ) )
283+ . map_err ( |e| {
284+ log_error ! (
285+ self . logger,
286+ "Failed to retrieve script payload: {}" ,
287+ e
288+ ) ;
289+ } ) ?;
290+ let utxo = Utxo :: new_v0_p2wpkh ( u. outpoint , u. txout . value , & wpkh) ;
291+ utxos. push ( utxo) ;
292+ } else {
293+ log_error ! (
294+ self . logger,
295+ "Unexpected program length: {}" ,
296+ program. program( ) . len( )
297+ ) ;
298+ }
299+ }
300+ _ => {
301+ log_error ! (
302+ self . logger,
303+ "Tried to use a non-witness script. This must never happen."
304+ ) ;
305+ panic ! ( "Tried to use a non-witness script. This must never happen." ) ;
306+ }
307+ }
308+ }
309+ }
310+ }
311+
312+ Ok ( utxos)
313+ }
314+
315+ fn get_change_script ( & self ) -> Result < ScriptBuf , ( ) > {
316+ let locked_wallet = self . inner . lock ( ) . unwrap ( ) ;
317+ let address_info = locked_wallet. get_address ( AddressIndex :: New ) . map_err ( |e| {
318+ log_error ! ( self . logger, "Failed to retrieve new address from wallet: {}" , e) ;
319+ } ) ?;
320+
321+ Ok ( address_info. address . script_pubkey ( ) )
322+ }
323+
324+ fn sign_psbt ( & self , mut psbt : PartiallySignedTransaction ) -> Result < Transaction , ( ) > {
325+ let locked_wallet = self . inner . lock ( ) . unwrap ( ) ;
326+
327+ match locked_wallet. sign ( & mut psbt, SignOptions :: default ( ) ) {
328+ Ok ( finalized) => {
329+ if !finalized {
330+ log_error ! ( self . logger, "Failed to finalize PSBT." ) ;
331+ return Err ( ( ) ) ;
332+ }
333+ }
334+ Err ( err) => {
335+ log_error ! ( self . logger, "Failed to sign transaction: {}" , err) ;
336+ return Err ( ( ) ) ;
337+ }
338+ }
339+
340+ Ok ( psbt. extract_tx ( ) )
341+ }
342+ }
343+
248344/// Similar to [`KeysManager`], but overrides the destination and shutdown scripts so they are
249345/// directly spendable by the BDK wallet.
250346pub struct WalletKeysManager < D , B : Deref , E : Deref , L : Deref >
@@ -398,11 +494,10 @@ where
398494 } ) ?;
399495
400496 match address. payload {
401- bitcoin :: address :: Payload :: WitnessProgram ( program) => {
402- ShutdownScript :: new_witness_program ( & program ) . map_err ( |e| {
497+ Payload :: WitnessProgram ( program) => ShutdownScript :: new_witness_program ( & program )
498+ . map_err ( |e| {
403499 log_error ! ( self . logger, "Invalid shutdown script: {:?}" , e) ;
404- } )
405- }
500+ } ) ,
406501 _ => {
407502 log_error ! (
408503 self . logger,
0 commit comments