@@ -184,6 +184,55 @@ impl fmt::Display for AddressInfo {
184184/// A `CanonicalTx` managed by a `Wallet`.
185185pub type WalletTx < ' a > = CanonicalTx < ' a , Arc < Transaction > , ConfirmationBlockTime > ;
186186
187+ /// The finalization status for a single PSBT input.
188+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
189+ pub enum FinalizePsbtInputResult {
190+ /// The input was already finalized before this call.
191+ AlreadyFinalized ,
192+ /// The input was successfully finalized during this call.
193+ Finalized ,
194+ /// The wallet could not derive a descriptor for the input.
195+ MissingDescriptor ,
196+ /// The wallet found the descriptor but could not construct the input satisfaction.
197+ CouldNotSatisfy ,
198+ }
199+
200+ impl FinalizePsbtInputResult {
201+ /// Whether the input is finalized after this call.
202+ pub fn is_finalized ( & self ) -> bool {
203+ matches ! ( self , Self :: AlreadyFinalized | Self :: Finalized )
204+ }
205+ }
206+
207+ /// Holds per-input PSBT finalization results.
208+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
209+ pub struct FinalizePsbtResult {
210+ results : BTreeMap < usize , FinalizePsbtInputResult > ,
211+ }
212+
213+ impl FinalizePsbtResult {
214+ fn new ( results : BTreeMap < usize , FinalizePsbtInputResult > ) -> Self {
215+ Self { results }
216+ }
217+
218+ /// Whether all inputs are finalized after this call.
219+ pub fn is_finalized ( & self ) -> bool {
220+ self . results
221+ . values ( )
222+ . all ( FinalizePsbtInputResult :: is_finalized)
223+ }
224+
225+ /// Borrow the per-input finalization results.
226+ pub fn results ( & self ) -> & BTreeMap < usize , FinalizePsbtInputResult > {
227+ & self . results
228+ }
229+
230+ /// Consume the result and return the per-input finalization results.
231+ pub fn into_results ( self ) -> BTreeMap < usize , FinalizePsbtInputResult > {
232+ self . results
233+ }
234+ }
235+
187236impl Wallet {
188237 /// Build a new single descriptor [`Wallet`].
189238 ///
@@ -1842,6 +1891,19 @@ impl Wallet {
18421891 psbt : & mut Psbt ,
18431892 sign_options : SignOptions ,
18441893 ) -> Result < bool , SignerError > {
1894+ Ok ( self . try_finalize_psbt ( psbt, sign_options) ?. is_finalized ( ) )
1895+ }
1896+
1897+ /// Finalize a PSBT and return per-input finalization results. Use this method when you need to
1898+ /// inspect why a specific input could not be finalized.
1899+ ///
1900+ /// The method should only return `Err` when the PSBT is malformed, for example if its inputs
1901+ /// are out of bounds.
1902+ pub fn try_finalize_psbt (
1903+ & self ,
1904+ psbt : & mut Psbt ,
1905+ sign_options : SignOptions ,
1906+ ) -> Result < FinalizePsbtResult , SignerError > {
18451907 let tx = & psbt. unsigned_tx ;
18461908 let chain_tip = self . chain . tip ( ) . block_id ( ) ;
18471909 let prev_txids = tx
@@ -1867,14 +1929,15 @@ impl Wallet {
18671929 } )
18681930 . collect :: < HashMap < Txid , u32 > > ( ) ;
18691931
1870- let mut finished = true ;
1932+ let mut results = BTreeMap :: new ( ) ;
18711933
18721934 for ( n, input) in tx. input . iter ( ) . enumerate ( ) {
18731935 let psbt_input = & psbt
18741936 . inputs
18751937 . get ( n)
18761938 . ok_or ( IndexOutOfBoundsError :: new ( n, psbt. inputs . len ( ) ) ) ?;
18771939 if psbt_input. final_script_sig . is_some ( ) || psbt_input. final_script_witness . is_some ( ) {
1940+ results. insert ( n, FinalizePsbtInputResult :: AlreadyFinalized ) ;
18781941 continue ;
18791942 }
18801943 let confirmation_height = confirmation_heights
@@ -1927,23 +1990,29 @@ impl Wallet {
19271990 if !tmp_input. witness . is_empty ( ) {
19281991 psbt_input. final_script_witness = Some ( tmp_input. witness ) ;
19291992 }
1993+ results. insert ( n, FinalizePsbtInputResult :: Finalized ) ;
1994+ }
1995+ Err ( _) => {
1996+ results. insert ( n, FinalizePsbtInputResult :: CouldNotSatisfy ) ;
19301997 }
1931- Err ( _) => finished = false ,
19321998 }
19331999 }
1934- None => finished = false ,
2000+ None => {
2001+ results. insert ( n, FinalizePsbtInputResult :: MissingDescriptor ) ;
2002+ }
19352003 }
19362004 }
19372005
19382006 // Clear derivation paths from outputs.
1939- if finished {
2007+ let finalized = FinalizePsbtResult :: new ( results) ;
2008+ if finalized. is_finalized ( ) {
19402009 for output in & mut psbt. outputs {
19412010 output. bip32_derivation . clear ( ) ;
19422011 output. tap_key_origins . clear ( ) ;
19432012 }
19442013 }
19452014
1946- Ok ( finished )
2015+ Ok ( finalized )
19472016 }
19482017
19492018 /// Return the secp256k1 context used for all signing operations.
0 commit comments